Объект модели

Этот раздел описывает Model API. Изложенный материал опирается на материал, изложенный в разделах о моделях и выполнении запросов, возможно вам следует прочитать их перед прочтением этого раздела.

В примерах будут использованы :ref:` примеры моделей web-блога <queryset-model-example>` представленные в разделе о выполнении запросов.

Создание объектов

To create a new instance of a model, instantiate it like any other Python class:

class Model(**kwargs)

The keyword arguments are the names of the fields you’ve defined on your model. Note that instantiating a model in no way touches your database; for that, you need to save().

Примечание

Возможно, вам захочется переопределить метод __init__. В таком случае не переопределяйте сигнатуру вызова этого метода, иначе объект модели может не сохраняться. Вместо переопределения __init__ лучше используйте один из следующих подходов:

  1. Добавить метод класса в модель:

    from django.db import models
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        @classmethod
        def create(cls, title):
            book = cls(title=title)
            # do something with the book
            return book
    
    book = Book.create("Pride and Prejudice")
    
  2. Добавить метод в менеджер модели(лучший вариант):

    class BookManager(models.Manager):
        def create_book(self, title):
            book = self.create(title=title)
            # do something with the book
            return book
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        objects = BookManager()
    
    book = Book.objects.create_book("Pride and Prejudice")
    

Настройка загрузки модели

classmethod Model.from_db(db, field_names, values)

Метод from_db() позволяет настроить создания экземпляра модели при загрузке данных из базы данных.

The db argument contains the database alias for the database the model is loaded from, field_names contains the names of all loaded fields, and values contains the loaded values for each field in field_names. The field_names are in the same order as the values. If all of the model’s fields are present, then values are guaranteed to be in the order __init__() expects them. That is, the instance can be created by cls(*values). If any fields are deferred, they won’t appear in field_names. In that case, assign a value of django.db.models.DEFERRED to each of the missing fields.

Кроме создания экземпляра модели метод from_db() должен установить флаги adding и db атрибута _state нового объекта модели.

В этом примере вы можете увидеть как сохранить начальные загруженные значений полей и проверять их при сохранении:

from django.db.models import DEFERRED

@classmethod
def from_db(cls, db, field_names, values):
    # Default implementation of from_db() (subject to change and could
    # be replaced with super()).
    if len(values) != len(cls._meta.concrete_fields):
        values = list(values)
        values.reverse()
        values = [
            values.pop() if f.attname in field_names else DEFERRED
            for f in cls._meta.concrete_fields
        ]
    instance = cls(*values)
    instance._state.adding = False
    instance._state.db = db
    # customization to store the original field values on the instance
    instance._loaded_values = dict(zip(field_names, values))
    return instance

def save(self, *args, **kwargs):
    # Check how the current values differ from ._loaded_values. For example,
    # prevent changing the creator_id of the model. (This example doesn't
    # support cases where 'creator_id' is deferred).
    if not self._state.adding and (
            self.creator_id != self._loaded_values['creator_id']):
        raise ValueError("Updating the value of creator isn't allowed")
    super().save(*args, **kwargs)

The example above shows a full from_db() implementation to clarify how that is done. In this case it would of course be possible to use super() call in the from_db() method.

Обновление объектов из базы данных

If you delete a field from a model instance, accessing it again reloads the value from the database:

>>> obj = MyModel.objects.first()
>>> del obj.field
>>> obj.field  # Loads the field from the database
Model.refresh_from_db(using=None, fields=None)

Если вам необходимо обновить значения модели из базы данных, вы можете использовать refresh_from_db(). Если вызвать этот метод без аргументов, произойдет следующее:

  1. Все загруженные поля модели будут обновлены значениями из базы данных.
  2. Any cached relations are cleared from the reloaded instance.

Only fields of the model are reloaded from the database. Other database-dependent values such as annotations aren’t reloaded. Any @cached_property attributes aren’t cleared either.

Перезагрузка выполняется из базы данных, из которой объект был изначально загружен, или из базы данных по умолчанию, если база данных не была явно указана. Аргумент using позволяет явно указать базу данных.

Вы можете указать какие поля загружать с помощью аргумента fields.

Например, чтобы проверить вызов метода update(), вы можете использовать следующий тест:

def test_update_result(self):
    obj = MyModel.objects.create(val=1)
    MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
    # At this point obj.val is still 1, but the value in the database
    # was updated to 2. The object's updated value needs to be reloaded
    # from the database.
    obj.refresh_from_db()
    self.assertEqual(obj.val, 2)

Обратите внимание, при доступе к отложенным(deferred) полям они загружаются этим методом. Таким образом вы можете переопределить способ загрузки отложенных полей. В этом примере мы перегружаем все поля, если загружаются отложенные поля:

class ExampleModel(models.Model):
    def refresh_from_db(self, using=None, fields=None, **kwargs):
        # fields contains the name of the deferred field to be
        # loaded.
        if fields is not None:
            fields = set(fields)
            deferred_fields = self.get_deferred_fields()
            # If any deferred field is going to be loaded
            if fields.intersection(deferred_fields):
                # then load all of them
                fields = fields.union(deferred_fields)
        super().refresh_from_db(using, fields, **kwargs)
Model.get_deferred_fields()

Возвращает список текущих отложенных полей для экземпляра модели.

Проверка объектов

Проверка объектов модели проходив в три этапа:

  1. Проверка полей модели - Model.clean_fields()
  2. Проверка всего объекта - Model.clean()
  3. Проверка уникальности полей - Model.validate_unique()

Все три этапа выполняются при вызове метода full_clean().

При использовании ModelForm, вызов is_valid() выполняет проверку для всех полей, включенных в форму. Подробности смотрите раздел о ModelForm. Вы должны использовать метод full_clean() модели только если собираетесь самостоятельно обрабатывать ошибки валидности, или если ModelForm не содержит поля, которые должны проверяться.

Model.full_clean(exclude=None, validate_unique=True)

Этот метод вызывает Model.clean_fields(), Model.clean(), и Model.validate_unique()`(если ``validate_unique`() равно True) в указанном порядке и вызывает исключение ValidationError, которое содержит атрибут message_dict с ошибками всех трех этапов проверки.

Необязательный аргумент exclude используется, чтобы исключить часть полей из проверки. ModelForm использует этот аргумент для полей не включенных в форму, так как ошибки для этих полей не могут быть исправлены пользователем.

Обратите внимание, full_clean() не вызывается при вызове метода save(). Если вы хотите выполнить проверку для созданных вами объектов модели, вам необходимо явно вызывать этот метод. Например:

from django.core.exceptions import ValidationError
try:
    article.full_clean()
except ValidationError as e:
    # Do something based on the errors contained in e.message_dict.
    # Display them to a user, or handle them programmatically.
    pass

Первым делом full_clean() выполняет проверку каждого поля.

Model.clean_fields(exclude=None)

Этот метод проверяет все поля модели. Необязательный аргумент exclude используется, чтобы исключить часть полей из проверки. Если одно из полей не пройдет проверку, будет вызвано исключение ValidationError.

Следующим этапов проверки в full_clean() будет вызов метода Model.clean(). Этот метод должен быть переопределен, если вам нужна дополнительная проверка модели.

Model.clean()

Этот метод должен быть переопределен, если вам нужна дополнительная проверка модели или изменить значения атрибутов. Для объектов, вы можете определить его для автоматического определения полей, или для проверки, которая требует значения нескольких полей:

import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError(_('Draft entries may not have a publication date.'))
        # Set the pub_date for published items if it hasn't been set already.
        if self.status == 'published' and self.pub_date is None:
            self.pub_date = datetime.date.today()

Обратите внимание, Model.full_clean(), как и метод модели clean(), не вызываются при вызове save().

Любое исключение ValidationError вызванное в Model.clean() будет сохранено со специальным ключом в словаре ошибок, NON_FIELD_ERRORS, который используется для ошибок относящихся ко всей модели, а не конкретному полю:

from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
try:
    article.full_clean()
