Ссылка на экземпляр модели ¶
В этом документе подробно описывается API объектов Model
. Он дополняет содержимое, представленное в руководствах по моделям и запросах к базе данных , поэтому рекомендуется прочитать и понять их, прежде чем читать это.
В этом справочнике мы будем использовать образцы шаблонов веб-журнала, показанные в Руководстве по запросам базы данных .
Создание объектов ¶
Чтобы создать новый экземпляр модели, создайте его, как любой другой класс Python:
-
класс
Model
( ** kwargs ) ¶
Именованные параметры - это имена полей, определенных в шаблоне. Обратите внимание, что создание экземпляра шаблона не влияет на базу данных; для этого необходимо зарегистрироваться save()
.
Заметка
У вас может возникнуть соблазн настроить шаблон, переопределив его метод __init__
. Однако, если вы это сделаете, будьте осторожны, чтобы не изменить подпись метода, потому что любые изменения могут заблокировать регистрацию экземпляра модели. Вместо перегрузки __init__
попробуйте использовать один из следующих подходов:
Добавьте метод
classmethod
в класс модели: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
( используется = 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]
Чтобы назначить исключение конкретному полю, создайте экземпляр 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
но вы хотите явно указать идентификатор нового объекта при его сохранении, задайте его явно перед сохранением, а не полагайтесь на автоматическое присвоение идентификатора:
>>> 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 выполняет следующие шаги:
Передайте сигнал перед записью. Сигнал
django.db.models.signals.pre_save
отправляется, позволяя любой функции, слушающей этот сигнал, предпринять действия.Подготовка данных. Метод
pre_save()
каждого поля вызывается для выполнения любого возможного автоматического изменения данных. Например, поля даты / времени переопределяют,pre_save()
чтобы реализоватьauto_now_add
иauto_now
.Подготовка данных для базы данных. Метод
get_db_prep_save()
каждого поля должен предоставлять свое текущее значение в типе данных, который может быть записан в базу данных.Большинство полей не требуют подготовки данных. Простые типы данных, такие как целые числа или строки, «готовы к записи» как объект Python. Однако более сложные типы данных часто нуждаются в некоторой модификации.
Например, поля
DateField
используют объект Pythondatetime
для хранения своих данных. Базы данных не могут хранить объектыdatetime
, поэтому значение поля необходимо преобразовать в строку даты в формате ISO, чтобы вставить в базу данных.Вставка данных в базу данных. Предварительно обработанные и подготовленные данные преобразуются в оператор SQL для вставки в базу данных.
Выходной сигнал после записи. Сигнал
django.db.models.signals.post_save
отправляется, позволяя любой функции, слушающей этот сигнал, предпринять действия.
Как Django отличает UPDATE от INSERT ¶
Вы могли заметить, что объекты базы данных Django используют один и тот же метод save()
для создания или изменения объектов. Уровень абстракции Django избавляет от необходимости различать SQL INSERT
и UPDATE
. В частности, при вызове, когда save()
атрибут первичного ключа объекта не устанавливает значение default
, Django следует следующему алгоритму:
- Если для атрибута первичного ключа объекта установлено значение, эквивалентное
True
(то есть значение, отличное отNone
или пустая строка), Django выполняетUPDATE
инструкцию (update). - Если атрибут первичного ключа объекта не определен или если инструкция
UPDATE
ничего не обновила (например, если первичный ключ установлен на значение, которое не существует в базе данных ), Django выполняет запросINSERT
.
Если атрибут первичного ключа объекта устанавливает значение по умолчанию default
, Django выполняет инструкцию, UPDATE
если это существующий экземпляр модели и для его первичного ключа установлено значение, существующее в базе данных. , В противном случае Django выполняет инструкцию INSERT
.
Сложность здесь в том, чтобы не указывать явно значение первичного ключа при регистрации новых объектов, если вы не можете гарантировать, что этот первичный ключ свободен. Дополнительные сведения об этом нюансе см. В разделах «Явная установка значений первичного ключа» выше и « Ограничение для вставки или обновления» ниже.
До Django 1.5 Django делал ошибку, SELECT
когда был установлен атрибут первичного ключа. Если он SELECT
нашел объект, то Django сделает его UPDATE
, в противном случае он сделает один INSERT
. Этот старый алгоритм произвел дополнительный запрос по делу UPDATE
. В некоторых случаях база данных может не сообщать, что строка была обновлена, даже если есть строка базы данных, которая соответствует первичному ключу объекта. Примером может служить возвращаемый триггер PostgreSQL . В таких случаях можно вернуться к предыдущему алгоритму, установив для параметра значение .ON UPDATE
NULL
select_on_save
True
Model.save()
больше не пытается найти запись в базе данных при сохранении нового экземпляра, Model
а для первичного ключа установлено значение по умолчанию; в этом случае он всегда переходит к единице INSERT
.
Ограничение вставки или обновления ¶
В редких случаях необходимо иметь возможность заставить метод 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 предоставляет некоторые средства для достижения такого рода относительного обновления. Используя des , предыдущий пример формулируется следующим образом:expressions F
expressions F
>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()
Для получения дополнительных сведений см. Документацию и их использование в запросах на обновление .expressions F
Указание полей для сохранения ¶
Передавая список имен полей в параметре update_fields
из save()
, только поля в этом списке будут обновлены. Это может быть полезно, когда необходимо обновить небольшое подмножество полей объекта. Можно ожидать небольшого увеличения производительности, если не обновлять все поля модели в базе данных. Например :
product.name = 'Name changed again'
product.save(update_fields=['name'])
Параметр update_fields
может быть любым повторяемым объектом, содержащим строки. Если последний пуст, запись не производится. Значение None
вызывает обновление всех полей.
Использование update_fields
принудительного обновления.
При сохранении модели, полученной отложенной загрузкой модели ( only()
или defer()
), обновляются только поля, загруженные из базы данных. В этом случае эффект аналогичен update_fields
автоматическому. Если вы назначаете или изменяете какое-либо из значений отложенного поля, это поле добавляется к полям, которые нужно обновить.
Удаление объектов ¶
-
Model.
delete
( используется = 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 (требование спецификации URIRFC 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
набор для псевдонима соответствующей базы данных.