Django учебник Часть 3: Использование моделей
=============================================

* Назад
* Обзор: Django
* Далее

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

| Предпосылки | Django Tutorial Part 2: Creating a skeleton website. |
| --- | --- |
| Задача: | Научиться проектировать и создавать свои собственные модели, выбирая подходящие поля. |

Обзор
-----

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

В этом учебнике показано, как определить и получить доступ к моделям на примере LocalLibrary website.

Проектирование моделей LocalLibrary
-----------------------------------

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

Мы знаем, что нам нужно хранить информацию о книгах (название, резюме, автор, язык, на котором написана книга, категория, ISBN) и что у нас может быть несколько доступных экземпляров (с уникальным глобальным идентификатором, статусом доступности и т. Д.). Нам может потребоваться хранить больше информации об авторе, чем просто их имя, и могут быть несколько авторов с одинаковыми или похожими именами. Мы хотим иметь возможность сортировать информацию на основе названия книги, автора, письменного языка и категории.

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

Вы также можете использовать модели для представления параметров списка выбора (например, как выпадающий список вариантов), вместо жёсткого кодирования выбора на самом веб-сайте - это рекомендуется, когда все варианты неизвестны заранее или могут измениться. Очевидные кандидаты на модели в этом случае включают жанр книги (например, «Научная фантастика», «Французская поэзия» и т. д.) И язык (английский, французский, японский).

Как только мы определились с нашими моделями и полями, нам нужно подумать об отношениях. Django позволяет вам определять отношения, как один к одному (`OneToOneField`), один ко многим (`ForeignKey`) и многие ко многим (`ManyToManyField`).

Диаграмма ассоциации UML, приведённая ниже показывает модели, которые мы определили в этом случае (в виде блоков). Как и выше, мы создали модели для книги (общие сведения о книге), экземпляр книги (статус конкретных физических копий книги, доступных в системе) и автора.Мы также решили создать модель для жанра, чтобы можно было создавать / выбирать значения через интерфейс администратора. Мы решили не иметь модель для BookInstance: status - мы жёстко закодировали значения (LOAN\_STATUS), потому что мы не ожидаем их изменения. В каждом из полей вы можете увидеть имя модели, имена и типы полей, а также методы и их типы возврата.

На диаграмме также показаны зависимости между моделями, включая их *множители*. Множители представляют собой числа на диаграмме, показывающие минимум и максимум единиц каждой модели, которые могут присутствовать в этой связи. Например, соединительная линия между ящиками показывает, что книга и жанр связаны между собой. Цифры, близкие к модели жанра, показывают, что у книги может быть один или несколько жанров (сколько угодно), а числа на другом конце строки рядом с моделью книги показывают, что у жанра может быть ноль или более связанных книг.

![LocalLibrary Model UML - v3](/ru/docs/Learn/Server-side/Django/Models/local_library_model_uml.png)

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

Модель для начинающих
---------------------

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

### Определение модели

Модели обычно определяются в приложении **models.py**. Они реализуются как подклассы `django.db.models.Model`, и могут включать поля, методы и метаданные. В приведённом ниже фрагменте кода показана «типичная» модель, названная `MyModelName`:


```python
from django.db import models
from django.urls import reverse

class MyModelName(models.Model):
    """Типичный класс модели, производный от класса Model."""

    # Поля
    my_field_name = models.CharField(max_length=20, help_text='Введите описание поля')
    # …

    # Метаданные
    class Meta:
        ordering = ['-my\_field\_name']

    # Methods
    def get\_absolute\_url(self):
        """Возвращает URL-адрес для доступа к определенному экземпляру MyModelName."""
        return reverse('model-detail-view', args=[str(self.id)])

    def \_\_str\_\_(self):
        """Строка для представления объекта MyModelName (например, в административной панели и т.д.)."""
        return self.my_field_name
```


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

#### Поля

Модель может иметь произвольное количество полей любого типа - каждый представляет столбец данных, который мы хотим сохранить в одной из наших таблиц базы данных. Каждая запись (строка) базы данных будет состоять из одного значения каждого поля. Давайте рассмотрим приведённый выше пример:


```python
my_field_name = models.CharField(max_length=20, help_text="Введите описание поля")
```


Наш вышеприведённый пример имеет одно поле, называемое my\_`field_name`, типа `models.CharField` — что означает, что это поле будет содержать строки буквенно-цифровых символов. Типы полей назначаются с использованием определённых классов, которые определяют тип записи, которая используется для хранения данных в базе данных, а также критерии проверки, которые должны использоваться, когда значения получены из формы HTML (то есть, что составляет действительное значение). Типы полей также могут принимать аргументы, которые дополнительно определяют, как поле хранится или может использоваться. В этом случае мы даём нашему полю два аргумента:

* `max_length=20` — Указывает, что максимальная длина значения в этом поле составляет 20 символов.
* `help_text="Введите описание поля"` — предоставляет текстовую метку для отображения, чтобы помочь пользователям узнать, какое значение необходимо предоставить, когда это значение должно быть введено пользователем через HTML-форму.

Имя поля используется для обращения к нему в запросах и шаблонах. В полях также есть метка, которая задаётся как аргумент (`verbose_name`), либо выводится путём заглавной буквы первой буквы имени переменной поля и замены любых символов подчёркивания пробелом (например, `my_field_name` будет иметь метку по умолчанию *My field name*).

Порядок, в котором объявляются поля, будет влиять на их порядок по умолчанию, если модель отображается в форме (например, на сайте администратора), хотя это может быть переопределено.

##### Общие аргументы поля

Следующие общие аргументы могут использоваться при объявлении многих / разных типов полей:

* help\_text: Предоставляет текстовую метку для HTML-форм (например, на сайте администратора), как описано выше.
* verbose\_name: Удобочитаемое имя для поля, используемого в поле метки. Если не указано, Django выведет по умолчанию подробное название от имени поля.
* default: Значение по умолчанию для поля. Это может быть значение или вызываемый объект, и в этом случае объект будет вызываться каждый раз, когда создаётся новая запись.
* null: Если True, Django будет хранить пустые значения как NULL в базе данных для полей, где это уместно (CharField вместо этого сохранит пустую строку). По умолчанию используется значение False.
* blank: Если True, поле может быть пустым в ваших формах. По умолчанию используется значение False, что означает, что проверка формы Django заставит вас ввести значение. Это часто используется с null = True, потому что если вы хотите разрешить пустые значения, вы также хотите, чтобы база данных могла представлять их соответствующим образом.
* choices: Группа вариантов для этого поля. Если это предусмотрено, по умолчанию соответствующий виджет формы будет полем выбора с этими вариантами вместо стандартного текстового поля.
* primary\_key: Если True, задаёт текущее поле в качестве первичного ключа для модели (первичный ключ - это специальный столбец базы данных, предназначенный для однозначной идентификации всех разных записей таблицы). Если в качестве первичного ключа не указано поле, Django автоматически добавит для этой цели поле.

Есть много других вариантов - вы можете просмотреть full list of field options here.

##### Общие типы полей

Следующие общие аргументы могут использоваться при объявлении многих / разных типов полей:

* CharField Используется для определения строк фиксированной длины от короткой до средней. Вы должны указать max\_length для хранения данных.
* TextField используется для больших строк произвольной длины. Вы можете указать `max_length` для поля, но это используется только тогда, когда поле отображается в формах (оно не применяется на уровне базы данных).
* IntegerField это поле для хранения значений (целого числа) и для проверки введённых значений в виде целых чисел в формах.
* DateField и DateTimeField используются для хранения / представления дат и информации о дате / времени (как Python datetime.date и datetime.datetime, соответственно). Эти поля могут дополнительно объявлять (взаимоисключающие) параметры `auto_now=True` (для установки поля на текущую дату каждый раз, когда модель сохраняется), auto\_now\_add (только для установки даты, когда модель была впервые создана) и по умолчанию (чтобы установить дату по умолчанию, которую пользователь может переустановить).
* EmailField используется для хранения и проверки адресов электронной почты.
* FileField и ImageField используются для загрузки файлов и изображений соответственно ( `ImageField` просто добавляет дополнительную проверку, что загруженный файл является изображением). Они имеют параметры для определения того, как и где хранятся загруженные файлы.
* AutoField - это особый тип IntegerField, который автоматически увеличивается. Первичный ключ этого типа автоматически добавляется в вашу модель, если вы явно не укажете его.
* ForeignKey Используется для указания отношения «один ко многим» к другой модели базы данных (например, автомобиль имеет одного производителя, но производитель может делать много автомобилей). «Одна» сторона отношения - это модель, содержащая ключ.
* ManyToManyField используется для определения отношения «многие ко многим» (например, книга может иметь несколько жанров, и каждый жанр может содержать несколько книг). В нашем приложении для библиотек мы будем использовать их аналогично ForeignKeys, но их можно использовать более сложными способами для описания отношений между группами. Они имеют параметр on\_delete, чтобы определить, что происходит, когда связанная запись удаляется (например, значение `models.SET_NULL` просто установило бы значение NULL)

