Book Image

Django: Web Development with Python

By : Aidas Bendoraitis, Samuel Dauzon, Arun Ravindran
Book Image

Django: Web Development with Python

By: Aidas Bendoraitis, Samuel Dauzon, Arun Ravindran

Overview of this book

Data science is hot right now, and the need for multitalented developers is greater than ever before. A basic grounding in building apps with a framework as minimalistic, powerful, and easy-to-learn as Django will be a useful skill to launch your career as an entrepreneur or web developer. Django is a web framework that was designed to strike a balance between rapid web development and high performance. This course will take you on a journey to become an efficient web developer thoroughly understanding the key concepts of Django framework. This learning path is divided into three modules. The course begins with basic concepts of the Django framework. The first module, Django Essentials, is like a practical guide, filled with many real-world examples to build highly effective Django web application. After getting familiar with core concepts of Django, it's time to practice your learning from the first module with the help of over 90 recipes available in this module. In the second module, Web Development with Django Cookbook, you'll learn varying complexities to help you create multilingual, responsive, and scalable websites with Django. By the end of this module, you will have a good understanding of the new features added to Django 1.8 and be an expert at web development processes.The next step is to discover the latest best practices and idioms in this rapidly evolving Django framework. This is what you'll be learning in our third module, Django Design Patterns and Best Practices. This module will teach you common design patterns to develop better Django code. By the end of the module, you will be able to leverage the Django framework to develop a fully functional web application with minimal effort.
Table of Contents (6 chapters)

Chapter 5. Working with Models

The website we just created contains only static data; however, what we want to do is store data so as to automate all the tasks. That's why there are models; they will put a link between our views and the database.

Django, like many frameworks, proposes database access with an abstraction layer. This abstraction layer is called object-relational mapping (ORM). This allows you to use the Python implementation object in order to access the data without worrying about using a database. With this ORM, we do not need to use the SQL query for simple and slightly complex actions. This ORM belongs to Django, but there are others such as SQLAlchemy, which is a quality ORM used especially in the Python TurboGears framework.

A model is an object that inherits from the Model class. The Model class is a Django class that is specifically designed for data persistence.

We define fields in models. These properties allow us to organize data within a model. To make a connection between databases and SQL, we can say that a model is represented by a table in the database, and a model property is represented by a field in the table.

In this chapter, we will explain:

  • How to set up access to the database
  • How to install South for the database migrations
  • How to create simple models
  • How to create a relationship between models
  • How to extend our models
  • How to use the administration module

Databases and Django

Django can interface with many databases. However, during the development of our application, we use SQLite libraries that are included in Django.

We will modify settings.py to set our connection to the database:

DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.sqlite3', 
    'NAME': os.path.join(PROJECT_ROOT, 'database.db'), 
    'USER': '',                     
    'PASSWORD': '',                 
    'HOST': '',                     
    'PORT': '',                     
  }
}

The following is the description of the properties mentioned in the preceding code:

  • The ENGINE property specifies the type of database to be used.
  • The NAME property defines the path and final name of the SQLite database. We use a syntax using os.path.join to our code, and it is compatible with all operating systems. The file's database will be contained in the project directory.
  • The other properties are useful when we use a database server, but as we will use SQLite, we do not need to define them.

Migrations with South

South is a very useful extension of Django. It facilitates the migration of the database when changing fields. It also keeps a history of the changes in the structure of the database.

We talk about it now because it must be installed before the creation of the database to work correctly.

Django 1.7 incorporates a migration system. You will not need to use South anymore to make the migration of a Django application. You can find more information about the migration systems integrated into Django 1.7 at https://docs.djangoproject.com/en/dev/topics/migrations/.

Installing South

To install South, we use the pip command. We have already used it to install Django. To do this, run the following command:

pip install South

Before actually using South, we must change the settings.py file for South to be well integrated in Django. To do this, you must go to INSTALLED_APPS and add the following lines (depending on the version, it is possible that the installation of South added the line):

