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.
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
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
except statement build on these fundamentals.
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,
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 function_name([parameter list]): # rest of function
To define a class in Python, you use the
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:
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)
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 # ...
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:
Or in the case of functions:
Some real-life examples:
forms.Formpoints to the
Formclass in the
pages.apps.PagesConfigpoints to the
PagesConfigclass in the
appssubpackage of the
django.conf.urlspoints to the
urlspackage inside the
djangowhich is also a
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.
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
||Any single character|
||Any single digit|
||Any character between
||Any character between
||Any character between
||One or more of the previous expression (e.g.,
||One or more characters until (and not including) a forward slash|
||Zero or one of the previous expression (e.g.,
||Zero or more of the previous expression (e.g.,
||Between one and three (inclusive) of the previous expression (e.g.,
||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.