except ValidationError as e:
    non_field_errors = e.message_dict[NON_FIELD_ERRORS]

Чтобы добавить ошибку валидации к определенному полю, создайте экземпляр ValidationError со словарем, где ключи отображают необходимые поля. Добавим к предыдущему примеру проверку поля pub_date:

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})
        ...

Если вы нашли ошибку для нескольких полей в методе Model.clean(), вы можете передать словарь с ошибками, ключи которого являются названиями полей:

raise ValidationError({
    'title': ValidationError(_('Missing title.'), code='required'),
    'pub_date': ValidationError(_('Invalid date.'), code='invalid'),
})

Также full_clean() выполняет все проверки на уникальность модели.

How to raise field-specific validation errors if those fields don’t appear in a ModelForm

You can’t raise validation errors in Model.clean() for fields that don’t appear in a model form (a form may limit its fields using Meta.fields or Meta.exclude). Doing so will raise a ValueError because the validation error won’t be able to be associated with the excluded field.

To work around this dilemma, instead override Model.clean_fields() as it receives the list of fields that are excluded from validation. For example:

class Article(models.Model):
    ...
    def clean_fields(self, exclude=None):
        super().clean_fields(exclude=exclude)
        if self.status == 'draft' and self.pub_date is not None:
            if exclude and 'status' in exclude:
                raise ValidationError(
                    _('Draft entries may not have a publication date.')
                )
            else:
                raise ValidationError({
                    'status': _(
                        'Set status to draft if there is not a '
                        'publication date.'
                     ),
                })
Model.validate_unique(exclude=None)

Этот метод похож на clean_fields(), но проверяет уникальность полей, используя все определенные правила, а не значения полей.Необязательный аргумент exclude используется, чтобы исключить часть полей из проверки. Вызывает исключение ValidationError, если поле не прошло проверку.

Заметим, при использовании аргумента exclude, все правила определенные в unique_together, включающие одно из указанных полей, не будет учитываться при проверке.

Сохранение объектов

Чтобы сохранить объект в базе данных, используйте save():

Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)

Если вы хотите изменить процесс сохранения, переопределите метод save(). Подробности в разделе Переопределение методов модели.

Процесс сохранения модели имеет ряд особенностей описанных ниже.

Автоинкрементные первичные ключи

Если модель содержит AutoField — автоинкрементный первичный ключи — его значение будет вычислено и сохранено в атрибут объекта при первом вызове метода save():

>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id     # Returns None, because b2 doesn't have an ID yet.
>>> b2.save()
>>> b2.id     # Returns the ID of your new object.

Нельзя точно сказать каким будет значение ID до вызова метода save(), так как оно вычисляется базой данных, а не Django.

Для удобства каждая модель содержит полей AutoField с названием id, если вы не указали параметр primary_key=True для поля модели. Подробности в описании AutoField.

Свойство pk

Model.pk

Независимо от того, определили вы первичный ключ самостоятельно, или позволили Django добавить его, каждая модель содержит свойство pk. Он ведет себя как обычный атрибут, но на самом деле является псевдонимом для атрибута первичного ключа. Вы можете получить или установить его значение, так же как и любого другого атрибута, при этом будет обновлено соответствующее поле модели.

Явное определение значения первичного ключа

If a model has an AutoField but you want to define a new object’s ID explicitly when saving, define it explicitly before saving, rather than relying on the auto-assignment of the ID:

>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b3.id     # Returns 3.
>>> b3.save()
>>> b3.id     # Returns 3.

Если вы определяете значение первичного автоинкрементного ключа, убедитесь что это значение не существует уже в базе данных! Если вы укажите существующее в базе значение, Django предположит что вы хотите изменить запись в базе данных, а не сохранить новую.

Учитывая пример с блогом 'Cheddar Talk' выше, этот код перезапишет предыдущий объект в базе данных:

b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save()  # Overrides the previous blog with ID=3!

О том, как это определяется, смотрите How Django knows to UPDATE vs. INSERT (FIXME) ниже.

Явное определение первичного ключа в основном полезно при сохранении множества объектов, когда вы уверенны что все значения уникальны.