Существует много других типов полей, включая поля для разных типов чисел (большие целые числа, малые целые числа, дробные), логические значения, URL-адреса, slugs, уникальные идентификаторы и другие «связанные с временем» сведения (продолжительность, время и т. д.). Вы можете просмотреть full list here.

#### Метаданные

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


```python
class Meta:
    ordering = ["-my\_field\_name"]
    ...
```


Одной из наиболее полезных функций этих метаданных является управление сортировка записей, возвращаемых при запросе типа модели. Вы можете сделать это, указав соответствия названия полей для сортировки, как показано выше. Порядок будет зависеть от типа поля (поля символов отсортированы в алфавитном порядке, а поля даты отсортированы в хронологическом порядке). Как показано выше, вы можете префикс имени поля минус-символом (-), чтобы изменить порядок сортировки.

Например, если мы решили сортировать книги по умолчанию:


```python
ordering = ["title", "-pubdate"]
```


Книги будут отсортированы по алфавиту по названию, от A-Z, а затем по дате публикации внутри каждого названия, от самого нового до самого старого.

Другим распространённым атрибутом является verbose\_name, подробное имя для класса в единственной и множественной форме:


```python
verbose_name = "BetterName"
```


Другие полезные атрибуты позволяют создавать и применять новые «разрешения доступа» для модели (разрешения по умолчанию применяются автоматически), разрешить упорядочение на основе другого поля или объявить, что класс является «абстрактным» (базовый класс, для которого вы не можете создавать записи, и вместо этого будет создан для создания других моделей). Многие другие параметры метаданных управляют тем, какая база данных должна использоваться для модели и как хранятся данные (это действительно полезно, если вам нужно сопоставить модель с существующей базой данных). Полный список опций метаданных доступен здесь: Model metadata options (Django документация).

#### Методы

Модель также может иметь методы. Минимально в каждой модели вы должны определить стандартный метод класса для Python \_\_str \_\_ (), чтобы вернуть удобочитаемую строку для каждого объекта. Эта строка используется для представления отдельных записей на сайте администрирования (и в любом другом месте, где вам нужно обратиться к экземпляру модели). Часто это возвращает поле названия или имени из модели.


```python
def \_\_str\_\_(self):
    return self.field_name
```


Другим распространённым методом включения в модели Django является get\_absolute\_url (), который возвращает URL-адрес для отображения отдельных записей модели на веб-сайте (если вы определяете этот метод, тогда Django автоматически добавит кнопку «Просмотр на сайте» на экранах редактирования записей модели на сайте администратора). Типичный шаблон для get\_absolute\_url () показан ниже.


```python
def get\_absolute\_url(self):
    """
 Returns the url to access a particular instance of the model.
 """
    return reverse('model-detail-view', args=[str(self.id)])
```


**Примечание:** Примечание. Предполагается, что вы будете использовать URL-адреса, например / myapplication / mymodelname / 2, для отображения отдельных записей для вашей модели (где «2» - это идентификатор для определённой записи), вам нужно будет создать URL-карту, чтобы передать ответ и идентификатор «Образцовое представление модели» (которое будет выполнять работу, необходимую для отображения записи). Вышеуказанная функция reverse () может «перевернуть» ваш URL-адрес (в приведённом выше примере с именем «model-detail-view»), чтобы создать URL-адрес правильного формата.

Конечно, для выполнения этой работы вам всё равно придётся писать сопоставление URL-адрес, просмотр и шаблон!

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

### Управление моделью

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

#### Создание и изменение записей

Чтобы создать запись, вы можете определить экземпляр модели, а затем вызвать метод save ().


```python
# Create a new record using the model's constructor.
a_record = MyModelName(my_field_name="Instance #1")

# Save the object into the database.
a_record.save()
```