'south',
'TasksManager',

Using the South extension

Before we make our first migrations and generate our database, we also have to create the schema migration. To do this, we must run the following command:

manage.py schemamigration TasksManager --initial 

Then, we must perform an initial migration:

manage.py syncdb --migrate 

Django asks us to first create an account. This account will be a superuser. Remember the login and password that you enter; you will need this information later.

South is now fully operational. Each time we need to modify the models, we will make a migration. However, for the migration to be made correctly, you must keep the following things in mind:

  • Never perform the Django syncdb command. After running syncdb --migrate for the first time, never run it again. Use migrate afterwards.
  • Always put a default value in the new fields; otherwise, we will be asked to assign a value.
  • Each time we finish editing our models, we must execute the following two commands in the correct order:
    manage.py schemamigration TasksManager –auto
    manage.py migrate TasksManager
    

Installing South

To install South, we use the pip command. We have already used it to install Django. To do this, run the following command:

pip install South

Before actually using South, we must change the settings.py file for South to be well integrated in Django. To do this, you must go to INSTALLED_APPS and add the following lines (depending on the version, it is possible that the installation of South added the line):

'south',
'TasksManager',

Using the South extension

Before we make our first migrations and generate our database, we also have to create the schema migration. To do this, we must run the following command:

manage.py schemamigration TasksManager --initial 

Then, we must perform an initial migration:

manage.py syncdb --migrate 

Django asks us to first create an account. This account will be a superuser. Remember the login and password that you enter; you will need this information later.

South is now fully operational. Each time we need to modify the models, we will make a migration. However, for the migration to be made correctly, you must keep the following things in mind:

  • Never perform the Django syncdb command. After running syncdb --migrate for the first time, never run it again. Use migrate afterwards.
  • Always put a default value in the new fields; otherwise, we will be asked to assign a value.
  • Each time we finish editing our models, we must execute the following two commands in the correct order:
    manage.py schemamigration TasksManager –auto
    manage.py migrate TasksManager
    

Using the South extension

Before we make our first migrations and generate our database, we also have to create the schema migration. To do this, we must run the following command:

manage.py schemamigration TasksManager --initial 

Then, we must perform an initial migration:

manage.py syncdb --migrate 

Django asks us to first create an account. This account will be a superuser. Remember the login and password that you enter; you will need this information later.

South is now fully operational. Each time we need to modify the models, we will make a migration. However, for the migration to be made correctly, you must keep the following things in mind:

  • Never perform the Django syncdb command. After running syncdb --migrate for the first time, never run it again. Use migrate afterwards.
  • Always put a default value in the new fields; otherwise, we will be asked to assign a value.
  • Each time we finish editing our models, we must execute the following two commands in the correct order:
    manage.py schemamigration TasksManager –auto
    manage.py migrate TasksManager
    

Creating simple models

To create models, we must have already studied the application in depth. Models are the basis of any application because they will store all the data. Therefore, we must prepare them carefully.

Concerning our Tasksmanager application, we need a user who saves tasks performed on a project. We'll create two models: User_django and Project.

We need to store our models in the models.py file. We will edit the models.py file in the TasksManager folder. We do not need to modify the configuration file, because when you need the model, we will have to import it.

The file already exists and has a line. The following line allows you to import the base model of Django:

from django.db import models

The UserProfile model

To create the UserProfile model, we ask ourselves the question, "what data about the user do we need to keep?". We will need the following data:

  • The user's real name
  • A nickname that will identify each user
  • A password that will be useful for user authentication
  • Phone number
  • Date of birth (this is not essential, but we must study the dates!)
  • The date and time of the last connection
  • E-mail address
  • Age (in years)
  • The creation date of the user account
  • A specialization, if it is supervisor
  • The type of user
  • A supervisor, if you are a developer

The model that is needed is as follows:

