4.19. Models Directory
Fat model architecture
Single File vs. Models per file
Important, add
app_label
to model'sMeta
classImportant, add
__init__.py
to themyproject/shop/models/
directoryImportant, import
from .customer import *
inmyproject/shop/models/__init__.py
4.19.1. Files and Directory Structure
shop/
├── models/
│ ├── __init__.py
│ ├── customer.py
│ ├── address.py
│ ├── order.py
│ ├── product.py
├── admin.py
├── apps.py
├── tests.py
├── views.py
4.19.2. Models
One model per file
Important, add
app_label
to model'sMeta
classUse string in
ForeignKey
to avoid circular importSupporting classes like choices, relations and helper functions, etc. can be in the same file
File: myproject/shop/models/customer.py
>>>
... from django.db import models
... from django.utils.translation import gettext_lazy as _
...
...
... class Customer(models.Model):
... firstname = models.CharField(verbose_name=_('First Name'), max_length=50)
... lastname = models.CharField(verbose_name=_('Last Name'), max_length=50, db_index=True)
... email = models.EmailField(verbose_name=_('Email'), max_length=100, null=True, blank=True, default=None, unique=True)
...
... def __str__(self):
... return f'{self.firstname} {self.lastname}'
...
... class Meta:
... app_label = 'shop'
... verbose_name = _('Customer')
... verbose_name_plural = _('Customers')
File: myproject/shop/models/address.py
>>>
... from django.db import models
... from django.utils.translation import gettext_lazy as _
...
...
... class AddressType(models.TextChoices):
... HOME = 'home', _('Home')
... WORK = 'work', _('Work')
... BILLING = 'billing', _('Billing')
... SHIPPING = 'shipping', _('Shipping')
...
...
... class Address(models.Model):
... customer = models.ForeignKey(verbose_name=_('Customer'), to='shop.Customer', on_delete=models.CASCADE, related_name='address')
... type = models.CharField(verbose_name=_('Type'), choices=AddressType, max_length=20, null=False, blank=False)
... street = models.CharField(verbose_name=_('Street'), max_length=100, null=False, blank=False)
... house = models.CharField(verbose_name=_('House Number'), max_length=20, null=False, blank=False)
... apartment = models.CharField(verbose_name=_('Apartment Number'), max_length=20, null=True, blank=True, default=None)
... postcode = models.CharField(verbose_name=_('Post Code'), max_length=20, null=False, blank=False)
... city = models.CharField(verbose_name=_('City'), max_length=100, null=False, blank=False)
... region = models.CharField(verbose_name=_('Region'), max_length=100, null=True, blank=True, default=None)
... country = models.CharField(verbose_name=_('Country'), max_length=100, null=False, blank=False)
...
... class Meta:
... app_label = 'shop'
... verbose_name = _('Address')
... verbose_name_plural = _('Addresses')
...
... def __str__(self):
... return f'{self.street} {self.house}, {self.city}'
4.19.3. Init File
Important, add
__init__.py
to themyproject/shop/models/
directoryImportant, import
from .customer import *
inmyproject/shop/models/__init__.py
File: myproject/shop/models/__init__.py
:
from .customer import *
from .address import *
from .order import *
from .product import *
4.19.4. Assignments
# TODO: Create Tests
# doctest: +SKIP_FILE
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Django Model Directory
# - Difficulty: easy
# - Lines: 4
# - Minutes: 5
# %% English
# 0. Use `myproject.demo`
# 1. Split models into separate files in `models` directory
# 2. Create `myproject/shop/models/__init__.py` and import models from files
# %% Polish
# 0. Użyj `myproject.demo`
# 1. Podziel modele na osobne pliki w katalogu `models`
# 2. Stwórz `myproject/shop/models/__init__.py` i zaimportuj modele z pliku
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ required'
"""
...