Designing Better Models in Django

highcenburg

Vicente G. Reyes

Posted on March 6, 2021

Designing Better Models in Django

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.😁 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. 😁

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)
Enter fullscreen mode Exit fullscreen mode

Common Methods

Defining models is not easy nor should not be 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})
Enter fullscreen mode Exit fullscreen mode

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})
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode
...
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})
Enter fullscreen mode Exit fullscreen mode

References

In [1]: from blog.source.models import Category 
In [2]: a = Category.objects.get(name='python') 
In [3]: print(a) python
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
highcenburg
Vicente G. Reyes

Posted on March 6, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related