Python For Django Programmers – Part 3

By big-nige | tutorials

Jun 18

In this final introductory tutorial on Python for Django programmers, I will be explaining how to catch errors with Python, discussing functions and classes in Python, explaining how packages, modules and the dot operator work in Python and finishing with a brief explanation of how regular expressions work in Python and Django.

This tutorial is an extract from my new book – Build Your First Website with Python and Django.

Catching Errors

Lets say you have a simple function where you have to take the answer from a previous operation and divide it by 5:

ans = answer/5
print("Answer divided by 5 is", ans)

Seems straight forward, let’s try that out at the Python prompt:

>>> answer = 3
>>> ans = answer/5
>>> print("Answer divided by 5 is", ans)
Answer divided by 5 is 0.6
>>>

So far, so good – but what if, instead of getting an integer, our function got handed a string? Let’s try that again in Python:

>>> answer = "3"
>>> ans = 5/answer
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'int' and 'str'

Oops! You will note that you didn’t even get to enter the final print() statement before Python threw an error. If this happened in the middle of an important part of your code, it could crash your program with potentially disastrous results.

Luckily, Python provides an easy, but robust way of handling errors within your code with the tryexcept statement:

try:
    # Try this piece of code
except:
    # If the code throws an error, execute this bit of code.

Let’s try that now with our previous example:

>>> answer = 3
>>> try:
...     ans = answer/5      # Python will try to execute this statement
...     print("Answer divided by 5 is", ans)
... except:
...     print("something went wrong")
...
Answer divided by 5 is 0.6  # In this case, all is ok and we get the expected output

>>> answer = "3"
>>> try:
...     ans = answer/5      # Passing in a string will throw an error
...     print("Answer divided by 5 is", ans)
... except:
...     print("something went wrong")
...
something went wrong        # Python captures the error and let's
                            # us know without crashing the program
>>>

This code is better, but we still have no idea what caused the error. Lucky for us, Python also captures the type of error. If you look closely at the first bit of code that threw the error, you will see this line:

    TypeError: unsupported operand type(s) for /: 'int' and 'str'

In this case, Python is telling us that the bad input is throwing a TypeError. So let’s modify the code to make it a bit more descriptive:

>>> answer = "3"
>>> try:
...     ans = answer/5
...     print("Answer divided by 5 is", ans)
... except TypeError:
...     print("Type Error. Answer must be an integer.")
...
Type Error. Answer must be an integer.
>>>

This is only a very basic example of error handling. It’s also incomplete (the code above will still crash if answer is zero), however more complex implementations of the tryexcept statement build on these fundamentals.

For more on the tryexcept statement, see Errors and Exceptions in the Python documentation. You can also find a comprehensive list of Built in Exceptions in the Python docs.

Classes and Functions

The basic purpose of classes and functions is to group together pieces of related code. The major difference between the two is that a function does something, whereas a class is something. So, for example, if Person was a class, walk() and eat() would be functions.

Both classes and functions can contain other functions. If a function is inside another function, it’s called a sub-function. If a function is included inside a class it’s called a method. Subclasses also exist, but they are created by a process called inheritance. We will get to inheritance in just a bit.

To define a function in Python you use the def statement:

def function_name([parameter list]):
    # rest of function

To define a class in Python, you use the class statement:

class Someclass([argument list]):
    # class constructor
    __init__():
        # Constructor code
    # class methods
    def ...

You create subclasses that contain all of the attributes and methods of another class using inheritance. Inheritance is an important concept in object-oriented programming. Inheritance helps prevent repetition in code, and it allows programmers to build complex programs from simpler building blocks.

To create a class that inherits from another class, you refer to the parent when defining the class:

class ChildClass(ParentClass):

This is easier to understand with an example – a simple Django form class:

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    email = forms.EmailField(required=False)
    message = forms.CharField(widget=forms.Textarea)

In this example, the class is inheriting from Django’s forms.Form class, which make all of the methods and attributes of the parent class (forms.Form) available in the child class (subclass) ContactForm.

Packages, Modules and the Dot Operator

To clearly organize large projects into logical units, Python structures code into modules and packages.

A module is the base unit of Python’s program structure. A module is a file with a .py extension that contains all of the functions, classes and definitions pertaining to that module.

A package is a collection of modules, all saved inside a package folder. The package folder must contain a file called __init__.py for Python to be able to identify the folder as a package.

Let’s have a look at the Django project we created in the last chapter to see packages and modules in action:

\mfdw_site
__init__.py     # This tells Python that mfdw_site is a package
settings.py     # The settings module for our project
urls.py         # The urls module for our project
# ...

The Dot Operator

Dot notation is a common idiom in object-oriented programming. I like to think of the dot like a point, because the dot points to something. In the case of Python, the dot operator points to the next object in the object chain. In Django classes, the object chain is like this:

package.module.class.method

Or in the case of functions:

package.module.function.attribute

Some real-life examples:

  • forms.Form points to the Form class in the forms package
  • pages.apps.PagesConfig points to the PagesConfig class in the apps subpackage of the pages package
  • django.conf.urls points to the urls package inside the conf package inside django which is also a Python package!

This can sometimes get a bit confusing, but if you remember to join the dots (sorry, bad pun there), you can usually find out what the dot operator is referring to.

Regular Expressions

While not strictly a Python topic, it’s important to introduce regular expressions (or regexes) as they are used extensively by Django – especially in URL configuration files (URLconfs). While Django URLconfs allow arbitrary regexes for powerful URL matching,¬†you’ll probably only use a few regex symbols in practice. Table 5-1 lists a selection of common symbols.

Table 5-1: Common regex symbols

Symbol Matches
. (dot) Any single character
\d Any single digit
[A-Z] Any character between A and Z (uppercase)
[a-z] Any character between a and z (lowercase)
[A-Za-z] Any character between a and z (case-insensitive)
+ One or more of the previous expression (e.g., \d+ matches one or more digits)
[^/]+ One or more characters until (and not including) a forward slash
? Zero or one of the previous expression (e.g., \d? matches zero or one digits)
* Zero or more of the previous expression (e.g., \d* matches zero, one or more than one digit)
{1,3} Between one and three (inclusive) of the previous expression (e.g., \d{1,3} matches one, two or three digits)
(...) Matches whatever regular expression is inside the parentheses, and indicates the start and end of a group

For more on regular expressions, see the Python regex documentation.