Setting up our Django Project

This entry is part 2 of 2 in the series Django Web App

In order to start developing our Django app, I’m going to help you begin by using Python best practices which includes setting up a virtual environment for this version of Python and this project’s requirements.  With virtualenvwrapper installed, run mkvirtualenv drecipes.  This will create a separate, isolated Python environment so you can continue using a different Python version on other projects as well as different versions of libraries.  For example, when I develop with older versions of Django and Python on some projects, virtualenv allows me to keep the two projects separate while still being compatible with each production environment.

Each time you want to develop for the drecipes project, you’ll run workon drecipes in order to activate this environment.

Create a requirements.txt file in your project directory.  Add these two lines to it:

Django==1.7.6
mysqlclient==1.3.6

Next, run pip install -r requirements.txt.  This will take the 2 requirements from our file and install them so they are ready to use.

With Django installed, run django-admin.py startproject drecipes.  This will create the initial Django project structure that looks similar to this:

your_project_folder/
    manage.py
    drecipes/
        __init__.py
        settings.py
        urls.py
        wsgi.py
    requirements.txt

In order to connect to our database, modify the settings.py file as follows:

DATABASES = {
     'default': {
-        'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': 'drecipes_codecrawl',
+        'USER': 'root',
+        'PASSWORD': 'Ma12sona',
+        'HOST': '127.0.0.1',
     }
 }

NAME should be your database name, USER is the database user you create.  It is never a good idea to run a database as root, but since I’m only doing this locally, I am not concerned with a security issue.  The same goes for the PASSWORD not being encrypted or at least not stored directly in version control.  Normally, I store all of these in environment variables that can differ based on host, like test, stage, and production may all have different settings.

Then run python manage.py migrate as follows:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying sessions.0001_initial... OK

We’re not going to use the built in Django admin, so you can remove the admin lines from drecipes/urls.py, but you don’t have to.  I always do when my app is in production, and I’m not using it.

You should now be able to run python manage.py runserver to see site on localhost:8000 (see screenshot).

Initial Django app running

Django – Starting to Build a Web App using Django

This entry is part 1 of 2 in the series Django Web App

I’m going to try to keep this series focused on building a web app using Django and related technologies, so I’ll often skip over extraneous install help, especially on multiple operating systems.  Things like virtualenv, virtualenvwrapper, and database libraries can be particularly problematic on Windows and sometimes Mac, so I’ll leave any detail install/setup help for stackoverflow.  I am developing on Mac, but I have developed Django apps on Windows and Linux also, so I am familiar with all sorts of issues installing and running Python apps, if you end up needing help.

To start with, I’m going to provide a list of core development tools, libraries, and programs that help facilitate web development, especially in Python.  These will all make developing web apps easier in their own way.

  1. Python – I’m using Python 3.4.3 on a Mac
    $ python -V
    Python 3.4.3
  2. pip – The recommended tool to install Python packages/dependencies
  3. virtualenvwrapper – (Optional) Install using pip.  This is used to manage different Python projects that require different dependencies or versions of the same dependencies.
  4. A database – You can use SQLite which is built into Python.  I am going to use MySQL so I can utilize phpMyAdmin to display tables and their data.  Typically, I would use either MySQL or PostgreSQL, as of late I’ve become more accustomed to Postgres.  As you’ll see when we start creating the data models for our app, the database doesn’t matter for this example due to Django’s use of an ORM, which I’ll explain in more detail at a later time.
  5. Bootstrap – CSS for basic design and JavaScript functionality.

So aside from the libraries we’ll need, including Django, these are going to be our core dependencies to start building the Django web application.

A brief screencast of the web app we’ll build \/.

Next post, I’ll go over the initial Django project setup and creating some basic functionality.

Python Classes and OOP

This entry is part 8 of 8 in the series Python

So we’re back to the example I left in the last lesson:

