Ссылка на экземпляр модели
В этом документе описываются подробности API Model. Он опирается на материалы, представленные в руководствах по моделям и запросам к базе данных, поэтому, вероятно, вам стоит прочитать и понять эти документы перед чтением данного.
На протяжении всего данного справочника мы будем использовать примеры моделей веб-журнала, представленные в руководстве по запросам к базе данных.
Создание объектов
Чтобы создать новый экземпляр модели, создайте его так же, как любой другой класс Python:
-
class Model(**kwargs)
Ключевые аргументы — это имена полей, которые вы определили в своей модели. Обратите внимание, что создание экземпляра модели никак не затрагивает вашу базу данных; для этого вам нужно save().
Примечание
Вы можете быть искушены настраивать модель, переопределяя метод __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)
Метод 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, 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().
Обновление объектов из базы данных
Если вы удаляете поле из экземпляра модели, повторный доступ к нему перезагружает значение из базы данных:
>>> 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(). При вызове этого метода без аргументов выполняется следующее:
- Все неотложенные поля модели обновляются до значений, которые в настоящее время присутствуют в базе данных.
- Любые кэшированные отношения очищаются из перезагруженного экземпляра.
Перезагружаются только поля модели. Другие зависящие от базы данных значения, такие как аннотации, не перезагружаются. Также не очищаются атрибуты @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)
-
Model.get_deferred_fields()
Вспомогательный метод, возвращающий множество имен атрибутов всех полей, которые в настоящее время отложены для данной модели.
Валидация объектов
Валидация модели включает три этапа:
- Валидация полей модели -
Model.clean_fields() - Валидация модели в целом -
Model.clean() - Валидация уникальности полей -
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]
END_OF_DOCUMENT_MARKER Для назначения исключений конкретному полю, создайте экземпляр 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)
Этот метод аналогичен clean_fields(), но валидирует все ограничения уникальности вашей модели вместо отдельных значений полей. Необязательный аргумент exclude позволяет вам указать список имён полей, которые следует исключить из валидации. В случае неудачи валидации будет выброшено исключение ValidationError.
Обратите внимание, что если вы передадите аргумент exclude методу validate_unique(), любые ограничения 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.
Нет способа узнать значение идентификатора до вызова save(), так как это значение рассчитывается базой данных, а не Django.
Для удобства каждая модель имеет AutoField с именем id по умолчанию, если явно не указано primary_key=True для поля в модели. Дополнительная информация в документации для AutoField.
Свойство pk
-
Model.pk
Независимо от того, определяете ли вы первичный ключ самостоятельно или позволяете Django его предоставить, каждая модель будет иметь свойство pk. Оно ведёт себя как обычный атрибут модели, но на самом деле является псевдонимом для поля, являющегося первичным ключом модели. Вы можете читать и устанавливать это значение, как и любой другой атрибут, и оно обновит соответствующее поле в модели.
Явное задание значений автоинкрементируемых первичных ключей
Если у модели есть 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 абстрагирует необходимость использования INSERT или UPDATE SQL-запросов. В частности, при вызове save() и если атрибут первичного ключа объекта **не** задаёт default, Django следует этому алгоритму:
- Если атрибут первичного ключа объекта установлен на значение, которое оценивается как
True(т.е., значение, отличное отNoneили пустой строки), Django выполняетUPDATE. - Если атрибут первичного ключа объекта не установлен или
UPDATEничего не обновило (например, если первичный ключ установлен на значение, которого нет в базе данных), Django выполняетINSERT.
Если атрибут первичного ключа объекта задаёт 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(). Передача обоих параметров является ошибкой: нельзя одновременно вставлять и обновлять!
В очень редких случаях вам потребуется использовать эти параметры. 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. Если вы присваиваете или изменяете значение любого отложенного поля, поле будет добавлено к обновлённым полям.
Удаление объектов
-
Model.delete(using=DEFAULT_DB_ALIAS, keep_parents=False)
Выполняет SQL DELETE для объекта. Это удаляет объект только в базе данных; экземпляр Python всё ещё будет существовать и в его полях всё ещё будут данные. Этот метод возвращает количество удалённых объектов и словарь с количеством удалений по каждому типу объектов.
Для получения более подробной информации, включая удаление объектов по группам, см. Удаление объектов.
Если вы хотите настроить поведение удаления, вы можете переопределить метод delete(). Подробнее см. в Переопределении предопределённых методов модели.
Иногда при наследстве с множественной таблицей вы можете захотеть удалить только данные дочерней модели. Указание keep_parents=True сохранит данные родительской модели.
Сериализация объектов
Когда вы pickle модель, её текущее состояние сериализуется. При рассериализации он будет содержать экземпляр модели на момент сериализации, а не данные, которые сейчас находятся в базе данных.
Другие методы экземпляров модели
Несколько методов объектов имеют специальные цели.
__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__()
Метод равенства определяется таким образом, что экземпляры с одинаковым значением первичного ключа и тем же конкретным классом считаются равными, за исключением того, что экземпляры с значением первичного ключа 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__()
Метод __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.views.details', args=[str(self.id)])
Одно из мест, где 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, RFC 2396#section-2) и быть закодированной в 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'
Была добавлена поддержка ArrayField и RangeField.
-
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на псевдоним связанной базы данных.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/3.2/ref/models/instances/