• 3.2
  • 5.0
  • 6.1
  • Версия документации: 3.1

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

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

Throughout this reference we’ll use the example Weblog models presented in the database query guide.

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

Чтобы создать объект модели, просто создайте ее экземпляр как любого другого класса Python:

class Model(**kwargs)

Именованные аргументы – это названия полей определенных в модели. Создание экземпляра модели не выполняет никаких запросов к базе данных; для сохранения вызовите метод save().

Примечание

You may be tempted to customize the model by overriding the __init__ method. If you do so, however, take care not to change the calling signature as any change may prevent the model instance from being saved. Rather than overriding __init__, try using one of these approaches:

  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() позволяет настроить создания экземпляра модели при загрузке данных из базы данных.

Аргумент db содержит название базы данных, из которой загружается объект, field_names содержит список загруженных полей, а values содержит значения полей из field_names. Поля в field_names расположены в таком же порядке как и values, поэтому можно использовать cls(**(zip(field_names, values))) для создания объекта. Если все поля модели присутствуют, порядок значений в values будет таким, каким их ожидает __init__(). И вы можете создать объект с помощью cls(*values). Все поля модели загружены, если cls._deferred равен False.

Помимо создания новой модели, метод 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)

В приведенном выше примере показана полная реализация from_db(), чтобы прояснить, как это делается. В этом случае можно было бы использовать вызов super() в методе from_db().

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

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. Любые кэшированные отношения удаляются из перезагруженного экземпляра.

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

Перезагрузка выполняется из базы данных, из которой объект был изначально загружен, или из базы данных по умолчанию, если база данных не была явно указана. Аргумент 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()

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

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

There are three steps involved in validating a model:

  1. Проверка полей модели - Model.clean_fields()

  2. Проверка всего объекта - Model.clean()

  3. Проверка уникальности полей - Model.validate_unique()

All three steps are performed when you call a model’s full_clean() method.

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

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

This method calls Model.clean_fields(), Model.clean(), and Model.validate_unique() (if validate_unique is True), in that order and raises a ValidationError that has a message_dict attribute containing errors from all three stages.

The optional exclude argument can be used to provide a list of field names that can be excluded from validation and cleaning. ModelForm uses this argument to exclude fields that aren’t present on your form from being validated since any errors raised could not be corrected by the user.

Обратите внимание, 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)

This method will validate all fields on your model. The optional exclude argument lets you provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.

Следующим этапов проверки в 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'),
})

Finally, full_clean() will check any unique constraints on your model.

Как вызвать ошибки проверки для конкретных полей, если эти поля не отображаются в ModelForm``

Вы не можете вызывать ошибки проверки в Model.clean() для полей, которые не отображаются в форме модели (форма может ограничивать свои поля, используя Meta.fields или Meta.exclude). Это приведет к возникновению ошибки ValueError, поскольку ошибку проверки нельзя будет связать с исключенным полем.

Чтобы обойти эту дилемму, вместо этого переопределите Model.clean_fields(), поскольку он получает список полей, исключенных из проверки. Например:

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)

This method is similar to clean_fields(), but validates all uniqueness constraints on your model instead of individual field values. The optional exclude argument allows you to provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.

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

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

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

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

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

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

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

If a model has an AutoField — an auto-incrementing primary key — then that auto-incremented value will be calculated and saved as an attribute on your object the first time you call 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) ниже.

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

Если вы используете PostgreSQL, возможно, потребуется обновить последовательность, связанную с первичным ключом; см. Ручное указание значений автоинкрементных первичных ключей.

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

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

  1. Посылается сигнал post-save. Посылается сигнал django.db.models.signals.post_save, позволяя функциям, обрабатывающим этот сигнал, выполнить какие-либо действия.

  2. Предварительная обработка данных. Метод pre_save() каждого поля вызывается для выполнения любого необходимого автоматического изменения данных. Например, поля даты/времени переопределяют pre_save() для реализации auto_now_add и auto_now.

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

    Большинство полей не требует подготовки данных. Простые типы данных, такие как числа и строки, уже „готовы к сохранению“ как объекты Python. Однако, большинство сложных типов данных требуют некоторой модификации.

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

  4. Сохранение данных в базе данных. Предварительно обработанные, подготовленные данные формируются в SQL запрос, который выполняется в базе данных.

  5. Посылается сигнал post-save. Посылается сигнал django.db.models.signals.post_save, позволяя функциям, обрабатывающим этот сигнал, выполнить какие-либо действия.

