8. Models

8.1. Model Fields

8.2. Text fields

  • CharField

  • TextField

  • SlugField

  • URLField

8.3. Numeric fields

  • DecimalField

  • IntegerField

  • PositiveIntegerField

  • PositiveSmallIntegerField

8.4. Logic fields

  • BooleanField

8.5. Date and time fields

  • DateField

  • DateTimeField

  • DurationField

  • TimeField

8.6. File fields

  • FileField

  • ImageField

8.7. Relations

  • ForeignKeyField

  • ManyToManyField

8.8. Model field arguments

8.9. All

  • verbose_name

  • max_length

  • choices

  • validators

  • help_text

  • null

  • blank

  • default

  • db_index

8.10. Relations

  • to (ForeignKey, ManyToManyField)

  • related_name (ForeignKey, ManyToManyField)

  • on_delete (ForeignKey, ManyToManyField)

8.11. Date and time

  • auto_add (DateField, DateTimeField)

  • auto_add_now (DateField, DateTimeField)

8.12. Numeric

  • decimal_places (DecimalField)

  • max_digits (DecimalField)

8.13. Abstract Models

class Meta:
    abstract = True

8.14. Architecture

  • Fat model architecture

8.15. Single File vs. Models per file

8.16. Reverse engineering database

  • python manage.py inspectdb

8.17. Database schema migration

8.18. Makemigrations

$ python manage.py makemigrations
Migrations for 'contact':
  addressbook/contact/migrations/0001_initial.py
    - Create model Contact

8.19. Migrate

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, contact, sessions
Running migrations:
  Applying contact.0001_initial... OK

8.20. Example Model

Code 8.16. Example Model
import datetime

from django.db import models
from django.utils.translation import gettext_lazy as _


class Contact(models.Model):
    STATUS_BEST_FRIEND = 'best-friend'
    STATUS_FRIEND = 'friend'
    STATUS_ACQUAINTANCE = 'acquaintance'
    STATUS_OTHER = 'other'
    STATUS_CHOICES = [
        (STATUS_BEST_FRIEND, _('Best Friend')),
        (STATUS_FRIEND, _('Friend')),
        (STATUS_ACQUAINTANCE, _('Acquaintance')),
        (STATUS_OTHER, _('Other'))]

    GENDER_MALE = 'male'
    GENDER_FEMALE = 'female'
    GENDER_OTHER = None
    GENDER_CHOICES = [
        (GENDER_MALE, _('Male')),
        (GENDER_FEMALE, _('Female')),
        (GENDER_OTHER, _('Undisclosed'))]

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    reporter = models.ForeignKey(verbose_name=_('Reporter'), to='auth.User', on_delete=models.CASCADE, null=True, default=None)
    is_deleted = models.BooleanField(verbose_name=_('Is deleted?'), default=False)

    firstname = models.CharField(verbose_name=_('First Name'), max_length=30)
    lastname = models.CharField(verbose_name=_('Last Name'), max_length=30, db_index=True)
    date_of_birth = models.DateField(verbose_name=_('Date of birth'), null=True, blank=True, default=None)
    email = models.EmailField(verbose_name=_('Email'), null=True, blank=True, default=None)
    bio = models.TextField(verbose_name=_('Bio'), null=True, blank=True, default=None)
    image = models.ImageField(verbose_name=_('Image'), null=True, blank=True, default=None)
    status = models.CharField(verbose_name=_('Status'), max_length=30, choices=STATUS_CHOICES, null=True, blank=True, default=None)
    gender = models.CharField(verbose_name=_('Gender'), max_length=30, choices=GENDER_CHOICES, null=True, blank=True, default=None)
    friends = models.ManyToManyField(verbose_name=_('Friends'), to='contact.Contact', blank=True, default=None)

    def __str__(self):
        return f'{self.firstname} {self.lastname}'

    def get_age(self):
        if not self.date_of_birth:
            return None

        today = datetime.date.today()
        return today.year - self.date_of_birth.year


    def save(self, *args, **kwargs):
        # is called at Model.save()
        return super().save(*args, **kwargs)

    class Meta:
        verbose_name = _('Contact')
        verbose_name_plural = _('Contacts')
        unique_together = ['firstname', 'lastname']

8.21. Assignments

Code 8.17. Solution
"""
* Assignment: Address Book
* Complexity: medium
* Lines of code: 50 lines
* Time: 21 min

English:
    TODO: English Translation
    X. Run doctests - all must succeed

Polish:
    1. Stwórz projekt `addressbook`
    2. Stwórz apkę `contact`
    3. Stwórz model `Address` z polami:
        a. Typ (do wyboru typ: domowy, praca, komórka)
        b. Ulica
        c. Numer bloku
        d. Numer mieszkania
        e. Kod pocztowy
        f. Miasto
        g. Region
        h. Kraj
    4. Stwórz model `Person` z polami:
        a. Imię
        b. Nazwisko
        c. Data Urodzenia
        d. Zdjęcie
        e. Telefon (do wyboru typ: domowy, praca, komórka)
        f. Email (do wyboru typ: domowy, praca, komórka)
        g. Adres
    5. Osoba może mieć wiele adresów, telefonów i e-maili
    6. Wygeneruj panel administracyjny
    7. Można wypisać kontakty i na głównym ekranie widoczne są podstawowe pola osoby
    8. Dodaj wyszukiwarkę po nazwisku
    9. Dodaj filtrowanie po dacie urodzenia
    X. Uruchom doctesty - wszystkie muszą się powieść
"""