Ссылка на экземпляр модели
В этом документе описываются детали API Model. Он опирается на материалы, представленные в руководствах по моделям и запросам к базе данных, поэтому вам, вероятно, следует прочитать и понять эти документы перед чтением этого.
В этом справочнике мы будем использовать примеры моделей блога, представленные в руководстве по запросам к базе данных.
Создание объектов
Чтобы создать новый экземпляр модели, инициализируйте его как любой другой класс Python:
-
class Model(**kwargs)[source]
Используемые ключевые аргументы — это имена полей, которые вы определили в своей модели. Обратите внимание, что инициализация модели никак не влияет на вашу базу данных; для этого вам необходимо save().
Примечание
Вы можете захотеть настроить модель, переопределив метод __init__. Однако будьте внимательны, не изменяйте сигнатуру вызова, так как любое изменение может помешать сохранению экземпляра модели. Кроме того, обращение к полям модели внутри __init__ в некоторых случаях может привести к ошибкам бесконечной рекурсии. Вместо переопределения __init__, попробуйте использовать один из этих подходов:
-
Добавьте статический метод в класс модели:
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") -
Добавьте метод в пользовательский менеджер (обычно предпочтительнее):
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)[source]
Метод from_db() можно использовать для настройки создания экземпляра модели при загрузке из базы данных.
Аргумент db содержит псевдоним базы данных, из которой загружается модель, field_names содержит имена всех загруженных полей, а values содержит загруженные значения для каждого поля в field_names. Значения field_names расположены в том же порядке, что и values. Если все поля модели присутствуют, то values гарантированно находятся в порядке, который ожидает __init__(). То есть экземпляр можно создать с помощью cls(*values). Если какие-либо поля отложены, они не появятся в field_names. В этом случае присвойте значение django.db.models.DEFERRED каждому из отсутствующих полей.
Помимо создания новой модели, метод 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, (value for value in values if value is not DEFERRED))
)
return instance
def save(self, **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(**kwargs)
Приведенный выше пример демонстрирует полную реализацию from_db(), чтобы прояснить, как это делается. В этом случае можно было бы использовать вызов super() в методе from_db().
Обновление объектов из базы данных
Если вы удалите поле из экземпляра модели, обращение к нему снова перезагрузит значение из базы данных:
>>> obj = MyModel.objects.first() >>> del obj.field >>> obj.field # Loads the field from the database
-
Model.refresh_from_db(using=None, fields=None, from_queryset=None)[source]
-
Model.arefresh_from_db(using=None, fields=None, from_queryset=None)
Асинхронная версия: arefresh_from_db()
Если вам нужно перезагрузить значения модели из базы данных, вы можете использовать метод refresh_from_db(). При вызове этого метода без аргументов выполняется следующее:
- Все поля модели, не отложенные, обновляются до значений, текущих в базе данных.
- Все кэшированные связи очищаются из перезагруженного экземпляра.
Из базы данных перезагружаются только поля модели. Другие значения, зависящие от базы данных, такие как аннотации, не перезагружаются. Любые атрибуты @cached_property также не очищаются.
Перезагрузка происходит из базы данных, из которой был загружен экземпляр, или из базы данных по умолчанию, если экземпляр не был загружен из базы данных. Аргумент 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)
Обратите внимание, что при доступе к отложенным полям загрузка значения отложенного поля происходит через этот метод. Таким образом, можно настроить способ загрузки отложенных данных. Приведенный ниже пример показывает, как перезагрузить все поля экземпляра при перезагрузке отложенного поля:
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)
Аргумент from_queryset позволяет использовать другой набор запросов, отличного от созданного из _base_manager. Это дает вам больший контроль над тем, как модель перезагружается. Например, если ваша модель использует мягкое удаление, вы можете заставить refresh_from_db() учитывать это:
obj.refresh_from_db(from_queryset=MyModel.active_objects.all())
Можно кэшировать связанные объекты, которые в противном случае были бы удалены из перезагруженного экземпляра:
obj.refresh_from_db(from_queryset=MyModel.objects.select_related("related_field"))
Можно заблокировать строку до конца транзакции перед перезагрузкой значений модели:
obj.refresh_from_db(from_queryset=MyModel.objects.select_for_update())
Добавлен аргумент from_queryset.
-
Model.get_deferred_fields()[source]
Вспомогательный метод, возвращающий набор имен атрибутов всех полей, которые в данный момент отложены для данной модели.
Проверка объектов
Для проверки модели используются четыре шага:
- Проверка полей модели -
Model.clean_fields() - Проверка модели в целом -
Model.clean() - Проверка уникальности полей -
Model.validate_unique() - Проверка ограничений -
Model.validate_constraints()
Все четыре шага выполняются при вызове метода модели full_clean().
При использовании ModelForm, вызов is_valid() выполнит эти шаги проверки для всех полей, включённых в форму. Дополнительная информация содержится в документации по ModelForm. Вам нужно вызывать метод модели full_clean() только в том случае, если вы планируете самостоятельно обрабатывать ошибки проверки или если вы исключили поля из ModelForm, которые требуют проверки.
-
Model.full_clean(exclude=None, validate_unique=True, validate_constraints=True)[source]
Этот метод вызывает Model.clean_fields(), Model.clean(), Model.validate_unique() (если validate_unique равно True) и Model.validate_constraints() (если validate_constraints равно 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)[source]
Этот метод проверит все поля вашей модели. Необязательный аргумент exclude позволяет указать список имён полей, которые нужно исключить из проверки. Он вызовет исключение ValidationError, если какая-либо проверка поля завершится неудачно.
Второй шаг full_clean() – вызов Model.clean(). Этот метод должен быть переопределён для выполнения пользовательской проверки модели.
-
Model.clean()[source]
Этот метод следует использовать для предоставления пользовательской проверки модели и изменения атрибутов модели по мере необходимости. Например, можно использовать его для автоматического предоставления значения поля или для проверки, требующей доступа к более чем одному полю:
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() проверит уникальные ограничения вашей модели.
Как вызвать ошибки проверки, специфичные для поля, если эти поля не отображаются в форме 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)[source]
Этот метод похож на clean_fields(), но проверяет ограничения уникальности, определённые с помощью Field.unique, Field.unique_for_date, Field.unique_for_month, Field.unique_for_year или Meta.unique_together в вашей модели вместо отдельных значений полей. Необязательный аргумент exclude позволяет указать список имён полей, которые нужно исключить из проверки. Он вызовет исключение ValidationError, если какая-либо проверка завершится неудачно.
UniqueConstraint которые определены в Meta.constraints проверяются Model.validate_constraints().
Обратите внимание, что если вы передадите аргумент exclude методу validate_unique(), то любое ограничение unique_together, включающее одно из переданных полей, не будет проверено.
И наконец, full_clean() проверит любые другие ограничения вашей модели.
-
Model.validate_constraints(exclude=None)[source]
Этот метод проверяет все ограничения, определенные в Meta.constraints. Необязательный аргумент exclude позволяет указать список имен полей, которые следует исключить из проверки. Будет выброшено исключение ValidationError, если какие-либо ограничения не пройдут проверку.
Сохранение объектов
Чтобы сохранить объект обратно в базу данных, вызовите save():
-
Model.save(*, force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)[source]
-
Model.asave(*, force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)
Асинхронная версия: asave()
Подробную информацию об использовании аргументов force_insert и force_update см. в разделе Принудительное выполнение INSERT или UPDATE. Подробности об аргументе update_fields можно найти в разделе Указание полей для сохранения.
Если вам требуется настраиваемое поведение сохранения, вы можете переопределить этот save() метод. Подробнее см. в разделе Переопределение предопределённых методов модели.
Процесс сохранения модели также имеет некоторые нюансы; см. разделы ниже.
Устарело начиная с версии 5.1: Поддержка позиционных аргументов устарела.
Автоинкрементируемые первичные ключи
Если модель имеет 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.
Нет способа узнать значение идентификатора до вызова save(), потому что это значение рассчитывается вашей базой данных, а не Django.
Для удобства каждая модель имеет AutoField с именем id по умолчанию, если явно не указано primary_key=True в поле вашей модели. Подробнее см. документацию по AutoField.
Свойство pk
-
Model.pk
Независимо от того, определяете ли вы первичный ключ самостоятельно или позволяете Django его сгенерировать, каждая модель будет иметь свойство pk. Оно ведет себя как обычный атрибут модели, но фактически является псевдонимом для поля или полей, составляющих первичный ключ модели. Вы можете читать и устанавливать это значение так же, как и любой другой атрибут, и оно будет обновлять соответствующие поля в модели.
Добавлена поддержка первичного ключа, составленного из нескольких полей, с помощью CompositePrimaryKey.
Явное указание значений авто-первичных ключей
Если модель имеет AutoField, но вы хотите явно указать ID нового объекта при сохранении, укажите его явно перед сохранением, а не полагайтесь на автоматическое назначение 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!
См. Как Django определяет UPDATE или INSERT, ниже, чтобы понять причину этого.
Явное указание значений авто-первичных ключей в основном полезно для массового сохранения объектов, когда вы уверены, что столкновений по первичным ключам не будет.
Если вы используете PostgreSQL, последовательность, связанную с первичным ключом, может потребоваться обновить; см. Указание значений автоинкрементируемых первичных ключей вручную.
Что происходит при сохранении?
При сохранении объекта Django выполняет следующие действия:
-
Отправка сигнала pre-save. Сигнал
pre_saveотправляется, позволяя функциям, подписчикам на этот сигнал, выполнить какие-либо действия. -
Предварительная обработка данных. Вызывается метод
pre_save()каждого поля для выполнения необходимых автоматических изменений данных. Например, поля даты/времени переопределяютpre_save()для реализацииauto_now_addиauto_now. -
Подготовка данных для базы данных. Вызывается метод
get_db_prep_save()каждого поля, чтобы получить текущее значение в формате, подходящем для записи в базу данных.Большинству полей не требуется подготовка данных. Простые типы данных, такие как целые числа и строки, «готовы к записи» как объект Python. Однако более сложные типы данных часто требуют некоторой модификации.
Например, поля
DateFieldиспользуют объект Pythondatetimeдля хранения данных. Базы данных не хранят объектыdatetime, поэтому значение поля должно быть преобразовано в строку даты в формате ISO для вставки в базу данных. - Вставка данных в базу данных. Подготовленные данные собираются в SQL-запрос для вставки в базу данных.
-
Отправка сигнала post-save. Отправляется сигнал
post_save, позволяя функциям, подписчикам на этот сигнал, выполнить какие-либо действия.
Как Django определяет UPDATE или INSERT
Вы, возможно, заметили, что объекты базы данных Django используют один и тот же метод save() для создания и изменения объектов. Django абстрагирует необходимость использования операторов SQL INSERT или UPDATE. В частности, когда вы вызываете save(), и атрибут первичного ключа объекта не определяет default или db_default, Django выполняет следующий алгоритм:
- Если атрибут первичного ключа объекта имеет значение, отличное от
None, Django выполняет операциюUPDATE. - Если атрибут первичного ключа объекта не задан или если
UPDATEничего не изменило (например, если первичный ключ задан на значение, которого нет в базе данных), Django выполняет операциюINSERT.
Если атрибут первичного ключа объекта определяет default или db_default, то Django выполняет операцию UPDATE, если это существующая модель и первичный ключ задан на значение, которое существует в базе данных. В противном случае Django выполняет операцию INSERT.
Важно помнить, что при сохранении новых объектов не следует явно указывать значение первичного ключа, если вы не можете гарантировать, что это значение свободно. Более подробная информация об этом нюансе приведена в разделе Явное указание значений первичных ключей с автоинкрементом выше и в разделе Принудительное выполнение INSERT или UPDATE ниже.
В Django 1.5 и ранее Django выполнял SELECT, когда атрибут первичного ключа был задан. Если SELECT находил строку, то Django выполнял UPDATE, иначе выполнял INSERT. Старый алгоритм приводит к одной дополнительной запросу в случае UPDATE. Есть некоторые редкие случаи, когда база данных не сообщает о том, что строка была обновлена, даже если база данных содержит строку для значения первичного ключа объекта. Примером является триггер PostgreSQL ON UPDATE, который возвращает NULL. В таких случаях можно вернуться к старому алгоритму, установив значение опции select_on_save на True.
Принудительное выполнение INSERT или UPDATE
В некоторых редких случаях необходимо заставить метод save() выполнить операцию SQL INSERT, а не перейти к выполнению UPDATE. Или наоборот: обновить, если возможно, но не вставлять новую строку. В таких случаях можно передать параметры force_insert=True или force_update=True методу save(). Передача обоих параметров является ошибкой: вы не можете одновременно вставлять и обновлять!
При использовании наследования моделей с несколькими таблицами также можно передать кортеж родительских классов в force_insert для принудительного выполнения операторов INSERT для каждого базового класса. Например:
Restaurant(pk=1, name="Bob's Cafe").save(force_insert=(Place,)) Restaurant(pk=1, name="Bob's Cafe", rating=4).save(force_insert=(Place, Rating))
Вы можете передать force_insert=(models.Model,) для принудительного выполнения оператора INSERT для всех родительских классов. По умолчанию force_insert=True только принуждает вставку новой строки для текущей модели.
В большинстве случаев вам не потребуется использовать эти параметры. Django почти всегда выполняет правильные действия, и попытка переопределить их приведёт к ошибкам, которые трудно отследить. Эта функция предназначена только для продвинутого использования.
Использование update_fields принудит обновление аналогично force_update.
Обновление атрибутов на основе существующих полей
Иногда необходимо выполнить простое арифметическое действие над полем, например, увеличение или уменьшение текущего значения. Один из способов добиться этого — выполнить арифметику на Python, например:
>>> product = Product.objects.get(name="Venezuelan Beaver Cheese") >>> product.number_sold += 1 >>> product.save()
Если старое значение поля number_sold, полученное из базы данных, было 10, то значение 11 будет записано обратно в базу данных.
Процесс можно сделать более надёжным, избегая гонки, а также немного быстрее, выразив обновление относительно исходного значения поля, а не как явное присваивание нового значения. Django предоставляет F expressions для выполнения такого рода относительного обновления. Используя F expressions, предыдущий пример выражается так:
>>> from django.db.models import F
>>> product = Product.objects.get(name="Venezuelan Beaver Cheese")
>>> product.number_sold = F("number_sold") + 1
>>> product.save()
Для получения более подробной информации см. документацию по F expressions и их использование в запросах обновления.
Указание полей для сохранения
Если save() получает список имён полей в аргументе ключевого слова update_fields, будут обновлены только поля, указанные в этом списке. Это может быть желательно, если вы хотите обновить только одно или несколько полей объекта. Будет небольшая выгода в производительности, если не обновлять все поля модели в базе данных. Например:
product.name = "Name changed again" product.save(update_fields=["name"])
Аргумент update_fields может быть любым итерируемым объектом, содержащим строки. Пустой update_fields итерируемый объект пропустит сохранение. Значение None выполнит обновление всех полей.
Указание update_fields принудит обновление.
При сохранении модели, полученной через отложенную загрузку модели (only() или defer()), будут обновлены только поля, загруженные из базы данных. В этом случае происходит автоматическое update_fields. Если вы присваиваете или изменяете значение любого отложенного поля, поле будет добавлено в список обновляемых полей.
Field.pre_save() и update_fields
Если update_fields передано, вызываются только методы pre_save() для update_fields. Например, это означает, что поля даты/времени с auto_now=True не будут обновлены, если они не включены в update_fields.
Удаление объектов
-
Model.delete(using=DEFAULT_DB_ALIAS, keep_parents=False)[source]
-
Model.adelete(using=DEFAULT_DB_ALIAS, keep_parents=False)
Асинхронная версия: adelete()
Выполняет операцию SQL DELETE для объекта. Это удаляет объект только в базе данных; экземпляр Python всё ещё будет существовать и содержать данные в своих полях, за исключением первичного ключа, установленного на None. Этот метод возвращает количество удалённых объектов и словарь с количеством удалений по каждому типу объекта.
Для получения более подробной информации, включая удаление объектов в пакетном режиме, см. Удаление объектов.
Если вам требуется настраиваемое поведение при удалении, вы можете переопределить метод delete(). Подробнее см. в Переопределение предопределённых методов модели.
Иногда при наследовании моделей с несколькими таблицами вам может понадобиться удалить только данные дочерней модели. Указание keep_parents=True сохранит данные родительской модели.
Сериализация объектов
При pickle модели, её текущее состояние сериализуется. При десериализации она будет содержать экземпляр модели на момент её сериализации, а не данные, которые в данный момент находятся в базе данных.
Другие методы экземпляра модели
Некоторые методы объекта имеют специальные назначения.
__str__()
-
Model.__str__()[source]
Метод __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 f"{self.first_name} {self.last_name}"
__eq__()
-
Model.__eq__()[source]
Метод равенства определён таким образом, что экземпляры с одинаковым значением первичного ключа и одинаковым конкретным классом считаются равными, за исключением экземпляров с значением первичного ключа None, которые не равны ничему, кроме себя. Для прокси-моделей конкретный класс определяется как первый не-прокси родитель модели; для всех остальных моделей он просто класс модели.
Например:
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__()[source]
Метод __hash__() основан на значении первичного ключа экземпляра. Он фактически hash(obj.pk). Если у экземпляра нет значения первичного ключа, будет поднята ошибка TypeError (иначе метод __hash__() возвращал бы разные значения до и после сохранения экземпляра, но изменение значения __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-detail", kwargs={"pk": self.pk})
Одно из мест, где Django использует get_absolute_url(), — это приложение администрирования. Если объект определяет этот метод, страница редактирования объекта будет содержать ссылку «Просмотреть на сайте», которая переведёт вас напрямую к публичной просмотровой странице объекта, как задано get_absolute_url().
Аналогично, некоторые другие части Django, такие как фреймворк лент новостей, используют get_absolute_url() при его определении. Если для экземпляров вашей модели имеет смысл иметь уникальную 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(), и пусть весь остальной код обращается к этому одному месту.
Примечание
Строка, возвращаемая из get_absolute_url(), должна содержать только символы ASCII (требуется спецификацией URI, Раздел 2 RFC 3986) и быть закодированной в URL, если необходимо.
Код и шаблоны, вызывающие get_absolute_url(), должны иметь возможность использовать результат напрямую без дальнейшей обработки. Вы можете использовать функцию django.utils.encoding.iri_to_uri(), чтобы помочь в этом, если вы используете строки, содержащие символы за пределами диапазона 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'
-
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, установленные на псевдоним связанной базы данных.
_is_pk_set()
-
Model._is_pk_set()[source]
Метод _is_pk_set() возвращает, установлен ли pk экземпляра модели. Он абстрагирует определение первичного ключа модели, обеспечивая согласованное поведение независимо от конкретной конфигурации pk.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.2/ref/models/instances/