# bank.py
class Person(object):
    """This is the base class that represents
    a Person
    """
    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age

    def get_full_name(self):
        return self.first_name +' '+ self.last_name

class Employee(Person):
    """Since an employee is a Person, we indicate
    that we are a Person by declaring
    class Employee(Person):
    The item inside of () shows we inherit from
    Person
    """
    def __init__(self, fname, lname, age, salary, manager):
        Person.__init__(self, first_name=fname, last_name=lname, age=age)
        self.salary = salary
        self.manager = manager

    def get_manager_salary(self):
        return self.manager.salary

    def is_owner(self):
        return True if self.manager is not None else False

class Customer(Person):
    """A Customer is also a Person
    which means we also have a first and last name
    as well as an age
    """
    def __init__(self, first_name, last_name, age, bank_account):
        Person.__init__(self, first_name, last_name, age=age)
        self.bank_account = bank_account

    def get_account_balance(self):
        return self.bank_account.balance

    def deposit(self, amount):
        # We return the new account balance
        return self.bank_account.increase_cash(amount)

    def spend(self, amount):
        return self.bank_account.decrease_cash(amount)

class BankAccount(object):
    """A class that represents a bank
    account
    """
    def __init__(self, balance, manager):
        self.balance = balance
        self.manager = manager

    def decrease_cash(self, spent_money):
        self.balance -= spent_money
        return self.balance

    def increase_cash(self, money):
        self.balance += money
        return self.balance

if __name__ == '__main__':
    bank_manager = Employee('Scrooge', 'McMuffins', salary=1000000, age=99, manager=None)
    rich_bank_account = BankAccount(1000, bank_manager)
    rich_customer = Customer('Rich', 'Person', age=205, bank_account=rich_bank_account)

    print 'The bank manager for your bank is %s'%(bank_manager.get_full_name())
    print 'Your account has $%d in it'%(rich_bank_account.balance)

    interest_payment = 2500
    print '%s\'s account earns $%d of interest'%(rich_customer.get_full_name(), interest_payment)
    new_balance = rich_bank_account.increase_cash(interest_payment)
    print '%s\'s new balance is $%d'%(rich_customer.get_full_name(), new_balance)
    print '%s\'s age is %d years old'%(rich_customer.get_full_name(), rich_customer.age)

    print '%s spends a little money'%(rich_customer.get_full_name())
    rich_customer.spend(100)
    print '%s now has $%d'%(rich_customer.get_full_name(), rich_customer.get_account_balance())

    # He has the same mean bank manager as the rich person!
    poor_account = BankAccount(10, manager=bank_manager)
    poor_customer = Customer('Poor', 'Person', 105, poor_account)

    print '%s starts with $%d'%(poor_customer.get_full_name(), poor_account.balance)
    print '%s steals money from %s'%(bank_manager.get_full_name(), poor_customer.get_full_name())
    poor_account.decrease_cash(5)
    print '%s now only has $%d'%(poor_customer.get_full_name(), poor_customer.get_account_balance())

Here I’m going to explain each part in detail, enough detail that you’ll hopefully be able to follow along and understand what classes are used for and how to use them.

Let’s first get some basic terminology out of the way.  Class is simply the blueprint of an object, where a class is the code that describes how an object should behave, and an object is a single instance.

# person.py
from bank import Person

zach = Person('Zach', 'Hilbert', 109)
slim = Person('Slim', 'Jim', 25)

# zach is an instance of a Person
print 'My name is ', zach.get_full_name()
print 'But his name is', slim.get_full_name()

Here is an example using Person from bank.py.  The first line of code: from bank import Person, simply says, from the bank module (ie. bank.py), import the Person class.  Then we use Person to create zach.  zach is an instance of Person.  slim is also an instance of Person.  Each instance of person has the ability to utilize the methods of Person (functions of class).

class Person(object):
    """This is the base class that represents
    a Person
    """
    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age

    def get_full_name(self):
        return self.first_name +' '+ self.last_name

