aboutsummaryrefslogtreecommitdiff
path: root/files/ru/learn/server-side/django/models/index.html
blob: 4aeb0d64bc32b3553fc40e4a0812d81e88400e2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
---
title: 'Django учебник Часть 3: Использование моделей'
slug: Learn/Server-side/Django/Models
tags:
  - Django
  - данные
  - модель
  - туториал
translation_of: Learn/Server-side/Django/Models
---
<div>             {{LearnSidebar}}</div>

<div>{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}</div>

<p class="summary">В этой статье показано, как определить модели для <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> сайта. Она объясняет, что такое модель, как она объявляется, и некоторые из основных типов полей. В ней также кратко показаны некоторые из основных способов доступа к данным модели.</p>

<table class="learn-box standard-table">
 <tbody>
  <tr>
   <th scope="row">Предпосылки</th>
   <td><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Tutorial Part 2: Creating a skeleton website</a>.</td>
  </tr>
  <tr>
   <th scope="row">Задача:</th>
   <td>Научиться проектировать и создавать свои собственные модели, выбирая подходящие поля.</td>
  </tr>
 </tbody>
</table>

<h2 id="Обзор">Обзор</h2>

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

<p>В этом учебнике показано, как определить и получить доступ к моделям на примере <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary website</a>.</p>

<h2 id="Проектирование_моделей_LocalLibrary">Проектирование моделей LocalLibrary</h2>

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

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

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

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

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

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

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

<p><img alt="LocalLibrary Model UML - v3" src="https://mdn.mozillademos.org/files/15646/local_library_model_uml.png" style="height: 660px; width: 977px;"></p>

<div class="note">
<p>Примечание. В следующем разделе приведен базовый пример, поясняющий, как модели определяются и используются. Когда вы его прочитаете, подумайте, как мы построим каждую из моделей на диаграмме выше.</p>
</div>

<h2 id="Модель_для_начинающих">Модель для начинающих</h2>

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

<h3 id="Определение_модели">Определение модели</h3>

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

<pre class="notranslate">from django.db import models

class MyModelName(models.Model):
    """
    A typical class defining a model, derived from the Model class.
    """

    # Fields
    my_field_name = models.CharField(max_length=20, help_text="Enter field documentation")
    ...

    # Metadata
    class Meta:
        ordering = ["-my_field_name"]

    # Methods
    def get_absolute_url(self):
         """
         Returns the url to access a particular instance of MyModelName.
         """
         return reverse('model-detail-view', args=[str(self.id)])

    def __str__(self):
        """
        String for representing the MyModelName object (in Admin site etc.)
        """
        return self.field_name</pre>

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

<h4 id="Поля">Поля</h4>

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

<pre class="brush: js notranslate">my_field_name = models.CharField(max_length=20, help_text="Enter field documentation")</pre>

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

<ul>
 <li><code>max_length=20</code> — Указывает, что максимальная длина значения в этом поле составляет 20 символов.</li>
 <li><code>help_text="Enter field documentation"</code> — предоставляет текстовую метку для отображения, чтобы помочь пользователям узнать, какое значение необходимо предоставить, когда это значение должно быть введено пользователем через HTML-форму.</li>
</ul>

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

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

<h5 id="Общие_аргументы_поля">Общие аргументы поля</h5>

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

<ul>
 <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#help-text">help_text</a>: Предоставляет текстовую метку для HTML-форм (например, на сайте администратора), как описано выше.</li>
 <li><a href="https://docs.djangoproject.com/en/2.1/ref/models/fields/#verbose-name">verbose_name</a>: Удобочитаемое имя для поля, используемого в поле метки. Если не указано, Django выведет по умолчанию подробное название от имени поля.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#default">default</a>: Значение по умолчанию для поля. Это может быть значение или вызываемый объект, и в этом случае объект будет вызываться каждый раз, когда создается новая запись.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#null">null</a>: Если True, Django будет хранить пустые значения как NULL в базе данных для полей, где это уместно (CharField вместо этого сохранит пустую строку). По умолчанию используется значение False.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#blank">blank</a>: Если True, поле может быть пустым в ваших формах. По умолчанию используется значение False, что означает, что проверка формы Django заставит вас ввести значение. Это часто используется с null = True, потому что если вы хотите разрешить пустые значения, вы также хотите, чтобы база данных могла представлять их соответствующим образом.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#choices">choices</a>: Группа вариантов для этого поля. Если это предусмотрено, по умолчанию соответствующий виджет формы будет полем выбора с этими вариантами вместо стандартного текстового поля.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#primary-key">primary_key</a>: Если True, задает текущее поле в качестве первичного ключа для модели (первичный ключ - это специальный столбец базы данных, предназначенный для однозначной идентификации всех разных записей таблицы). Если в качестве первичного ключа не указано поле, Django автоматически добавит для этой цели поле.</li>