If you’re using PostgreSQL, the sequence associated with the primary key might need to be updated; see Manually-specifying values of auto-incrementing primary keys.

Что происходит при сохранении?

При сохранении объекта Django выполняет следующие шаги:

  1. Emit a pre-save signal. The pre_save signal is sent, allowing any functions listening for that signal to do something.

  2. Preprocess the data. Each field’s pre_save() method is called to perform any automated data modification that’s needed. For example, the date/time fields override pre_save() to implement auto_now_add and auto_now.

  3. Prepare the data for the database. Each field’s get_db_prep_save() method is asked to provide its current value in a data type that can be written to the database.

    Most fields don’t require data preparation. Simple data types, such as integers and strings, are „ready to write“ as a Python object. However, more complex data types often require some modification.

    Например, поле DateField использует объект Python datetime для хранения значения. База данных не принимает объект datetime, поэтому значение поля должно быть преобразовано в строковое представление даты в соответствии стандарту ISO перед сохранением в базу данных.

  4. Insert the data into the database. The preprocessed, prepared data is composed into an SQL statement for insertion into the database.

  5. Emit a post-save signal. The post_save signal is sent, allowing any functions listening for that signal to do something.

Как Django определят использовать UPDATE или INSERT

You may have noticed Django database objects use the same save() method for creating and changing objects. Django abstracts the need to use INSERT or UPDATE SQL statements. Specifically, when you call save() and the object’s primary key attribute does not define a default, Django follows this algorithm:

  • Если атрибут первичного ключа объекта содержи значение равное True (например, не None или не пустая строка), Django выполняет UPDATE запрос.
  • If the object’s primary key attribute is not set or if the UPDATE didn’t update anything (e.g. if primary key is set to a value that doesn’t exist in the database), Django executes an INSERT.

If the object’s primary key attribute defines a default then Django executes an UPDATE if it is an existing model instance and primary key is set to a value that exists in the database. Otherwise, Django executes an INSERT.

Будьте осторожны, явно указывая значение первичного ключа при сохранении нового объекта, если вы не уверенны, что этот первичный ключ не используется. Более подробно об этом читайте Explicitly specifying auto-primary-key values (FIXME) и Принудительное выполнение INSERT или UPDATE.

В предыдущих версиях Django выполнялся SELECT запрос, когда первичный ключ был явно указан. Если SELECT находил строку, Django выполнял UPDATE запрос, иначе – INSERT. В результате выполнялся один лишний запрос в случае использования UPDATE. В очень редких случаях база данных не оповещает об обновлении записи, если уже есть с указанным первичным ключом. Например, тригер PostgreSQL ON UPDATE, который возвращает NULL. В таких случаях можно вернуться к старому алгоритму, указав True в select_on_save.

Changed in Django 3.0:

Model.save() no longer attempts to find a row when saving a new Model instance and a default value for the primary key is provided, and always executes an INSERT.

Принудительное выполнение INSERT или UPDATE

In some rare circumstances, it’s necessary to be able to force the save() method to perform an SQL INSERT and not fall back to doing an UPDATE. Or vice-versa: update, if possible, but not insert a new row. In these cases you can pass the force_insert=True or force_update=True parameters to the save() method. Passing both parameters is an error: you cannot both insert and update at the same time!

Вряд ли вам понадобится использовать эти параметры. Django почти всегда сделает то, что вам нужно, и переопределение такого поведения может привести к ошибкам, которые трудно отследить. Эта функция предназначена для опытных пользователей.

Использование update_fields инициирует обновление объекта, как и при вызове force_update.

Обновление значений полей

Иногда вам может понадобиться выполнить простые арифметические операции над полями, такие как увеличить или уменьшить текущее значение. Очевидный способ сделать это:

>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold += 1
>>> product.save()

Если старое значение number_sold, полученное из базы данных, равно 10, в базу данных будет записано значение 11.

Этот процесс может быть надежным, предотвращая состояния гонки, и немного быстрее, если выполнить обновление значение поля, а не явное присвоение нового значения. Django предоставляет объект F для выполнения обновления. Используя F(), следующий пример будет выглядеть таким образом:

