Связи между моделями, строковое представление

Классическая доска объявлений подразумевает, что все объявления разделены на тематические рубрики (электроника, услуги, аренда и т.д). Также добавим данный функционал в наш проект.

Сначала объявим новый класс модели Rubric, которая обеспечит функционирование рубрик. Для этого необходимо дописать код в models.py (приложение bboard):

Class Rubric(models.Model):
    name = models.CharField(max_length=30, db_index=True,
                                           verbose_name='Название')
    class Meta:
        verbose name_plural = 'Рубрики'
        verbose_name = 'Рубрика'
        ordering = ['name']

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

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

Теперь добавим в модель Bb новое поле – rubric:

Class Bb(models.Model):
    . . . 
    Rubric = models.ForeignKey('Rubric', null=True,
                    on_delete=models.PROTECT, verbose_name='Рубрика')
    class Meta:
        . . .

Класс ForeignKey – поле внешнего ключа, который используется для хранения ключа записи из первичной модели. При помощи первого параметра в конструктор класса передается имя класса первичной модели, поскольку первичная модель у нас объявлена после вторичной.

По умолчанию все поля моделей обязательны к заполнению. Поэтому нет возможности добавить новое поле, также обязательное к заполнению – возникнет ошибка на уровне СУБД. Придется явно сделать поле rubric необязательным к заполнению при помощи параметра null (значение True).

Действия при каскадном удалении записей вторичной модели настраиваются при помощи именованного параметра on_delete. Значение PROTECT запрещает каскадное удаление. Это сделано, чтобы даже при удалении рубрики объявления оставались.

Применение миграций

После сохранения изменений необходимо сгенерировать миграции, чтобы все изменения в структуре базы данных были зафиксированы:

manage.py makemigrations bboard

После данной команды в каталоге migrations будет автоматически создан новый файл миграции с названием в формате 0002_auto_<дата_время>. Можно открыть файл и посмотреть его содержимое – там будут инструкции для создания новой таблицы для модели Rubric, а также для добавления нового поля rubric в таблицу модели Bb.

Применим созданный файл миграции:

manage.py migrate

Сразу зарегистрируем созданную модель на административном сайте, для чего добавим в модель admin.py две строки:

from .models import Rubric
admin.site.register(Rubric)

Активируем отладочный веб-сервер, перейдет в административную панель и вручную добавим в модель Rubric несколько рубрик (например, «Транспорт» и «Недвижимость»).

Строковое представление модели

Изменения успешно применены, однако в списке записей все рубрики отображаются в виде малоинформативного шаблона <имя класса модели>object(<ключ>).

Один из способов решения – объявить для модели Rubric специальный класс редактора, в котором указать набор полей для вывода (ранее уже рассматривалось). Но данный способ лучше подходит для моделей, которые имеют несколько значащих полей (в данном случае поле только одно).

Рассмотрим другой способ – переопределение метода __str__(self), возвращающего строковое представления класса. Добавим в модуль models.py следующий код:

Class Rubric(models.Model):
    . . .
    def __str__(self):
        return self.name
    class Meta:
        . . .

Теперь в качестве строкового представления будет выводиться название рубрики.

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

Осталось сделать так, чтобы в рубрики выводились также в списке записей модели Bb. Для этого достаточно в класс Bbadmin добавить поле ‘rubric’ в перечень имен полей, присвоенный атрибуту list_display:

class Bbadmin(admin.ModelAdmin):
    List_display = ('title', 'content', 'price', 'published', 'rubric')
    . . .




Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: