Designing Models in Django
In this article, I would like to share my experience and help in designing and formatting your Django code. Hopefully you are already using PEP8, but it is also a good tone to use Django's code formatting style guidelines.
Below you can read the recommendations on Django code formatting.
Model names
Since the model is a class, we always use the CapWords convention, i.e. we start each word in the model name with a capital letter, without underscores. For example User
, Permission
, ContentType
, etc.
For model attributes, we use snake_case, i.e. all words with a small letter separated by an underscore. For example first_name
, last_name
.
Example:
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=30)
vat_identification_number = models.CharField(max_length=20)
Also, always use the singular for the model name: Company
instead of Companies
. A model definition is a representation of a single object (in this example, a company), not a set.
It's a bit confusing at first if you're used to thinking in terms of database tables. Eventually the model will be translated into a table. It is quite correct to use the plural for the name of the table, because a table is a collection of objects.
The sequence of placement within the model class
Django's recommendations for the sequence of placement of internal classes, methods, and attributes are as follows:
- if choices are defined for a model field, define each choice as a tuple of tuples, using uppercase letters;
- model data fields;
- user manager attributes;
class Meta
;def __str__()
;def save();
def get_absolute_url();
- the rest of your class methods.
Example:
from django.db import models
from django.urls import reverse
class Company(models.Model):
# CHOICES
PUBLIC_LIMITED_COMPANY = 'PLC'
PRIVATE_COMPANY_LIMITED = 'LTD'
LIMITED_LIABILITY_PARTNERSHIP = 'LLP'
COMPANY_TYPE_CHOICES = (
(PUBLIC_LIMITED_COMPANY, 'Public limited company'),
(PRIVATE_COMPANY_LIMITED, 'Private company limited by shares'),
(LIMITED_LIABILITY_PARTNERSHIP, 'Limited liability partnership'),
)
# DATABASE FIELDS
name = models.CharField('name', max_length=30)
vat_identification_number = models.CharField('VAT', max_length=20)
company_type = models.CharField('type', max_length=3, choices=COMPANY_TYPE_CHOICES)
# MANAGERS
objects = models.Manager()
limited_companies = LimitedCompanyManager()
# META CLASS
class Meta:
verbose_name = 'company'
verbose_name_plural = 'companies'
# TO STRING METHOD
def __str__(self):
return self.name
# SAVE METHOD
def save(self, *args, **kwargs):
do_something()
super().save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
# ABSOLUTE URL METHOD
def get_absolute_url(self):
return reverse('company_details', kwargs={'pk': self.id})
# OTHER METHODS
def process_invoices(self):
do_something()
Reverse relationship
родственное_имя
This attribute is used in the ForeignKey
field. It allows you to specify a normal and convenient name for the reverse relationship.
Example:
class Company:
name = models.CharField(max_length=30)
class Employee:
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='employees')
This code means that the model object Company
will have an attribute employees
that returns QuerySet
with all employee objects of the specified company.
google = Company.objects.get(name='Google')
google.employees.all()
Empty and null fields
The difference between empty and null fields has already been discussed, but I'll repeat:
null
: related to database, determines whether a given database column will take null values or not.blank
: related to Django validation, used during form validation when callingform.is_valid ()
.
Do not use the value null=True
for text fields that are optional. Otherwise you will get two possible values for "no data": "None" and an empty string. Having two possible values for "no data" is redundant. The Django convention should use the empty string, not NULL.
# The default values of `null` and `blank` are `False`.
# значение по умолчанию для null и blank - False
class Person(models.Model):
name = models.CharField(max_length=255) # обязательное
bio = models.TextField(max_length=500, blank=True) # необязательное (не используйте null=True для текстовых полей)
birth_date = models.DateField(null=True, blank=True) # необязательное (здесь нужно использовать оба атрибута null и blank)
Closure
Model definition is an important part of your application. You can see a detailed discussion of the guidelines in the Django's Coding Style documentation.
Back to Top