Models

During this session, please feel free to consult the Django Tutorial and the Mozilla Tutorial tutorials on models.

What is a model? It is a Python object that the Django ORM (object-relational mapper) uses so that databases are familiar and friendly for Pythonistas. One of the key adavantages of this approach is that developers can use multiple databases and types of databases without having to learn the differences between a query in MySQL or postgres. We’ll discuss sql queries later on so that you understand what’s going on under the hood of the ORM.

Python is an object oriented language. Here’s a very simple object in Python from the GAM project:

class CurrentItem:
    def __init__(self, name, letters):
        self.name = name
        self.letters = letters

To create a current item object, just use current = CurrentItem We can set or update the values for name and letters with current.name = item_name or current.letters

Python 3.7+ comes with a native dataclass object.

from dataclasses import dataclass

@dataclass
class Course:
    campus: str    # 'campus' has no default value
    semester: str
    title: str
    credit: int = 1  # assign a default value for 'credit'
    department: str
    instructor: str
    times: str
    room: str 
    additional_info: str
    misc_links: str

In a Django model we add fields to the model. Note that there are many data types. The most common is Charfield, for a string. For a full list of model field types documentation.:

from django.db import models

class Fish(models.Model):
    """A model for adding fish to the database."""

    # Fields
    name = models.CharField(max_length=200, help_text='The fish's prefered name')
    type = models.CharField(max_length=20, help_text='The type of fish')
    date_of_birth = models.DateField(auto_now=False)
    has_fins = models.BooleanField(null=True)
    
    def __str__(self):
        return self.name

Note the str method. This defines what is displayed in the admin interface (we’ll get to that soon). You can also add methods to the model. For example, for age”

import datetime 
    ... 
    def age(self):
        dob = self.date_of_birth
        now = datetime.datetime.now().date()
        age = now - dob
        return age.days / 365

ManytoMany and Foreign Key

class Persona(models.Model):
    """A person."""

    nombre_de_la_persona = models.CharField(max_length=200, null=True)
    nombre = models.CharField(max_length=200, blank=True)
    segundo = models.CharField(max_length=200, blank=True)
    apellido_paterno = models.CharField(max_length=200, blank=True)
    apellido_materno = models.CharField(max_length=200, blank=True)
    fecha_de_nacimiento = models.CharField(max_length=200, blank=True)
    fecha_desaparicion = models.CharField(max_length=200, blank=True)
    edad_en_el_momento = models.CharField(max_length=200, blank=True)
    género = models.CharField(max_length=200, blank=True)
    etnicidad = models.CharField(max_length=200, blank=True)
    profesión = models.CharField(max_length=200, blank=True)
    actividades_políticas = models.ManyToManyField('Organización', blank=True)
    # relaciones = models.ManyToManyField('Relación', blank=True)
    image = models.ManyToManyField('Imagen', blank=True)
    notas = RichTextField(blank=True)

    def __str__(self):
        return self.nombre_de_la_persona

    def get_absolute_url(self):
        return "/persona/%i/" % self.id

vs.

class Caja(models.Model):
    """A folder."""

    archivo = models.ForeignKey('Archivo', on_delete=models.CASCADE, default=1)
    colección = models.ForeignKey('Colección', on_delete=models.CASCADE, default=1)
    número_de_caja = models.CharField(max_length=200, blank=True)
    carpetas = models.ManyToManyField('Carpeta', blank=True, related_name='carpetas')
    departamento = models.ManyToManyField(
        Lugar, blank=True, related_name='departamento'
    )
    municipios = models.ManyToManyField(Lugar, blank=True, related_name='municipios')
    letras = models.CharField(max_length=200, blank=True)
    legajos = models.CharField(max_length=200, blank=True)
    fechas_extremas = models.CharField(max_length=200, blank=True)
    volumen_en_metros_lineales = models.CharField(max_length=200, blank=True)
    sistema_digital = models.CharField(max_length=200, blank=True)
    descripción = RichTextField(blank=True, default='')

    def __str__(self):
        return '{}/{}/{}'.format(self.archivo, self.colección, self.número_de_caja)

Set list of options

STATUS_CHOICES = (
    ('NONE', 'Sin correcciones'),
    ('IN', 'En progreso'),
    ('DONE', 'Compitió'),
    ('FINAL', 'Competido y verificado'),
)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, blank=True)

RichTextField

from ckeditor.fields import RichTextField
RichTextField(blank=True, default='')

Migrations

Keep in mind that your models.py file is a set of instructions to Django on how to structure your database. Any changes that you make to models need to be applied to the database using manage.py makemigrations and then manage.py migrate. These commands generate a migrations file (such as ./migrations/0001_initial.py) with step-by-step instructions to update the database. You should not need to change them, but it’s good to understand the process. For a more in depth discussion of migrations, see this Real Python primer.