class UserProfile(models.Model):
  name = models.CharField(max_length=50, verbose_name="Name")
  login = models.CharField(max_length=25, verbose_name="Login")
  password = models.CharField(max_length=100, verbose_name="Password")
  phone = models.CharField(max_length=20, verbose_name="Phone number" , null=True, default=None, blank=True)
  born_date = models.DateField(verbose_name="Born date" , null=True, default=None, blank=True)
  last_connection = models.DateTimeField(verbose_name="Date of last connection" , null=True, default=None, blank=True)
  email = models.EmailField(verbose_name="Email")
  years_seniority = models.IntegerField(verbose_name="Seniority", default=0)
  date_created = models.DateField(verbose_name="Date of Birthday", auto_now_add=True)

We have not defined the specialization, type of user, and supervisor, because these points will be seen in the next part.

In the preceding code, we can see that Django_user inherits from the Model class. This Model class has all the methods that we will need to manipulate the models. We can also override these methods to customize the use of models.

Within this class, we added our fields by adding an attribute in which we specified the values. For example, the first name field is a character string type with a maximum length of 50 characters. The verbose_name property will be the label that defines our field in forms. The following is a list of the commonly used field types:

  • CharField: This is a character string with a limited number of characters
  • TextField: This is a character string with unlimited characters
  • IntegerField: This is an integer field
  • DateField: This is a date field
  • DateTimeField: This field consists of the date as well as the time in hours, minutes, and seconds
  • DecimalField: This is a decimal number that can be defined precisely

Tip

Django automatically saves an id field in auto increment. Therefore, we do not need to define a primary key.

The Project model

To save our projects, we will need the following data:

  • Title
  • Description
  • Client name

These factors allow us to define the following model:

class Project(models.Model):
  title = models.CharField(max_length=50, verbose_name="Title")
  description = models.CharField(max_length=1000, verbose_name="Description")
  client_name = models.CharField(max_length=1000, verbose_name="Client name")

To comply with good practices, we would not have had to define a text field for the customer, but define a relationship to a client table. To simplify our first model, we define a text field for the client name.

The UserProfile model

To create the UserProfile model, we ask ourselves the question, "what data about the user do we need to keep?". We will need the following data:

  • The user's real name
  • A nickname that will identify each user
  • A password that will be useful for user authentication
  • Phone number
  • Date of birth (this is not essential, but we must study the dates!)
  • The date and time of the last connection
  • E-mail address
  • Age (in years)
  • The creation date of the user account
  • A specialization, if it is supervisor
  • The type of user
  • A supervisor, if you are a developer

The model that is needed is as follows:

class UserProfile(models.Model):
  name = models.CharField(max_length=50, verbose_name="Name")
  login = models.CharField(max_length=25, verbose_name="Login")
  password = models.CharField(max_length=100, verbose_name="Password")
  phone = models.CharField(max_length=20, verbose_name="Phone number" , null=True, default=None, blank=True)
  born_date = models.DateField(verbose_name="Born date" , null=True, default=None, blank=True)
  last_connection = models.DateTimeField(verbose_name="Date of last connection" , null=True, default=None, blank=True)
  email = models.EmailField(verbose_name="Email")
  years_seniority = models.IntegerField(verbose_name="Seniority", default=0)
  date_created = models.DateField(verbose_name="Date of Birthday", auto_now_add=True)

We have not defined the specialization, type of user, and supervisor, because these points will be seen in the next part.

In the preceding code, we can see that Django_user inherits from the Model class. This Model class has all the methods that we will need to manipulate the models. We can also override these methods to customize the use of models.

Within this class, we added our fields by adding an attribute in which we specified the values. For example, the first name field is a character string type with a maximum length of 50 characters. The verbose_name property will be the label that defines our field in forms. The following is a list of the commonly used field types:

  • CharField: This is a character string with a limited number of characters
  • TextField: This is a character string with unlimited characters
  • IntegerField: This is an integer field
  • DateField: This is a date field
  • DateTimeField: This field consists of the date as well as the time in hours, minutes, and seconds
  • DecimalField: This is a decimal number that can be defined precisely