</ul>

<p>Есть много других вариантов - вы можете просмотреть <a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/">full list of field options here</a>.</p>

<h5 id="Общие_типы_полей">Общие типы полей</h5>

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

<ul>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.CharField">CharField</a> Используется для определения строк фиксированной длины от короткой до средней. Вы должны указать max_length для хранения данных.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.TextField">TextField</a> используется для больших строк произвольной длины. Вы можете указать <code>max_length</code> для поля, но это используется только тогда, когда поле отображается в формах (оно не применяется на уровне базы данных).</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.IntegerField" title="django.db.models.IntegerField">IntegerField</a> это поле для хранения значений (целого числа) и для проверки введенных значений в виде целых чисел в формах.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.DateField">DateField</a> и <a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.DateTimeField">DateTimeField</a> используются для хранения / представления дат и информации о дате / времени (как Python datetime.date и datetime.datetime, соответственно). Эти поля могут дополнительно объявлять (взаимоисключающие) параметры <code>auto_now=True</code> (для установки поля на текущую дату каждый раз, когда модель сохраняется), auto_now_add (только для установки даты, когда модель была впервые создана) и по умолчанию (чтобы установить дату по умолчанию, которую пользователь может переустановить).</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.EmailField">EmailField</a> используется для хранения и проверки адресов электронной почты.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.FileField">FileField</a> и <a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ImageField">ImageField</a> используются для загрузки файлов и изображений соответственно ( <code>ImageField</code> просто добавляет дополнительную проверку, что загруженный файл является изображением). Они имеют параметры для определения того, как и где хранятся загруженные файлы.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.AutoField">AutoField</a> - это особый тип IntegerField, который автоматически увеличивается. Первичный ключ этого типа автоматически добавляется в вашу модель, если вы явно не укажете его.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ForeignKey">ForeignKey</a> Используется для указания отношения «один ко многим» к другой модели базы данных (например, автомобиль имеет одного производителя, но производитель может делать много автомобилей). «Одна» сторона отношения - это модель, содержащая ключ.</li>
 <li><a href="https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ManyToManyField">ManyToManyField</a> используется для определения отношения «многие ко многим» (например, книга может иметь несколько жанров, и каждый жанр может содержать несколько книг). В нашем приложении для библиотек мы будем использовать их аналогично ForeignKeys, но их можно использовать более сложными способами для описания отношений между группами. Они имеют параметр on_delete, чтобы определить, что происходит, когда связанная запись удаляется (например, значение <code>models.SET_NULL</code> просто установило бы значение NULL)</li>
</ul>

<p>Существует много других типов полей, включая поля для разных типов чисел (большие целые числа, малые целые числа, дробные), логические значения, URL-адреса, slugs, уникальные идентификаторы и другие «связанные с временем» сведения (продолжительность, время и т. д.). Вы можете просмотреть <a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#field-types">full list here</a>.</p>

<h4 id="Метаданные">Метаданные</h4>

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

<pre class="brush: python notranslate">class Meta:
    ordering = ["-my_field_name"]
    ...</pre>

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

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

<pre class="brush: python notranslate">ordering = ["title", "-pubdate"]</pre>

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

<p>Другим распространенным атрибутом является verbose_name, подробное имя для класса в единственной и множественной форме:</p>

<pre class="brush: python notranslate">verbose_name = "BetterName"</pre>

<p>Другие полезные атрибуты позволяют создавать и применять новые «разрешения доступа» для модели (разрешения по умолчанию применяются автоматически), разрешить упорядочение на основе другого поля или объявить, что класс является «абстрактным» (базовый класс, для которого вы не можете создавать записи, и вместо этого будет создан для создания других моделей). Многие другие параметры метаданных управляют тем, какая база данных должна использоваться для модели и как хранятся данные (это действительно полезно, если вам нужно сопоставить модель с существующей базой данных). Полный список опций метаданных доступен здесь: <a href="https://docs.djangoproject.com/en/2.2/ref/models/options/#model-meta-options">Model metadata options</a> (Django документация).</p>

