Code Style in Django

In this article written by Sanjeev Jaiswal and Ratan Kumar, authors of the book Learning Django Web Development, this article will cover all the basic topics which you would require to follow, such as coding practices for better Django web development, which IDE to use, version control, and so on.

We will learn the following topics in this article:

  • Django coding style
  • Using IDE for Django web development
  • Django project structure

This article is based on the important fact that code is read much more often than it is written. Thus, before you actually start building your projects, we suggest that you familiarize yourself with all the standard practices adopted by the Django community for web development.

Django coding style

Most of Django's important practices are based on Python. Though chances are you already know them, we will still take a break and write all the documented practices so that you know these concepts even before you begin.

To mainstream standard practices, Python enhancement proposals are made, and one such widely adopted standard practice for development is PEP8, the style guide for Python code–the best way to style the Python code authored by Guido van Rossum.

The documentation says, "PEP8 deals with semantics and conventions associated with Python docstrings." For further reading, please visit http://legacy.python.org/dev/peps/pep-0008/.

Understanding indentation in Python

When you are writing Python code, indentation plays a very important role. It acts as a block like in other languages, such as C or Perl. But it's always a matter of discussion amongst programmers whether we should use tabs or spaces, and, if space, how many–two or four or eight. Using four spaces for indentation is better than eight, and if there are a few more nested blocks, using eight spaces for each indentation may take up more characters than can be shown in single line. But, again, this is the programmer's choice.

The following is what incorrect indentation practices lead to:

>>> def a():
...   print "foo"
...     print "bar"
IndentationError: unexpected indent

So, which one we should use: tabs or spaces?

Choose any one of them, but never mix up tabs and spaces in the same project or else it will be a nightmare for maintenance. The most popular way of indention in Python is with spaces; tabs come in second. If any code you have encountered has a mixture of tabs and spaces, you should convert it to using spaces exclusively.

Doing indentation right – do we need four spaces per indentation level?

There has been a lot of confusion about it, as of course, Python's syntax is all about indentation. Let's be honest: in most cases, it is. So, what is highly recommended is to use four spaces per indentation level, and if you have been following the two-space method, stop using it. There is nothing wrong with it, but when you deal with multiple third party libraries, you might end up having a spaghetti of different versions, which will ultimately become hard to debug.

Now for indentation. When your code is in a continuation line, you should wrap it vertically aligned, or you can go in for a hanging indent. When you are using a hanging indent, the first line should not contain any argument and further indentation should be used to clearly distinguish it as a continuation line.

A hanging indent (also known as a negative indent) is a style of indentation in which all lines are indented except for the first line of the paragraph. The preceding paragraph is the example of hanging indent.

The following example illustrates how you should use a proper indentation method while writing the code:

bar = some_function_name(var_first, var_second,
                                           var_third, var_fourth) 
# Here indentation of arguments makes them grouped, and stand clear from others.
def some_function_name(
       var_first, var_second, var_third,
       var_fourth):
   print(var_first)
# This example shows the hanging intent.

We do not encourage the following coding style, and it will not work in Python anyway:

# When vertical alignment is not used, Arguments on the first line are forbidden
foo = some_function_name(var_first, var_second,
   var_third, var_fourth)
# Further indentation is required as indentation is not 
distinguishable between arguments and source code.
def some_function_name(    var_first, var_second, var_third,    var_fourth):    print(var_first)

Although extra indentation is not required, if you want to use extra indentation to ensure that the code will work, you can use the following coding style:

# Extra indentation is not necessary.
if (this
   and that):
   do_something()

Ideally, you should limit each line to a maximum of 79 characters. It allows for a + or character used for viewing difference using version control. It is even better to limit lines to 79 characters for uniformity across editors. You can use the rest of the space for other purposes.

The importance of blank lines

The importance of two blank lines and single blank lines are as follows:

  • Two blank lines: A double blank lines can be used to separate top-level functions and the class definition, which enhances code readability.
  • Single blank lines: A single blank line can be used in the use cases–for example, each function inside a class can be separated by a single line, and related functions can be grouped together with a single line. You can also separate the logical section of source code with a single line.

Importing a package

Importing a package is a direct implication of code reusability. Therefore, always place imports at the top of your source file, just after any module comments and document strings, and before the module's global and constants as variables. Each import should usually be on separate lines.

The best way to import packages is as follows:

import os
import sys

It is not advisable to import more than one package in the same line, for example:

import sys, os