**Примечание:** Примечание. Если вы не указали какое-либо поле в качестве primary\_key, новая запись будет выдаваться автоматически, с идентификатором имени поля. Вы можете запросить это поле после сохранения указанной выше записи, и оно будет иметь значение 1.

Вы можете получить доступ к полям в этой новой записи с использованием синтаксиса точек и изменить значения. Вы должны вызвать save (), чтобы сохранить изменённые значения в базе данных.


```python
# Access model field values using Python attributes.
print(a_record.id) #should return 1 for the first record.
print(a_record.my_field_name) # should print 'Instance #1'

# Change record by modifying the fields, then calling save().
a_record.my_field_name="New Instance Name"
a_record.save()
```


#### Поиск записей

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

**Примечание:** Примечание. Объяснение того, как искать записи, используя «абстрактную» модель и имена полей, может быть немного запутанным. В приведённом ниже обсуждении мы будем ссылаться на модель книги с полями названия и жанра, где жанр также является моделью с единственным именем в поле.

Мы можем получить все записи для модели как объект QuerySet, используя `objects.all()`. QuerySet - это итерируемый объект, означающий, что он содержит несколько объектов, которые мы можем перебирать / прокручивать.


```python
all_books = Book.objects.all()
```


Метод `filter()` Django позволяет отфильтровать возвращаемый `QuerySet` для соответствия указанному текстовому или числовому полю по конкретным критериям. Например, чтобы отфильтровать книги, содержащие слово «wild» («дикие») в заголовке, а затем подсчитать их, мы могли бы сделать следующее.


```python
wild_books = Book.objects.filter(title__contains='wild')
number_wild_books = Book.objects.filter(title__contains='wild').count()
```


Соответствующие поля и тип соответствия определяются в имени параметра фильтра, используя формат: `field_name__match_type` (обратите внимание на двойное подчёркивание между заголовком выше). Выше мы фильтруем заголовок с учётом регистра. Есть много других типов совпадений, которые вы можете сделать: `icontains` (без учёта регистра), `iexact` (точное совпадение без учёта регистра), `exact` (точное совпадение с учётом регистра ) и `in`, `gt` (больше), `startswith` и т. д смотреть полный список(Django Docs, [EN]).

В некоторых случаях вам нужно будет фильтровать поле, которое определяет отношение «один ко многим» к другой модели (например, `ForeignKey`). В этом случае вы можете «индексировать» поля в связанной модели с дополнительными двойными подчёркиваниями. Так, например, чтобы фильтровать книги с определённым жанровым рисунком, вам нужно будет указывать имя в поле жанра, как показано ниже:


```python
books_containing_genre = Book.objects.filter(genre__name__icontains='fiction')  # Will match on: Fiction, Science fiction, non-fiction etc.
```


**Примечание:** Вы можете использовать символы подчёркивания (\_\_) для навигации по многим уровням отношений (ForeignKey / ManyToManyField) по своему усмотрению. Например, книга, имеющая разные типы, определяемая с использованием дополнительной связи «обложка», может иметь имя параметра: type\_\_cover\_\_name\_\_exact = 'hard'.

Существует гораздо больше возможностей для запросов, включая обратные поиски от связанных моделей, цепочки фильтров, возврат меньшего набора значений и т. д. Для получения дополнительной информации см. Making queries (Django Docs, [EN]).

Определение моделей LocalLibrary
--------------------------------

В этом разделе мы начнём определять модели для библиотеки. Откройте *models.py (в / locallibrary / catalog /)*. Шаблон в верхней части страницы импортирует модуль моделей, который содержит базовый класс модели `models.Model`, от которого наследуются наши модели.


```python
from django.db import models

# Create your models here.
```

### Модель жанра

Скопируйте приведённый ниже код модели `Genre` и вставьте его в нижнюю часть вашего файла `models.py`. Эта модель используется для хранения информации о категории книг - например, будь то художественная или документальная, роман или военно-историческая и т. д. Как уже упоминалось выше, мы создали жанр как модель, а не как свободный текст или список выбора, чтобы возможные значения могли управляться через базу данных, а не были закодированными.


```python
class Genre(models.Model):
    """
 Model representing a book genre (e.g. Science Fiction, Non Fiction).
 """
    name = models.CharField(max_length=200, help_text="Enter a book genre (e.g. Science Fiction, French Poetry etc.)")

    def \_\_str\_\_(self):
        """
 String for representing the Model object (in Admin site etc.)
 """
        return self.name
```