>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()

Подробности смотрите в описании объекта F и его использование в запросах обновления.

Указываем какие поля сохранять

Если в save() передать именованный аргумент update_fields со списком полей модели, только эти поля будут обновлены. Это может пригодиться, если вы хотите обновить одно или несколько полей. Таким образом можно получить небольшой прирост в производительности. Например:

product.name = 'Name changed again'
product.save(update_fields=['name'])

update_fields может принимать любой итератор строк. Пустой update_fields пропустит сохранение. None сохранит все поля.

Указав update_fields вы инициируете редактирование записи.

Если модель была загружена не со всеми полями (через only() или defer()), только загруженные поля будут сохранены. В этом случае update_fields будет определен автоматически. Если значение поля будет изменено, оно будет добавлено в список для обновления.

Удаление объектов

Model.delete(using=DEFAULT_DB_ALIAS, keep_parents=False)

Выполняет SQL DELETE запрос для объекта. Удаляет объекты только из базы данных; объекты Python будут существовать и содержать данные. Метод возвращает количество удаленных объектов и словарь, который содержит количество удаленных объектов для каждой модели.

Подробности, включая как удалить множество объектов, смотрите в Удаление объектов.

Если вам нужно изменить процесс удаления, переопределите метод delete(). Подробности в Переопределение методов модели.

В некоторых случаях при multi-table наследовании вам может понадобиться удалить только данные дочерней модели. Передав аргумент keep_parents=True, вы сохраните данные родительской модели.

Сериализация объектов

При упаковке объекта модели с помощью pickle сохраняется текущее состояние. При распаковке объекта он содержит объект модели в состоянии на момент упаковки, а не текущее состояние в базе данных.

Вы не можете использовать объекты, упакованные на разных версиях Django

Упакованные модели работают только для той версии Django, на которой они были созданы. Если вы упаковали модель на Django версии N, нет гарантии, что вы сомжете распаковать её на Django версии N+1. Упаковка моделей не должна использоваться для долговременного архивирования объектов.

Ошибки несовместимости версий при распаковке объектом тяжело диагностировать, например сломанный объект, поэтому вызывается RuntimeWarning при попытке распаковать модель на версии Django отличной от той, которая использовалась при упаковке.

Остальные методы модели

Несколько методов имеют специальное назначение.

__str__()

Model.__str__()

Метод __str__() вызывается когда вы применяете функцию str() к объекту. Django использует str(obj) в нескольких местах. В частности, для отображения объектов в интерфейсе администратора Django и в качестве значения, вставляемого в шаблон, при отображении объекта. Поэтому, вы должны всегда возвращать в методе __str__() красивое и удобное для восприятия представление объекта.

Например:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

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

__eq__()

Model.__eq__()

The equality method is defined such that instances with the same primary key value and the same concrete class are considered equal, except that instances with a primary key value of None aren’t equal to anything except themselves. For proxy models, concrete class is defined as the model’s first non-proxy parent; for all other models it’s simply the model’s class.

Например:

from django.db import models

class MyModel(models.Model):
    id = models.AutoField(primary_key=True)

class MyProxyModel(MyModel):
    class Meta:
        proxy = True

class MultitableInherited(MyModel):
    pass

# Primary keys compared
MyModel(id=1) == MyModel(id=1)
MyModel(id=1) != MyModel(id=2)
# Primary keys are None
MyModel(id=None) != MyModel(id=None)
# Same instance
instance = MyModel(id=None)
instance == instance
# Proxy model
MyModel(id=1) == MyProxyModel(id=1)
# Multi-table inheritance
MyModel(id=1) != MultitableInherited(id=1)

__hash__()

Model.__hash__()