You may import packages in the following fashion, although it is optional:

from django.http import Http404, HttpResponse

If your import gets longer, you can use the following method to declare them:

from django.http import (
Http404, HttpResponse, HttpResponsePermanentRedirect
)

Grouping imported packages

Package imports can be grouped in the following ways:

  • Standard library imports: Such as sys, os, subprocess, and so on.
    import re
    import simplejson
  • Related third party imports: These are usually downloaded from the Python cheese shop, that is, PyPy (using pip install). Here is an example:
    from decimal import *
  • Local application / library-specific imports: This included the local modules of your projects, such as models, views, and so on.

    from models import ModelFoo
    from models import ModelBar

Naming conventions in Python/Django

Every programming language and framework has its own naming convention. The naming convention in Python/Django is more or less the same, but it is worth mentioning it here. You will need to follow this while creating a variable name or global variable name and when naming a class, package, modules, and so on.

This is the common naming convention that we should follow:

  • Name the variables properly: Never use single characters, for example, 'x' or 'X' as variable names. It might be okay for your normal Python scripts, but when you are building a web application, you must name the variable properly as it determines the readability of the whole project.
  • Naming of packages and modules: Lowercase and short names are recommended for modules. Underscores can be used if their use would improve readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.
  • Since module names are mapped to file names (models.py, urls.py, and so on), it is important that module names be chosen to be fairly short as some file systems are case insensitive and truncate long names.
  • Naming a class: Class names should follow the CamelCase naming convention, and classes for internal use can have a leading underscore in their name.
  • Global variable names: First of all, you should avoid using global variables, but if you need to use them, prevention of global variables from getting exported can be done via __all__, or by defining them with a prefixed underscore (the old, conventional way).
  • Function names and method argument: Names of functions should be in lowercase and separated by an underscore and self as the first argument to instantiate methods. For classes or methods, use CLS or the objects for initialization.
  • Method names and instance variables: Use the function naming rules—lowercase with words separated by underscores as necessary to improve readability. Use one leading underscore only for non-public methods and instance variables.

Using IDE for faster development

There are many options on the market when it comes to source code editors. Some people prefer full-fledged IDEs, whereas others like simple text editors. The choice is totally yours; pick up whatever feels more comfortable. If you already use a certain program to work with Python source files, I suggest that you stick to it as it will work just fine with Django. Otherwise, I can make a couple of recommendations, such as these:

  • SublimeText: This editor is lightweight and very powerful. It is available for all major platforms, supports syntax highlighting and code completion, and works well with Python. The editor is open source and you can find it at http://www.sublimetext.com/
  • PyCharm: This, I would say, is most intelligent code editor of all and has advanced features, such as code refactoring and code analysis, which makes development cleaner. Features for Django include template debugging (which is a winner) and also quick documentation, so this look-up is a must for beginners. The community edition is free and you can sample a 30-day trial version before buying the professional edition.

Setting up your project with the Sublime text editor

Most of the examples that we will show you in this book will be written using Sublime text editor. In this section, we will show how to install and set up the Django project.

  1. Download and installation: You can download Sublime from the download tab of the site www.sublimetext.com. Click on the downloaded file option to install.
  2. Setting up for Django: Sublime has a very extensive plug-in ecosystem, which means that once you have downloaded the editor, you can install plug-ins for adding more features to it.

After successful installation, it will look like this:

Learning Django Web Development

Most important of all is Package Control, which is the manager for installing additional plugins directly from within Sublime. This will be your only manual installation of the package. It will take care of the rest of the package installation ahead.

Learning Django Web Development

Some of the recommendations for Python development using Sublime are as follows:

  • Sublime Linter: This gives instant feedback about the Python code as you write it. It also has PEP8 support; this plugin will highlight in real time the things we discussed about better coding in the previous section so that you can fix them.

     Learning Django Web Development

  • Sublime CodeIntel: This is maintained by the developer of SublimeLint. Sublime CodeIntel have some of advanced functionalities, such as directly go-to definition, intelligent code completion, and import suggestions.

     Learning Django Web Development

You can also explore other plugins for Sublime to increase your productivity.

Setting up the pycharm IDE

You can use any of your favorite IDEs for Django project development. We will use pycharm IDE for this book. This IDE is recommended as it will help you at the time of debugging, using breakpoints that will save you a lot of time figuring out what actually went wrong.