Tip

Django automatically saves an id field in auto increment. Therefore, we do not need to define a primary key.

The Project model

To save our projects, we will need the following data:

  • Title
  • Description
  • Client name

These factors allow us to define the following model:

class Project(models.Model):
  title = models.CharField(max_length=50, verbose_name="Title")
  description = models.CharField(max_length=1000, verbose_name="Description")
  client_name = models.CharField(max_length=1000, verbose_name="Client name")

To comply with good practices, we would not have had to define a text field for the customer, but define a relationship to a client table. To simplify our first model, we define a text field for the client name.

The Project model

To save our projects, we will need the following data:

  • Title
  • Description
  • Client name

These factors allow us to define the following model:

class Project(models.Model):
  title = models.CharField(max_length=50, verbose_name="Title")
  description = models.CharField(max_length=1000, verbose_name="Description")
  client_name = models.CharField(max_length=1000, verbose_name="Client name")

To comply with good practices, we would not have had to define a text field for the customer, but define a relationship to a client table. To simplify our first model, we define a text field for the client name.

The relationship between the models

Relationships are elements that join our models. For example, in the case of this application, a task is linked to a project. Indeed, the developer performs a task for a particular project unless it is a more general task, but it's out of the scope of our project. We define the one-to-many type of relationship in order to denote that a task always concerns a single project but a project can be connected to many tasks.

There are two other kinds of relationships:

  • The one-to-one relationship sets apart a model in two parts. The resulting database will create two tables linked by a relationship. We will see an example in the chapter on the authentication module.
  • The many-to-many relationship defines relationships with many records in one model can be connected to many records of the several other models of the same type. For example, an author can publish several books and a book may have several authors.

Creating the task model with relationships

For the task model, we need the following elements:

  • A way to define the task in a few words
  • A description for more details about the task
  • A past life
  • Its importance
  • The project to which it is attached
  • The developer who has created it

This allows us to write the following model:

class Task(models.Model):
  title = models.CharField(max_length=50, verbose_name="Title")
  description = models.CharField(max_length=1000, verbose_name="Description")
  time_elapsed = models.IntegerField(verbose_name="Elapsed time" , null=True, default=None, blank=True)
  importance = models.IntegerField(verbose_name="Importance")
  project = models.ForeignKey(Project, verbose_name="Project" , null=True, default=None, blank=True)
  app_user = models.ForeignKey(UserProfile, verbose_name="User")

In this model, we have defined two foreign key field types: project and app_user. In the database, these fields contain the login details of the record to which they are attached in the other table.

The project field that defines the relationship with the Project model has two additional attributes:

  • Null: This decides whether the element can be defined as null. The fact that this attribute is in the project field means that a task is not necessarily related to a project.
  • Default: This sets the default value that the field will have. That is, if we do not specify the value of the project before saving the model, the task will not be connected to a domain.

Creating the task model with relationships

For the task model, we need the following elements:

  • A way to define the task in a few words
  • A description for more details about the task
  • A past life
  • Its importance
  • The project to which it is attached
  • The developer who has created it

This allows us to write the following model:

class Task(models.Model):
  title = models.CharField(max_length=50, verbose_name="Title")
  description = models.CharField(max_length=1000, verbose_name="Description")
  time_elapsed = models.IntegerField(verbose_name="Elapsed time" , null=True, default=None, blank=True)
  importance = models.IntegerField(verbose_name="Importance")
  project = models.ForeignKey(Project, verbose_name="Project" , null=True, default=None, blank=True)
  app_user = models.ForeignKey(UserProfile, verbose_name="User")

In this model, we have defined two foreign key field types: project and app_user. In the database, these fields contain the login details of the record to which they are attached in the other table.