The __hash__() method is based on the instance’s primary key value. It is effectively hash(obj.pk). If the instance doesn’t have a primary key value then a TypeError will be raised (otherwise the __hash__() method would return different values before and after the instance is saved, but changing the __hash__() value of an instance is forbidden in Python.

get_absolute_url()

Model.get_absolute_url()

Определите метод get_absolute_url(), чтобы указать Django как вычислить URL для объекта. Метод должен вернуть строку, которая может быть использована в HTTP запросе.

Например:

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

While this code is correct and simple, it may not be the most portable way to to write this kind of method. The reverse() function is usually the best approach.

Например:

def get_absolute_url(self):
    from django.urls import reverse
    return reverse('people.views.details', args=[str(self.id)])

Django использует get_absolute_url() в интерфейсе администратора. Если объект содержит этот метод, страница редактирования объекта будет содержать ссылку «Показать на сайте», которая приведет к странице отображения объекта, ссылку на которую возвращает get_absolute_url().

Кроме того, несколько приложений Django также используют этот метод, например syndication feed framework. Если объект модели представляет какой-то уникальный URL, вам стоит определить метод get_absolute_url().

Предупреждение

При создания URL не используйте непроверенные данные от пользователя, чтобы избежать подделки ссылок или перенаправлений:

def get_absolute_url(self):
    return '/%s/' % self.name

Если self.name равен '/example.com', будет возвращен '//example.com/', являющимся правильным URL-ом относительно протокола, вместо ожидаемого '/%2Fexample.com/'.

Хорошая практика использовать get_absolute_url() в шаблонах, вместо того, чтобы «хардкодить» URL-ы. Например, это плохой подход:

<!-- BAD template code. Avoid! -->
<a href="/people/{{ object.id }}/">{{ object.name }}</a>

Этот шаблон значительно лучше:

<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

The logic here is that if you change the URL structure of your objects, even for something small like correcting a spelling error, you don’t want to have to track down every place that the URL might be created. Specify it once, in get_absolute_url() and have all your other code call that one place.

Примечание

The string you return from get_absolute_url() must contain only ASCII characters (required by the URI specification, RFC 2396#section-2) and be URL-encoded, if necessary.

Code and templates calling get_absolute_url() should be able to use the result directly without any further processing. You may wish to use the django.utils.encoding.iri_to_uri() function to help with this if you are using strings containing characters outside the ASCII range.

Дополнительные методы модели

В дополнение к методам save(), delete(), объект модели может содержать некоторые из этих методов:

Model.get_FOO_display()

Для каждого поля, которое содержит choices, объект будет иметь метод get_FOO_display(), где FOO имя поля. Этот метод возвращает удобное для восприятия название для значения поля.

Например:

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
Model.get_next_by_FOO(**kwargs)
Model.get_previous_by_FOO(**kwargs)

Для каждого поля DateField и DateTimeField, которое не содержит null=True, объект будет иметь методы get_next_by_FOO() и get_previous_by_FOO(), где FOO название поля. Они возвращают следующий и предыдущий объект в соответствии со значением этого поля, вызывая соответствующее исключение DoesNotExist, если объект не существует.

Оба метода используют менеджер по умолчанию модели. Если вам необходимо использовать свой менеджер, которые должен выполнить какую-то фильтрацию, или просто добавить дополнительную фильтрацию, в методы можно передать дополнительные аргументы, которые должны соответствовать формату операторов фильтрации.

Заметим, что в случае одинаковых значений даты, эти методы будут использовать значение первичного ключа, для определения порядка объектов. Это гарантирует, что записи не будут пропущены или дублированы. Это также означает, что вы не можете использовать эти методы для не сохраненных объектов.

Overriding extra instance methods

In most cases overriding or inheriting get_FOO_display(), get_next_by_FOO(), and get_previous_by_FOO() should work as expected. Since they are added by the metaclass however, it is not practical to account for all possible inheritance structures. In more complex cases you should override Field.contribute_to_class() to set the methods you need.

Другие атрибуты

DoesNotExist

exception Model.DoesNotExist

Это исключение вызывается ORM в нескольких случаях, например методом QuerySet.get(), если объект не найден.

Django предоставляет исключение DoesNotExist как атрибут каждой модели, чтобы можно было обработать ошибку для каждой конкретной модели, используя try/except. Это исключение наследуется от django.core.exceptions.ObjectDoesNotExist.