<h4 id="Методы">Методы</h4>

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

<pre class="brush: python notranslate">def __str__(self):
    return self.field_name</pre>

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

<pre class="brush: python notranslate">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)])
</pre>

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

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

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

<h3 id="Управление_моделью">Управление моделью</h3>

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

<h4 id="Создание_и_изменение_записей">Создание и изменение записей</h4>

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

<pre class="brush: python notranslate"># 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()
</pre>

<div class="note">
<p>Примечание. Если вы не указали какое-либо поле в качестве primary_key, новая запись будет выдаваться автоматически, с идентификатором имени поля. Вы можете запросить это поле после сохранения указанной выше записи, и оно будет иметь значение 1.</p>
</div>

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

<pre class="brush: python notranslate"># 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()</pre>

<h4 id="Поиск_записей">Поиск записей</h4>

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

<div class="note">
<p>Примечание. Объяснение того, как искать записи, используя «абстрактную» модель и имена полей, может быть немного запутанным. В приведенном ниже обсуждении мы будем ссылаться на модель книги с полями названия и жанра, где жанр также является моделью с единственным именем в поле.</p>
</div>

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

<pre class="brush: python notranslate">all_books = Book.objects.all()
</pre>

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

<pre class="brush: python notranslate">wild_books = Book.objects.filter(title__contains='wild')
number_wild_books = Book.objects.filter(title__contains='wild').count()
</pre>

<p>Соответствующие поля и тип соответствия определяются в имени параметра фильтра, используя формат: <code>field_name__match_type </code>(обратите внимание на двойное подчеркивание между заголовком выше). Выше мы фильтруем заголовок с учетом регистра. Есть много других типов совпадений, которые вы можете сделать: <code>icontains</code> (без учета регистра), <code>iexact </code>(точное совпадение без учета регистра), <code>exact </code>(точное совпадение с учетом регистра ) и <code>in</code>, <code>gt </code>(больше), <code>startswith</code> и т. д <a href="https://docs.djangoproject.com/en/2.2/ref/models/querysets/#field-lookups">смотреть полный список </a>(Django Docs, [EN]).</p>

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

<pre class="brush: python notranslate">books_containing_genre = Book.objects.filter(genre<strong>__</strong>name<strong>__</strong>icontains='fiction')  # Will match on: Fiction, Science fiction, non-fiction etc.
</pre>

<div class="note">
<p><strong>Примечание:</strong> Вы можете использовать символы подчеркивания (__) для навигации по многим уровням отношений (ForeignKey / ManyToManyField) по своему усмотрению. Например, книга, имеющая разные типы, определяемая с использованием дополнительной связи «обложка», может иметь имя параметра: type__cover__name__exact = 'hard'.</p>
</div>

<p>Существует гораздо больше возможностей для запросов, включая обратные поиски от связанных моделей, цепочки фильтров, возврат меньшего набора значений и т. д. Для получения дополнительной информации см. <a href="https://docs.djangoproject.com/en/2.2/topics/db/queries/">Making queries</a> (Django Docs, [EN]).</p>

<h2 id="Определение_моделей_LocalLibrary">Определение моделей LocalLibrary</h2>

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

<pre class="brush: python notranslate">from django.db import models

# Create your models here.</pre>

<h3 id="Модель_жанра">Модель жанра</h3>

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

<pre class="brush: python notranslate">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</pre>

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

<h3 id="Модель_книги">Модель книги</h3>

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

<pre class="brush: python notranslate">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 &lt;a href="https://www.isbn-international.org/content/what-isbn"&gt;ISBN number&lt;/a&gt;')
    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)])
</pre>

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

<p>В обоих типах полей соответствующий класс модели объявляется как первый неименованный параметр, используя либо класс модели, либо строку, содержащую имя соответствующей модели. Вы должны использовать имя модели как строку, если связанный класс еще не был определен в этом файле до того, как он будет указан! Другими параметрами, представляющими интерес для поля автора, являются <code>null=True</code>, которое позволяет базе данных хранить значение <code>Null</code> , если автор не выбран, и on_delete = models. <code>SET_NULL </code>установит значение автора в Null, если связанная с автором запись будет удалена.</p>