The project field that defines the relationship with the Project model has two additional attributes:

  • Null: This decides whether the element can be defined as null. The fact that this attribute is in the project field means that a task is not necessarily related to a project.
  • Default: This sets the default value that the field will have. That is, if we do not specify the value of the project before saving the model, the task will not be connected to a domain.

Extending models

The inheritance model allows the use of common fields for two different models. For example, in our App_user model, we cannot determine whether a random recording will be a developer or supervisor.

One solution would be to create two different models, but we would have to duplicate all the common fields such as name, username, and password, as follows:

class Supervisor(models.Model):
  # Duplicated common fields
  specialisation = models.CharField(max_length=50, verbose_name="Specialisation")

class Developer(models.Model):
  # Duplicated common fields
  supervisor = models.ForeignKey(Supervisor, verbose_name="Supervisor")

It would be a shame to duplicate the code, but it is the principle that Django and DRY have to follow. That is why there is an inheritance model.

Indeed, the legacy model is used to define a master model (or supermodel), which contains the common fields to several models. Children models automatically inherit the fields of the supermodel.

Nothing is more explicit than an example; we will modify our classes, Developer and Supervisor, to make them inherit App_user:

class Supervisor(UserProfile):
  specialisation = models.CharField(max_length=50, verbose_name="Specialisation")

class Developer(UserProfile):
  supervisor = models.ForeignKey(Supervisor, verbose_name="Supervisor")

The result of the legacy database allows us to create three tables:

  • A table for the App_user model that contains the fields for the properties of the model
  • A table for the Supervisor model, with a text field for specialization and a field that has a foreign key relationship with the App_user table
  • A Developer table with two fields: a field in liaison with the Supervisor table and a field that links to the App_user table

Now that we have separated our two types of users, we will modify the relationship with App_user because only the developer will record his or her tasks. In the Tasks model, we have the following line:

app_user = models.ForeignKey(App_user, verbose_name="User")

This code is transformed as follows:

developer = models.ForeignKey(Developer, verbose_name="User")

For the generation of the database order to work, we must put models in the correct order. Indeed, if we define a relationship with a model that is not yet defined, Python will raise an exception. For the moment, the models will need to be defined in the order described. Later, we shall see how to work around this limitation.

In the next chapter, we will perform queries on the model. This requires the database to be synchronized with the models. We must first migrate South before starting the next chapter.

To perform the migration, we must use the commands we've seen at the beginning of the chapter. To simplify the migration, we can also create a batch file in the Python folder, where we will put the following lines:

manage.py schemamigration TasksManager --auto
manage.py migrate
pause

The following is a bash script you can create in the Work_manager folder that can perform the same thing on Debian Linux:

#!/bin/bash
manage.py runserver 127.0.0.1:8000

This way, when you migrate South, it will execute this file. The pause command allows you to look at the results or errors displayed without closing the window.

The admin module

The administration module is very convenient and is included by default with Django. It is a module that will maintain the content of the database without difficulty. This is not a database manager because it cannot maintain the structure of the database.

One question that you may ask is, "what does it have other than a management tool database?". The answer is that the administration module is fully integrated with Django and uses these models.

The following are its advantages:

  • It manages the relationships between models. This means that if we want to save a new developer, the module will propose a list of all the supervisors. In this way, it will not create a non-existent relationship.
  • It manages Django permissions. You can set permissions for users according to models and CRUD operations.
  • It is quickly established.

Being based on Django models and not on the database, this module allows the user to edit the recorded data.

Installing the module

To implement the administration module, edit the settings.py file. In the INSTALLED_APPS setting, you need to add or uncomment the following line:

'django.contrib.admin'

You also have to edit the urls.py file by adding or uncommenting the following lines:

from django.contrib import admin
admin.autodiscover()
url (r'^admin', include(admin.site.urls)),

The line that imports the administration module has to be at the beginning of the file with other imports. The line that runs the autodiscover() method must be found after the imports and before the urlpatterns definition. Finally, the last line is a URL that should be in urlpatterns.

