Страницы

Поиск по вопросам

среда, 26 февраля 2020 г.

Связать в одном поле 2 модели?

#python #django


У меня есть 3 модели:
class category(models.Model):
   title = models.CharField(max_length=255, verbose_name='название')

class page(models.Model):
    title = models.CharField(max_length=255, verbose_name='заголовок')
    text = models.TextField(verbose_name='текст')

class menu(models.Model):
    title = models.CharField(max_length=255, verbose_name='заголовок')
    content = models.ForeignKey(Page or Category) # <- How to?
    link = models.CharField(max_length=255)

Как сделать, что бы menu.content ссылалась либо на страницу, либо на категорию, и
в зависимости от того, на что она ссылается в menu.link должно быть либо category/,
либо page/?    


Ответы

Ответ 1



Можно через generic relations, как-то так: content_type = models.ForeignKey(ContentType) object_id = models.IntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id') Но, вроде бы, нет толкового метода ограничить на что может ссылаться GFK, разве что в БД пост-фактум (уже после заполнения таблицы content_types) засунуть констрейнты по ID, чтобы подстраховаться. Другой вариант — через multi-table inheritance. class MenuItem(models.Model): title = ... link = ... class Page(MenuItem): text = ... ... Но, опять же, некрасиво — MenuItem.objects вернет объекты класса MenuItem, а не Page. Т.е. придется выбирать отдельно по каждой таблице и склеивать. Третий вариант — если СУБД умеет наследование (как, скажем, PostgreSQL), то использовать его и raw SQL. CREATE TABLE menu_items ( ... ); CREATE TABLE pages ( ...) INHERITS (menu_items); Тогда SELECT * FROM menu_items может использовать все поля из таблиц-наследников. Но, опять же, это некрасиво — ломимся мимо Django'вского ORM'а. Хотя можно выкрутиться через unmanaged models и, возможно, представления для SELECT ... FROM ONLY ... (если они нужны; т.к. ORM никогда сам запрос не родит). Четвертый вариант — завести два ForeignKey, page и category, и влепить констрейнт, что одно и только одно из них должно быть NULL (None). И сделать, для удобства, @property у модели, которое вернет то, что is not None. По мне так лучший из вариантов, но совершенно не подходит для ситуаций, когда типов объектов много.

Ответ 2



Мне кажется, что самый простой способ - это все-таки сделать 2 поля, pagecontent и categorycontent, и заполнять их по-разному в зависимости от содержания link.

Комментариев нет:

Отправить комментарий