<p>Модель также определяет __str __ (), используя поле заголовка книги для представления книги. Окончательный метод get_absolute_url () возвращает URL-адрес, который можно использовать для доступа к подробной записи для этой модели (для этого нам нужно будет определить сопоставление URL-адресов, в котором содержится подробная информация о книге, и определить связанное представление и шаблон ).</p>

<h3 id="Модель_BookInstance">Модель BookInstance</h3>

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

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

<pre class="brush: python notranslate">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)</pre>

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

<ul>
 <li><code>UUIDField</code> используется для поля id, чтобы установить его как primary_key для этой модели. Этот тип поля выделяет глобальное уникальное значение для каждого экземпляра (по одному для каждой книги, которую вы можете найти в библиотеке).</li>
 <li><code>DateField</code> используется для данных due_back (при которых ожидается, что книга появится после заимствования или обслуживания). Это значение может быть blank или null (необходимо, когда книга доступна). Метаданные модели (Class Meta) используют это поле для упорядочивания записей, когда они возвращаются в запросе.</li>
 <li>status - это CharField, который определяет список choice/selection. Как вы можете видеть, мы определяем кортеж, содержащий кортежи пар ключ-значение и передаем его аргументу выбора. Значение в key/value паре - это отображаемое значение, которое пользователь может выбрать, а ключи - это значения, которые фактически сохраняются, если выбрана опция. Мы также установили значение по умолчанию «m» (техническое обслуживание), поскольку книги изначально будут созданы недоступными до того, как они будут храниться на полках.</li>
</ul>

<p>Модель __str __ () представляет объект BookInstance, используя комбинацию его уникального идентификатора и связанного с ним заголовка книги.</p>

<div class="note">
<p>Примечание. Немного Python:</p>

<ul>
 <li>Значение, возвращаемое __str __ (), является форматированной строкой. В строке мы используем % S для объявления 'placeholders'. После строки укажем %, а затем кортеж, содержащий значения, которые будут вставлены в заполнители. Если у вас просто один заполнитель, вы можете опустить кортеж - например, 'Мое значение:% S' % переменная.<br>
  <br>
  Обратите также внимание на то, что, хотя этот подход совершенно применим, но он более не является предпочтительным. Начиная с Python 3, вы должны использовать метод format, например. '{0} ({1})'.format (self.id, self.book.title). Вы можете узнать больше об этом  <a href="https://www.python.org/dev/peps/pep-3101/">здесь</a>.</li>
</ul>
</div>

<h3 id="Модель_автора">Модель автора</h3>

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

<p>Теперь все поля/методы должны быть знакомы. Модель определяет автора как имя, фамилию, дату рождения и (необязательную) дату смерти. Он указывает, что по умолчанию __str __ () возвращает имя в фамилии, порядковый номер первого имени. Метод get_absolute_url () отменяет сопоставление URL-адреса автора с целью получения URL-адреса для отображения отдельного автора.</p>

<pre class="brush: python notranslate">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)
</pre>

<h2 id="Повторно_выполнить_миграцию_базы_данных">Повторно выполнить миграцию базы данных</h2>

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

<pre class="notranslate"><code>python3 manage.py makemigrations
python3 manage.py migrate</code></pre>

<h2 id="Языковая_модель_-_вызов">Языковая модель - вызов</h2>

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

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

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

<p>После того, как вы решили, добавьте поле. Вы можете увидеть наше решение на Github <a href="https://github.com/mdn/django-locallibrary-tutorial/blob/master/catalog/models.py">here</a>.</p>

<ul>
</ul>

<ul>
</ul>

<h2 id="Резюме">Резюме</h2>

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

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

<h2 id="Смотрите_также">Смотрите также</h2>

<ul>
 <li><a href="https://docs.djangoproject.com/en/1.10/intro/tutorial02/">Writing your first Django app, part 2</a> (Django Docs)</li>
 <li><a href="https://docs.djangoproject.com/en/1.10/topics/db/queries/">Making queries</a> (Django Docs)</li>
 <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/querysets/">QuerySet API Reference</a> (Django Docs)</li>
</ul>

<p>{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}</p>