Spec-Zone.ru › Django 1.8

Ссылка на экземпляр модели

В этом документе описываются подробности API Model. Он основан на материалах, представленных в руководствах моделей и запросов к базе данных, поэтому вам, вероятно, стоит прочитать и понять эти документы перед чтением этого.

В этом руководстве мы будем использовать представленные в руководстве по запросам к базе данных примеры моделей Weblog.

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

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

class Model(**kwargs) [source]

Ключевые аргументы — это просто имена полей, которые вы определили в своей модели. Обратите внимание, что создание экземпляра модели никак не затрагивает вашу базу данных; для этого вам нужно save().

Примечание

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

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

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

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

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

classmethod Model.from_db(db, field_names, values) [source]

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

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

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

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

@classmethod
def from_db(cls, db, field_names, values):
    # default implementation of from_db() (could be replaced
    # with super())
    if cls._deferred:
        instance = cls(**zip(field_names, values))
    else:
        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().

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

Model.refresh_from_db(using=None, fields=None, **kwargs) [source]

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

  1. Все поля модели, не отложенные, обновляются до значений, которые в данный момент присутствуют в базе данных.
  2. Предыдущие загруженные связанные экземпляры, для которых значение отношения больше недействительно, удаляются из перезагруженного экземпляра. Например, если у вас есть внешний ключ от перезагруженного экземпляра к другой модели с именем Author, то если obj.author_id != obj.author.id, obj.author будут удалены, и при следующем обращении они будут перезагружены со значением obj.author_id.

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

Перезагрузка происходит из базы данных, из которой был загружен экземпляр, или из базы данных по умолчанию, если экземпляр не был загружен из базы данных. Аргумент 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(ExampleModel, self).refresh_from_db(using, fields, **kwargs)
Model.get_deferred_fields() [source]

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

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

Валидация модели включает три этапа:

  1. Валидация полей модели - Model.clean_fields()
  2. Валидация модели в целом - Model.clean()
  3. Валидация уникальности поля - Model.validate_unique()

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

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

Model.full_clean(exclude=None, validate_unique=True) [source]

Этот метод вызывает 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) [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 ugettext_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 ValidationError, NON_FIELD_ERRORS
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() проверит все уникальные ограничения вашей модели.

Model.validate_unique(exclude=None) [source]

Этот метод похож на 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) [source]

Если вы хотите настроить поведение сохранения, вы можете переопределить этот save() метод. См. Переопределение предопределённых методов модели для получения дополнительной информации.

Процесс сохранения модели также имеет некоторые тонкости; см. разделы ниже.

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

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

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

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

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

Свойство pk

Model.pk

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

Явное указание значений автопервичных ключей

Если модель имеет 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 ниже, для объяснения этого.

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

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

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

  1. Отправка сигнала до сохранения. Сигнал сигнал django.db.models.signals.pre_save отправляется, позволяя любому функции, подпишному на этот сигнал, выполнить некоторое пользовательское действие.
  2. Предварительная обработка данных. Каждое поле объекта получает запрос выполнить любые автоматические изменения данных, которые может потребоваться выполнить полю.

    Большинство полей не выполняют предварительную обработку — данные поля сохраняются без изменений. Предварительная обработка используется только для полей, которые имеют специальное поведение. Например, если ваша модель имеет DateField с auto_now=True, фаза предварительного сохранения изменит данные в объекте, чтобы убедиться, что поле даты содержит текущую метку даты. (В нашей документации пока нет списка всех полей со «специальным поведением».)

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

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

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

  4. Вставка данных в базу данных. Предварительно обработанные, подготовленные данные затем объединяются в SQL-запрос для вставки в базу данных.
  5. Отправка сигнала после сохранения. Сигнал django.db.models.signals.post_save отправляется, позволяя любым функциям, подписанным на этот сигнал, выполнить некоторые пользовательские действия.

Как Django определяет UPDATE или INSERT

Вы могли заметить, что объекты базы данных Django используют один и тот же метод save() для создания и изменения объектов. Django абстрагирует необходимость использования INSERT или UPDATE SQL-запросов. В частности, при вызове save(), Django следует этому алгоритму:

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

Обновление атрибутов на основе существующих полей

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

>>> 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) [source]

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

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

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

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

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

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

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

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

Другие методы экземпляров модели

Некоторые методы объектов имеют специальные цели.

Примечание

В Python 3, так как все строки по умолчанию рассматриваются как Unicode, используйте только метод __str__() (метод __unicode__() устарел). Если вам нужна совместимость с Python 2, вы можете декорировать свой класс модели с помощью python_2_unicode_compatible().

__unicode__

Model.__unicode__()

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

Например:

from django.db import models

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

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

Если вы определили метод __unicode__() в вашей модели, но не метод __str__(), Django автоматически предоставит вам метод __str__(), который вызывает __unicode__() и затем правильно преобразует результат в строку UTF-8. Это рекомендуемая практика разработки: определять только __unicode__() и позволять Django заботиться о преобразовании в строковые объекты при необходимости.

__str__

Model.__str__() [source]

Метод __str__() вызывается всякий раз, когда вы вызываете str() для объекта. В Python 3 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)

В Python 2 основное использование __str__ непосредственно внутри Django — это когда вывод repr() модели отображается где-либо (например, в отладочном выводе). Вам не обязательно помещать методы __str__() повсюду, если у вас есть осмысленные методы __unicode__().

Предыдущий пример с __unicode__() можно аналогичным образом записать с использованием __str__() следующим образом:

from django.db import models
from django.utils.encoding import force_bytes

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

    def __str__(self):
        # Note use of django.utils.encoding.force_bytes() here because
        # first_name and last_name will be unicode strings.
        return force_bytes('%s %s' % (self.first_name, self.last_name))

__eq__

Model.__eq__() [source]

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

Например:

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

MyModel(id=1) == MyModel(id=1)
MyModel(id=1) == MyProxyModel(id=1)
MyModel(id=1) != MultitableInherited(id=1)
MyModel(id=1) != MyModel(id=2)

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

__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.core.urlresolvers 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) и быть закодированной в URL, если необходимо.

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

Дополнительные методы экземпляров

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

Model.get_FOO_display()

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

Например:

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
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 при необходимости.

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

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

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

DoesNotExist

exception Model.DoesNotExist

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

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

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/ref/models/instances/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API