Vicente Garcia-Reyes

Vicente Garcia-Reyes

Designing Better Models in Django

Designing Better Models in Django

Subscribe to my newsletter and never miss my upcoming articles

Photo by Christopher Gower on Unsplash

Introduction

Defining database models is the most critical part of a new project. Django’s coding style ives us a recommended way to create models for our apps which I only discovered today thanks to LearnDjango.:grin: Creating database models may not be simple to devs who haven’t laid hands on Django yet, but I’ll try my best to make sense. :grin:

Learn Django is one of my go-to resources in being a Django developer. If you haven’t checked out the article about my top Django resources, you can check it here.

Model and Field Names

Models will always start with a Capital letter and will always be singular because they should only represent a single object and be using underscores and not a camelCase.

from django.db import models

class City(models.Model):
    town_name = models.CharField(max_length=50)

Common Methods

Defining models is not easy nor should not difficult. Next we add the __str__ and get_absolute_url() methods.

Defining the str method makes the model human-readable in the Django admin.

Defining the get_absolute_url() method tells Django how to calculate the canonical URL for the model. This method should return a string that references a view on the site. It’s also a good practice to use get_absolute_url() on the templates instead of hard-coding them.

<a href="town/{{ object.id }]}/">{{ object.town_name }}</a> # wrong

<a href="{{ object.get_absolute_url }}/">{{ object.town_name }}</a> # better

from django.db import models
from django.urls import reverse # new

class City(models.Model):
    town_name = models.CharField(max_length=50)

    def __str__(self): # new
        return self.town_name

    def get_absolute_url(self):
        return reverse('town', kwargs={"town_name": self.town_name})

Explicit Naming

Explicit is better than implicit

There are two ways to implicitly set the human-readable name for each field which Django does by automatically converting underscores to spaces. One is to use verbose_name(); if the field type is not OneToOneField, ManyToMany or ForeignKey, you can set it as the first positional argument.

from django.db import models 

class City(models.Model): 
    town_name = models.CharField(
    max_length=50,
    verbose_name='town name',
    )

    def __str__(self):
        return self.town_name 

    def get_absolute_url(self): 
        return reverse('town', kwargs={"town_name": self.town_name})

If a model uses ForeignKey, the model will have access to a Manager that returns all instances of the first model. This model returns QuerySets which can be filtered to retrieve objects.

Example:

>>> a = City.objects.get()
...
class Mayor(models.Model):
    first_name = models.CharField('first name', max_length=30)
    last_name = models.CharField('last name', max_length=30)
    city = models.ForeignKey(
        City,
        on_delete=models.CASCADE,
        related_name='mayors',
        related_query_name='human',
        )

    def __str__(self):
        return '%s %s' % (self.first_name, self.last_name)

    def get_absolute_url(self):
        return reverse('town_mayor', kwargs={'town_name': self.town_name})

References

In [1]: from blog.source.models import Category 
In [2]: a = Category.objects.get(name='python') 
In [3]: print(a) python
 
Share this

Impressum

Code snippets/words may be mine unless otherwise stated on each article.

Proudly part of