Модель имеет один `CharField` field (имя), которое используется для описания жанра (оно ограничено 200 символами и имеет некоторый `help_text`. В конце модели мы объявляем метод `__str__()`, который просто возвращает имя жанра, определённого конкретной записью. Verbose name не был определён, поэтому поле будет называться `Name` в формах.

### Модель книги

Скопируйте модель книги ниже и снова вставьте её в нижнюю часть файла. Модель книги представляет всю информацию о доступной книге в общем смысле, но не конкретный физический «экземпляр» или «копию» для временного использования. Модель использует CharField для представления названия книги и isbn (обратите внимание, как isbn указывает свой ярлык как «ISBN», используя первый неименованный параметр, поскольку в противном случае ярлык по умолчанию был бы «Isbn»). Модель использует TextField для summary, потому что этот текст, возможно, должен быть очень длинным.


```python
from django.urls import reverse #Used to generate URLs by reversing the URL patterns

class Book(models.Model):
    """
 Model representing a book (but not a specific copy of a book).
 """
    title = models.CharField(max_length=200)
    author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True)
    # Foreign Key used because book can only have one author, but authors can have multiple books
    # Author as a string rather than object because it hasn't been declared yet in the file.
    summary = models.TextField(max_length=1000, help_text="Enter a brief description of the book")
    isbn = models.CharField('ISBN',max_length=13, help_text='13 Character <a href="https://www.isbn-international.org/content/what-isbn">ISBN number</a>')
    genre = models.ManyToManyField(Genre, help_text="Select a genre for this book")
    # ManyToManyField used because genre can contain many books. Books can cover many genres.
    # Genre class has already been defined so we can specify the object above.

    def \_\_str\_\_(self):
        """
 String for representing the Model object.
 """
        return self.title

    def get\_absolute\_url(self):
        """
 Returns the url to access a particular book instance.
 """
        return reverse('book-detail', args=[str(self.id)])
```


Жанр представляет из себя ManyToManyField, так что книга может иметь несколько жанров, а жанр может иметь много книг. Автор объявляется через ForeignKey, поэтому в каждой книге будет только один автор, но у автора может быть много книг (на практике книга может иметь несколько авторов, но не в такой реализации!)

В обоих типах полей соответствующий класс модели объявляется как первый неименованный параметр, используя либо класс модели, либо строку, содержащую имя соответствующей модели. Вы должны использовать имя модели как строку, если связанный класс ещё не был определён в этом файле до того, как он будет указан! Другими параметрами, представляющими интерес для поля автора, являются `null=True`, которое позволяет базе данных хранить значение `Null` , если автор не выбран, и on\_delete = models. `SET_NULL` установит значение автора в Null, если связанная с автором запись будет удалена.

Модель также определяет \_\_str \_\_ (), используя поле заголовка книги для представления книги. Окончательный метод get\_absolute\_url () возвращает URL-адрес, который можно использовать для доступа к подробной записи для этой модели (для этого нам нужно будет определить сопоставление URL-адресов, в котором содержится подробная информация о книге, и определить связанное представление и шаблон ).

### Модель BookInstance

Затем скопируйте модель BookInstance (показано ниже) под другие модели. BookInstance представляет собой определённую копию книги, которую кто-то может брать взаймы, и включает информацию о том, доступна ли копия или в какой день она ожидается, «отпечаток» или сведения о версии, а также уникальный идентификатор книги в библиотеке. Теперь некоторые из полей и методов будут знакомы. Модель использует

* ForeignKey для идентификации связанной книги (в каждой книге может быть много копий, но в копии может быть только одна книга).
* CharField, для представления данных (конкретного выпуска) о книге.


```python
import uuid # Required for unique book instances

class BookInstance(models.Model):
    """
 Model representing a specific copy of a book (i.e. that can be borrowed from the library).
 """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="Unique ID for this particular book across whole library")
    book = models.ForeignKey('Book', on_delete=models.SET_NULL, null=True)
    imprint = models.CharField(max_length=200)
    due_back = models.DateField(null=True, blank=True)

    LOAN_STATUS = (
        ('m', 'Maintenance'),
        ('o', 'On loan'),
        ('a', 'Available'),
        ('r', 'Reserved'),
    )

    status = models.CharField(max_length=1, choices=LOAN_STATUS, blank=True, default='m', help_text='Book availability')

    class Meta:
        ordering = ["due\_back"]

    def \_\_str\_\_(self):
        """
 String for representing the Model object
 """
        return '%s (%s)' % (self.id,self.book.title)
```


Мы дополнительно объявляем несколько новых типов полей:

* `UUIDField` используется для поля id, чтобы установить его как primary\_key для этой модели. Этот тип поля выделяет глобальное уникальное значение для каждого экземпляра (по одному для каждой книги, которую вы можете найти в библиотеке).
* `DateField` используется для данных due\_back (при которых ожидается, что книга появится после заимствования или обслуживания). Это значение может быть blank или null (необходимо, когда книга доступна). Метаданные модели (Class Meta) используют это поле для упорядочивания записей, когда они возвращаются в запросе.
* status - это CharField, который определяет список choice/selection. Как вы можете видеть, мы определяем кортеж, содержащий кортежи пар ключ-значение и передаём его аргументу выбора. Значение в key/value паре - это отображаемое значение, которое пользователь может выбрать, а ключи - это значения, которые фактически сохраняются, если выбрана опция. Мы также установили значение по умолчанию «m» (техническое обслуживание), поскольку книги изначально будут созданы недоступными до того, как они будут храниться на полках.

Модель \_\_str \_\_ () представляет объект BookInstance, используя комбинацию его уникального идентификатора и связанного с ним заголовка книги.

**Примечание:** Примечание. Немного Python:

* Значение, возвращаемое \_\_str \_\_ (), является форматированной строкой. В строке мы используем % S для объявления 'placeholders'. После строки укажем %, а затем кортеж, содержащий значения, которые будут вставлены в заполнители. Если у вас просто один заполнитель, вы можете опустить кортеж - например, 'Моё значение:% S' % переменная.
 Обратите также внимание на то, что, хотя этот подход совершенно применим, но он более не является предпочтительным. Начиная с Python 3, вы должны использовать метод format, например. '{0} ({1})'.format (self.id, self.book.title). Вы можете узнать больше об этом здесь.

### Модель автора

Скопируйте модель автора (показано ниже) под существующим кодом в models.py.

Теперь все поля/методы должны быть знакомы. Модель определяет автора как имя, фамилию, дату рождения и (необязательную) дату смерти. Он указывает, что по умолчанию \_\_str \_\_ () возвращает имя в фамилии, порядковый номер первого имени. Метод get\_absolute\_url () отменяет сопоставление URL-адреса автора с целью получения URL-адреса для отображения отдельного автора.


```python
class Author(models.Model):
    """
 Model representing an author.
 """
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    date_of_birth = models.DateField(null=True, blank=True)
    date_of_death = models.DateField('Died', null=True, blank=True)

    def get\_absolute\_url(self):
        """
 Returns the url to access a particular author instance.
 """
        return reverse('author-detail', args=[str(self.id)])

    def \_\_str\_\_(self):
        """
 String for representing the Model object.
 """
        return '%s, %s' % (self.last_name, self.first_name)
```

Повторно выполнить миграцию базы данных
---------------------------------------

Теперь все ваши модели созданы. Теперь переустановите миграцию базы данных, чтобы добавить их в свою базу данных.
```

python3 manage.py makemigrations
python3 manage.py migrate
```

Языковая модель - вызов
-----------------------

Представьте себе, что местный благотворитель жертвует ряд новых книг, написанных на другом языке (скажем, фарси). Задача состоит в том, чтобы определить, как они будут лучше всего представлены на нашем веб-сайте библиотеки, а затем добавить их в модели.

Некоторые вещи, которые следует учитывать:

* Должен ли «язык» ассоциироваться с Book, BookInstance или каким-либо другим объектом?
* Должны ли быть представлены разные языки с использованием модели, свободного текстового поля или жёстко запрограммированного списка выбора?

После того, как вы решили, добавьте поле. Вы можете увидеть наше решение на Github here.

Резюме
------

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

На этом этапе мы отвлечёмся от создания сайта и проверим *Django Administration site*. Этот сайт позволит нам добавить некоторые данные в библиотеку, которые мы можем отобразить с помощью наших (ещё не созданных) представлений и шаблонов.

Смотрите также
--------------

* Writing your first Django app, part 2 (Django Docs)
* Making queries (Django Docs)
* QuerySet API Reference (Django Docs)
* Назад
* Обзор: Django
* Далее