We also have to create an admin.py file in the TasksManager folder in which we will define the styles we want to integrate into the management module:

from django.contrib import admin
from TasksManager.models import UserProfile, Project, Task , Supervisor , Developer
admin.site.register(UserProfile)
admin.site.register(Project)
admin.site.register(Task)
admin.site.register(Supervisor)
admin.site.register(Developer)

Now that we have configured the administration module, we can easily manage our data.

Using the module

To use the administration module, we must connect to the URL that we have just defined: http://localhost:8000/admin/.

We must connect with the logins defined when creating the database:

  1. Once we are connected, the model list appears.
  2. If we click on the Supervisor model link, we arrive at a page where we can add a supervisor by using the button at the top-right corner of the window:
    Using the module
  3. By clicking on this button, we load a page consisting of a form. This form automatically provides practical tools to manage dates and times:
    Using the module

Let's add a new supervisor and then add a developer. When you want to choose the supervisor, you can see the one we have just created in a combobox. The green cross on the right-hand side allows you to quickly create a supervisor.

In the following chapter, we will define the str method for our models. This will improve the display lists of objects in this management module.

Installing the module

To implement the administration module, edit the settings.py file. In the INSTALLED_APPS setting, you need to add or uncomment the following line:

'django.contrib.admin'

You also have to edit the urls.py file by adding or uncommenting the following lines:

from django.contrib import admin
admin.autodiscover()
url (r'^admin', include(admin.site.urls)),

The line that imports the administration module has to be at the beginning of the file with other imports. The line that runs the autodiscover() method must be found after the imports and before the urlpatterns definition. Finally, the last line is a URL that should be in urlpatterns.

We also have to create an admin.py file in the TasksManager folder in which we will define the styles we want to integrate into the management module:

from django.contrib import admin
from TasksManager.models import UserProfile, Project, Task , Supervisor , Developer
admin.site.register(UserProfile)
admin.site.register(Project)
admin.site.register(Task)
admin.site.register(Supervisor)
admin.site.register(Developer)

Now that we have configured the administration module, we can easily manage our data.

Using the module

To use the administration module, we must connect to the URL that we have just defined: http://localhost:8000/admin/.

We must connect with the logins defined when creating the database:

  1. Once we are connected, the model list appears.
  2. If we click on the Supervisor model link, we arrive at a page where we can add a supervisor by using the button at the top-right corner of the window:
    Using the module
  3. By clicking on this button, we load a page consisting of a form. This form automatically provides practical tools to manage dates and times:
    Using the module

Let's add a new supervisor and then add a developer. When you want to choose the supervisor, you can see the one we have just created in a combobox. The green cross on the right-hand side allows you to quickly create a supervisor.

In the following chapter, we will define the str method for our models. This will improve the display lists of objects in this management module.

Using the module

To use the administration module, we must connect to the URL that we have just defined: http://localhost:8000/admin/.

We must connect with the logins defined when creating the database:

  1. Once we are connected, the model list appears.
  2. If we click on the Supervisor model link, we arrive at a page where we can add a supervisor by using the button at the top-right corner of the window:
    Using the module
  3. By clicking on this button, we load a page consisting of a form. This form automatically provides practical tools to manage dates and times:
    Using the module

Let's add a new supervisor and then add a developer. When you want to choose the supervisor, you can see the one we have just created in a combobox. The green cross on the right-hand side allows you to quickly create a supervisor.

In the following chapter, we will define the str method for our models. This will improve the display lists of objects in this management module.

Advanced usage of models

We studied the basics of the models that allow us to create simple applications. Sometimes, it is necessary to define more complex structures.

Using two relationships for the same model

Sometimes, it is useful to store two foreign keys (or more) in a single model. For example, if we want two developers to work in parallel on the same task, we must use the related_name property in our models. For example, our Task model contains two relationships with the following lines:

developer1 = models.ForeignKey (Developer , verbose_name = "User" , related_name = "dev1" )
developer2 = models.ForeignKey (Developer , verbose_name = "User" , related_name = "dev2" )