In the Person class, we have 2 methods, __init__ and get_full_name.  get_full_name provides us a simple way to concatenate a person’s first and last names without having to write this every time we want their name.  The __init__ method is called a constructor, because it is what is called when you construct an instance of the class Person.

When we call zach = Person(‘Zach’, ‘Hilbert’, 109), Person() is instantiating the Person class and assigning the object to zach, which is an instance of Person.  When you call Person(‘Zach’, ‘Hilbert’, 109), __init__ gets called with ‘Zach’ as first_name, ‘Hilbert’ as last_name, and 109 as age.  For each method in a class, self is also passed in as a reference to the current object, so anytime you call self.<method/property>, it calls the data from that instance.  You can see this with zach and slim.  In zachself.first_name contains ‘Zach’, but slim contains ‘Slim’ for self.first_name.

The constructor of a class allows us to set necessary properties up front that may be use later.  All other methods can be created for use as necessary.  Employee and Customer inherit from Person, because they are people too, but both Employee and Customer have different properties and implementations.  Employee has a salary and a manager, who happens to be another employee, and Customer has a bank account which is a class itself.

These classes allow us to represent real-world objects that we might need to manipulate and represent in an application.  You can create as many people, employees, customers, and bank accounts as you want/need (as long as you have enough memory).

Often times you will have a database that saves information for each of these, and when you have customer ‘zach’ log into your application, your code gets zach’s information and bank account information and instantiates their respective classes to work with the zach object.  You might have lots of these objects and they can interact with each other as you need.

The exact implementation isn’t important here.  What is important is to understand that classes and objects help developers create applications that mimic real-world scenarios, and this is how many applications are built and used.

Beneath all of the classes you can see the use of each class and how each instance contains is own, separate data, as well as how these classes might be used to create a basic program.

Now that we have some of this more foundational material out of the way, I’ll focus more time on showing more realistic examples and implementations.

Python Objects (or a Bike and a Wheel)

This entry is part 7 of 8 in the series Python

When I first tried to teach myself programming, I bought a Java book that started teaching object-oriented programming (OOP) by describing an object (a bicycle), which had properties (wheels, pedals, etc), and state (moving or stopped).  I said whaah?!  Why am I learning about a bike and whether it’s moving or not.

Needless to say, I was completely befuddled and had no idea what I was doing or how to relate this bike concept.  Funny enough, a handful of years later a co-worker of mine described programming in almost exactly the same way.  It made as much of no sense as it did the first time.

The point in this initial ramble of mine is to promise you I won’t try to explain programming and OOP by using your first grade tricycle.

I like to think of OOP as a useful way to combine similar sets of code/logic so you can use it over and over without rewriting it.  From How To Become A Hacker (not the breaking into things type, but hacker as in building killer software), Eric S. Raymond writes:

Hackers (and creative people in general) should never be bored or have to drudge at stupid repetitive work, because when this happens it means they aren’t doing what only they can do — solve new problems. This wastefulness hurts everybody. Therefore boredom and drudgery are not just unpleasant but actually evil.

 

 

To behave like a hacker, you have to believe this enough to want to automate away the boring bits as much as possible, not just for yourself but for everybody else (especially other hackers).

OOP is useful so you don’t have to write the same thing, over and over again.  The example I like to use is writing a banking application.  First I’ll briefly explain a core part of DRY (Don’t Repeat Yourself) as functions.  If you have a for loop where you perform the same logic over a list, you can separate that logic into a function so you only write it once, but you can call it as many times as you need.

"""We're going to print abreviated titles
from a list of titles
"""
def short_title(title):
    new_title = ''
    if len(title) > 20: 
        new_title = title[:21]+'...'
    else:
        new_title = title

    return new_title

titles = [ 
    'Here is Title 1',
    'Title 2', 
    "A longer title that won't fit.",
    'Something a bit longer than we want'
]

for title in titles:
    print short_title(title)