Here is how to install and set up pycharm IDE for Django:

  1. Download and installation: You can check the features and download the pycharm IDE from the following link:

    http://www.jetbrains.com/pycharm/

    Learning Django Web Development

  2. Setting up for Django: Setting up pycharm for Django is very easy. You just have to import the project folder and give the manage.py path, as shown in the following figure:

    Learning Django Web Development

The Django project structure

The Django project structure has been changed in the 1.6 release version. Django (django-admin.py) also has a startapp command to create an application, so it is high time to tell you the difference between an application and a project in Django.

A project is a complete website or application, whereas an application is a small, self-contained Django application. An application is based on the principle that it should do one thing and do it right.

To ease out the pain of building a Django project right from scratch, Django gives you an advantage by auto-generating the basic project structure files from which any project can be taken forward for its development and feature addition.

Thus, to conclude, we can say that a project is a collection of applications, and an application can be written as a separate entity and can be easily exported to other applications for reusability.

To create your first Django project, open a terminal (or Command Prompt for Windows users), type the following command, and hit Enter:

$ django-admin.py startproject django_mytweets

This command will make a folder named django_mytweets in the current directory and create the initial directory structure inside it. Let's see what kind of files are created.

The new structure is as follows:

django_mytweets///
django_mytweets/
manage.py

This is the content of django_mytweets/:

django_mytweets/
__init__.py
settings.py
urls.py
wsgi.py

Here is a quick explanation of what these files are:

  • django_mytweets (the outer folder): This folder is the project folder. Contrary to the earlier project structure in which the whole project was kept in a single folder, the new Django project structure somehow hints that every project is an application inside Django.

    This means that you can import other third party applications on the same level as the Django project. This folder also contains the manage.py file, which include all the project management settings.

  • manage.py: This is utility script is used to manage our project. You can think of it as your project's version of django-admin.py. Actually, both django-admin.py and manage.py share the same backend code.

    Further clarification about the settings will be provided when are going to tweak the changes.

    Let's have a look at the manage.py file:

    #!/usr/bin/env python
    import os
    import sys
    if __name__ == "__main__":
       os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_mytweets.settings")
       from django.core.management import   execute_from_command_line
       execute_from_command_line(sys.argv)

    The source code of the manage.py file will be self-explanatory once you read the following code explanation.

    #!/usr/bin/env python

    The first line is just the declaration that the following file is a Python file, followed by the import section in which os and sys modules are imported. These modules mainly contain system-related operations.

    import os
    import sys

    The next piece of code checks whether the file is executed by the main function, which is the first function to be executed, and then loads the Django setting module to the current path. As you are already running a virtual environment, this will set the path for all the modules to the path of the current running virtual environment.

    if __name__ == "__main__":
       os.environ.setdefault("DJANGO_SETTINGS_MODULE",     "django_mytweets.settings")
    django_mytweets/ ( Inner folder)
    __init__.py

    Django projects are Python packages, and this file is required to tell Python that this folder is to be treated as a package. A package in Python's terminology is a collection of modules, and they are used to group similar files together and prevent naming conflicts.

  • settings.py: This is the main configuration file for your Django project. In it, you can specify a variety of options, including database settings, site language(s), what Django features need to be enabled, and so on.

    By default, the database is configured to use SQLite Database, which is advisable to use for testing purposes. Here, we will only see how to enter the database in the settings file; it also contains the basic setting configuration, and with slight modification in the manage.py file, it can be moved to another folder, such as config or conf.

    To make every other third-party application a part of the project, we need to register it in the settings.py file. INSTALLED_APPS is a variable that contains all the entries about the installed application. As the project grows, it becomes difficult to manage; therefore, there are three logical partitions for the INSTALLED_APPS variable, as follows:

    • DEFAULT_APPS: This parameter contains the default Django installed applications (such as the admin)
    • THIRD_PARTY_APPS: This parameter contains other application like SocialAuth used for social authentication
    • LOCAL_APPS: This parameter contains the applications that are created by you
  • url.py: This is another configuration file. You can think of it as a mapping between URLs and the Django view functions that handle them. This file is one of Django's more powerful features.

    When we start writing code for our application, we will create new files inside the project's folder. So, the folder also serves as a container for our code.

Now that you have a general idea of the structure of a Django project, let's configure our database system.

Summary

We prepared our development environment in this article, created our first project, set up the database, and learned how to launch the Django development server. We learned the best way to write code for our Django project and saw the default Django project structure.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Learning Django Web Development

Explore Title
comments powered by Disqus