Further in this book, we will not use these two relationships. To effectively follow this book, we must return to our previously defined Task model.

Note

Here, we define two developers on the same task. Best practices advise us to create a many-to-many relationship in the Task model. The thorough argument allows you to specify an intermediate table to store additional data. This is an optional step. An example of this type of relationship is as follows:

#Relationship to add to the Task model
developers = models.ManyToManyField(Developer , through="DeveloperWorkTask")
class DeveloperWorkTask(models.Model):
  developer = models.ForeignKey(Developer)
  task = models.ForeignKey(Task)
  time_elapsed_dev = models.IntegerField(verbose_name="Time elapsed", null=True, default=None, blank=True)

Defining the str method

As already mentioned in the section on the use of the admin module, the __str__() method will allow a better view of our models. This method will set the string that will be used to display our model instance. When Django was not compatible with Python 3, this method was replaced by the __unicode__() method.

For example, when we added a developer, the drop-down list that defines a supervisor showed us the "Supervisor object" lines. It would be more helpful to display the name of the supervisor. In order to do this, change our App_user class and add the str() method:

class UserProfile ( models.Model ) :
# Fields...
def __str__ (self):
  return self.name

This method will return the name of the supervisor for the display and allows you to manage the administration easily:

Defining the str method

Using two relationships for the same model

Sometimes, it is useful to store two foreign keys (or more) in a single model. For example, if we want two developers to work in parallel on the same task, we must use the related_name property in our models. For example, our Task model contains two relationships with the following lines:

developer1 = models.ForeignKey (Developer , verbose_name = "User" , related_name = "dev1" )
developer2 = models.ForeignKey (Developer , verbose_name = "User" , related_name = "dev2" )

Further in this book, we will not use these two relationships. To effectively follow this book, we must return to our previously defined Task model.

Note

Here, we define two developers on the same task. Best practices advise us to create a many-to-many relationship in the Task model. The thorough argument allows you to specify an intermediate table to store additional data. This is an optional step. An example of this type of relationship is as follows:

#Relationship to add to the Task model
developers = models.ManyToManyField(Developer , through="DeveloperWorkTask")
class DeveloperWorkTask(models.Model):
  developer = models.ForeignKey(Developer)
  task = models.ForeignKey(Task)
  time_elapsed_dev = models.IntegerField(verbose_name="Time elapsed", null=True, default=None, blank=True)

Defining the str method

As already mentioned in the section on the use of the admin module, the __str__() method will allow a better view of our models. This method will set the string that will be used to display our model instance. When Django was not compatible with Python 3, this method was replaced by the __unicode__() method.

For example, when we added a developer, the drop-down list that defines a supervisor showed us the "Supervisor object" lines. It would be more helpful to display the name of the supervisor. In order to do this, change our App_user class and add the str() method:

class UserProfile ( models.Model ) :
# Fields...
def __str__ (self):
  return self.name

This method will return the name of the supervisor for the display and allows you to manage the administration easily:

Defining the str method

Defining the str method

As already mentioned in the section on the use of the admin module, the __str__() method will allow a better view of our models. This method will set the string that will be used to display our model instance. When Django was not compatible with Python 3, this method was replaced by the __unicode__() method.

For example, when we added a developer, the drop-down list that defines a supervisor showed us the "Supervisor object" lines. It would be more helpful to display the name of the supervisor. In order to do this, change our App_user class and add the str() method:

class UserProfile ( models.Model ) :
# Fields...
def __str__ (self):
  return self.name

This method will return the name of the supervisor for the display and allows you to manage the administration easily:

Defining the str method

Summary

In this chapter, we learned migration with South. We also learned how to create simple models and relationships between the models. Furthermore, we learned how to install and use the admin module. In the next chapter, we will learn how to manipulate our data. We will learn how to use four main operations on the data: adding, reading (and research), modification, and deletion.