To declare a function, we use the keyword def to declare (or define) a function.  title in def short_title(title): is a parameter that is passed into this function, which we use later to create a short title.  The gist of short_title is to return an abbreviated title if it’s longer than 20 characters.  Don’t worry too much about the details, just try to understand that the short_title function allows us to repeat creating an abbreviated title and use it anywhere else we need it.

The output, in case you were curious:

$ python function.py 
Here is Title 1
Title 2
A longer title that w...
Something a bit longe...

Next lesson we’ll go over the following code about the rich, poor, and greedy:

# bank.py
class Person(object):
    """This is the base class that represents
    a Person
    """
    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age

    def get_full_name(self):
        return self.first_name +' '+ self.last_name

class Employee(Person):
    """Since an employee is a Person, we indicate
    that we are a Person by declaring
    class Employee(Person):
    The item inside of () shows we inherit from
    Person
    """
    def __init__(self, fname, lname, age, salary, manager):
        Person.__init__(self, first_name=fname, last_name=lname, age=age)
        self.salary = salary
        self.manager = manager

    def get_manager_salary(self):
        return self.manager.salary

    def is_owner(self):
        return True if self.manager is not None else False

class Customer(Person):
    """A Customer is also a Person
    which means we also have a first and last name
    as well as an age
    """
    def __init__(self, first_name, last_name, age, bank_account):
        Person.__init__(self, first_name, last_name, age=age)
        self.bank_account = bank_account

    def get_account_balance(self):
        return self.bank_account.balance

    def deposit(self, amount):
        # We return the new account balance
        return self.bank_account.increase_cash(amount)

    def spend(self, amount):
        return self.bank_account.decrease_cash(amount)

class BankAccount(object):
    """A class that represents a bank
    account
    """
    def __init__(self, balance, manager):
        self.balance = balance
        self.manager = manager

    def decrease_cash(self, spent_money):
        self.balance -= spent_money
        return self.balance

    def increase_cash(self, money):
        self.balance += money
        return self.balance

bank_manager = Employee('Scrooge', 'McMuffins', salary=1000000, age=99, manager=None)
rich_bank_account = BankAccount(1000, bank_manager)
rich_customer = Customer('Rich', 'Person', age=205, bank_account=rich_bank_account)

print 'The bank manager for your bank is %s'%(bank_manager.get_full_name())
print 'Your account has $%d in it'%(rich_bank_account.balance)

interest_payment = 2500
print '%s\'s account earns $%d of interest'%(rich_customer.get_full_name(), interest_payment)
new_balance = rich_bank_account.increase_cash(interest_payment)
print '%s\'s new balance is $%d'%(rich_customer.get_full_name(), new_balance)
print '%s\'s age is %d years old'%(rich_customer.get_full_name(), rich_customer.age)

print '%s spends a little money'%(rich_customer.get_full_name())
rich_customer.spend(100)
print '%s now has $%d'%(rich_customer.get_full_name(), rich_customer.get_account_balance())

# He has the same mean bank manager as the rich person!
poor_account = BankAccount(10, manager=bank_manager)
poor_customer = Customer('Poor', 'Person', 105, poor_account)

print '%s starts with $%d'%(poor_customer.get_full_name(), poor_account.balance)
print '%s steals money from %s'%(bank_manager.get_full_name(), poor_customer.get_full_name())
poor_account.decrease_cash(5)
print '%s now only has $%d'%(poor_customer.get_full_name(), poor_customer.get_account_balance())

The output for this code is below:

$ python bank.py 
The bank manager for your bank is Scrooge McMuffins
Your account has $1000 in it
Rich Person's account earns $2500 of interest
Rich Person's new balance is $3500
Rich Person's age is 205 years old
Rich Person spends a little money
Rich Person now has $3400
Poor Person starts with $10
Scrooge McMuffins steals money from Poor Person
Poor Person now only has $5

Can you piece it together before we talk about it?  Comment below with any thoughts….

@codecrawl
@zachhilbert