Как 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:

  • If the object’s primary key attribute is set to a value that evaluates to True (i.e., a value other than None or the empty string), Django executes an UPDATE.

  • Если первичный ключ не указан, или UPDATE ничего не обновил, Django выполнит 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

В редких случаях, может понадобиться принудительно заставить метод save() выполнить INSERT запрос вместо UPDATE. Или наоборот: обновить, при возможности, но не добавлять новую запись. В этом случае вы можете указать аргумент force_insert=True или force_update=True для метода save(). Очевидно, не правильно использовать оба аргумента вместе: вы не можете добавлять и обновлять одновременно!

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

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

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

Sometimes you’ll need to perform a simple arithmetic task on a field, such as incrementing or decrementing the current value. One way of achieving this is doing the arithmetic in Python like:

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

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

The process can be made robust, avoiding a race condition, as well as slightly faster by expressing the update relative to the original field value, rather than as an explicit assignment of a new value. Django provides F expressions for performing this kind of relative update. Using F expressions, the previous example is expressed as:

>>> 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 пропустит сохранение. Значение «Нет» приведет к обновлению всех полей.

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

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

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

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

Issues an SQL DELETE for the object. This only deletes the object in the database; the Python instance will still exist and will still have data in its fields. This method returns the number of objects deleted and a dictionary with the number of deletions per object type.

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

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

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

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

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

нельзя переносить «pickles» между версиями

Упакованные модели работают только для той версии 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__()

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

Например:

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__()

Метод __hash__ использует значение первичного ключа. На самом деле выполняется hash(obj.pk). Если первичный ключ не определен, будет вызвано исключение TypeError (иначе __hash__ разные значения перед и после сохранения объекта, что запрещено в Python).

get_absolute_url

Model.get_absolute_url()

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

Например:

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

(Хотя это код правильный и простой, но такой подход не самый лучший для создания подобных методов. Лучше использовать функцию reverse().)

Например:

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>

Идея в том что, если вы измените структуру URL-а для объекта, или просто исправите опечатку, вам не нужно исправлять его во всех местах, где этот URL используется. Просто определите его один раз в методе get_absolute_url(), и пусть остальной код использует его.

Примечание

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.

Код и шаблоны, использующие get_absolute_url(), должны иметь возможность использовать результат без обработки. Вы можете использовать функцию django.utils.encoding.iri_to_uri(), если используете unicode-строку, которая содержит не ASCII символы.

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

В дополнение к методам 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'
Changed in Django 3.1:

Support for ArrayField and RangeField was added.

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, если объект не существует.

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

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

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

В большинстве случаев переопределение или наследование get_FOO_display(), get_next_by_FOO() и get_previous_by_FOO() должно работать должным образом. Однако, поскольку они добавляются метаклассом, учитывать все возможные структуры наследования нецелесообразно. В более сложных случаях вам следует переопределить Field.contribute_to_class(), чтобы установить нужные вам методы.

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

_state

Model._state

Атрибут _state относится к объекту ModelState, который отслеживает жизненный цикл экземпляра модели.

Объект ModelState имеет два атрибута: adding, флаг, который имеет значение True, если модель еще не сохранена в базе данных, и db, строку, ссылающуюся на псевдоним базы данных, из которой был загружен или сохранен экземпляр.

Недавно созданные экземпляры имеют adding=True и db=None, поскольку они еще не сохранены. Экземпляры, полученные из QuerySet, будут иметь adding=False и db, установленные в псевдоним связанной базы данных.

Back to Top