Becoming a Python Grown-Up

This entry is part 6 of 8 in the series Python

These Python lessons have been moving fairly quickly, and that’s primarily because of all the other great lessons on the rest of site.  Once you learn to develop code in a language, it’s relatively simple to move on to learn a new language.  I’m assuming that new language for you, is Python.

Since we have touched on variables, basic data structures, and for loops, I want to finish up some of the core basics by going over while loops and conditional statements.

The code we’re going to work with is below:

wallet_money = 150 
# We're going to invest in penny stocks
# that cost a lot more than a penny
while wallet_money > 0:
    invest_amount = 0 
    # Checking if we should give up the rest
    if wallet_money <= 15: 
        # Invest all our money in pennies
        invest_amount = wallet_money
        wallet_money = 0
    else:
        # Invest 25% in pennies
        invest_amount = .25 * wallet_money
        wallet_money -= invest_amount
    print "Investing $%d" % (invest_amount)
    print "$%d left after losing on pennies" % (wallet_money)

print 'We squandered our savings on penny stocks!'

In order to follow this code, we have to acknowledge the elephant in the code block….we don’t have brackets!  Instead of using brackets to distinguish logic blocks, Python uses indentation, so formatting becomes the lifeblood of a successfully running python program.

Indentation needs to be consistent, ie. keep using tabs if you start with tabs, or keep using 2 spaces if you start with 2 spaces.

wallet_money = 150 
# We're going to invest in penny stocks
# that cost a lot more than a penny
while wallet_money > 0:
    invest_amount = 0
    ...stuff...

Here we start with $150 and a while statement.  While statements say “while <test is true>: do stuff.”  In our case, we say “while our wallet money hasn’t run out, invest, over, and over, and over….”  The ‘:’ colon after the test indicates that logic within this statement is to follow.

invest_amount = 0 
# Checking if we should give up the rest
if wallet_money <= 15: 
    # Invest all our money in pennies
    invest_amount = wallet_money
    wallet_money = 0
else:
    # Invest 25% in pennies
    invest_amount = .25 * wallet_money
    wallet_money -= invest_amount
print "Investing $%d" % (invest_amount)
print "$%d left after losing on pennies" % (wallet_money)

While we have money in our wallet, we first check to see how much we have left.

# Checking if we should give up the rest
if wallet_money <= 15: 
    # Invest all our money in pennies
    invest_amount = wallet_money
    wallet_money = 0

Because our money amount changes each time we invest, this if is called a conditional statement, meaning the logic is subject to change depending on the condition of our check.  If we have $15 or less, then we invest the rest of our money.

else:
    # Invest 25% in pennies
    invest_amount = .25 * wallet_money
    wallet_money -= invest_amount

Here, else is exactly what it sounds like, if we have $15 or less, then invest everything, else invest 25% of the remaining money.  This is called an if/else construct.  We can also have if/elif/elif/else, etc. where elif has another check each time for something different.

One thing to note here is the wallet_money -= invest_amount line.  This is the same as saying wallet_money = wallet_money – invest_amount, but in a more concise way.

Finally we print the investment amount and remaining amounts each time the loop runs, and we end up broke again by trusting in the stock market of pennies.  These print statements should look familiar.

I saved my file as penny_stocks.py which can be run using the command python penny_stocks.py.  You can see the output of this script below:

$ python penny_stocks.py 
Investing $37
$112 left after losing on pennies
Investing $28
$84 left after losing on pennies
Investing $21
$63 left after losing on pennies
Investing $15
$47 left after losing on pennies
Investing $11
$35 left after losing on pennies
Investing $8
$26 left after losing on pennies
Investing $6
$20 left after losing on pennies
Investing $5
$15 left after losing on pennies
Investing $3
$11 left after losing on pennies
Investing $11
$0 left after losing on pennies
We squandered our savings on penny stocks!

After this, you should be pretty close to becoming a Python professional, ready to write all sorts of applications!