Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 10, 2010 18:04:57

fanat1k
От:
Зарегистрирован: 2010-01-28
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Подскажите как реализовать следующее:
есть сущность “объявление”. В зависимости от типа(или объекта) этого объявления (комп, ноут, плеер), нужно прикрутить к нему набор свойств как общих (цена, вес, …), так и специфических (громкость, процессор, формат файлов, …).
1. Сначала думал через наследование, как написано в доке:

class Advertisement(models.Model):
title = models.CharField()
price = models.IntegerField()


class Meta:
abstract = True

class CompOptions(Advertisement)
cpu = models.CharField()
ram = models.CharField()

class PlayerOptions(Advertisement)


Но мне не нравится то что создаются таблицы compoptions, noutoptions, и т.д. где поля title, price просто дублируются, т.е. с точки зрения БД никакого наследование нету :(

2. держать все свойства в одной таблице тоже плохой вариант, так как получится 20 и более полей, из которых штук 5 общих, а остальные будут специфические для каждоготипа техники. Получится много пустых полей.

3. Выделить таблицу common_options, куда занести все общие свойства, потом создать для каждого девайса по таблице с его спец. свойствами. (благо таких будет ограниченное количество и потом добавить еще будет несложно)
Проблема в том, что это только мои теоретические догадки, не получается “набросать” схему БД.
Подозреваю что надо через связи многие-ко-многим, через дополнительные промежуточные таблицы.

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

Самое плохое в том что я не могу нарисовать для этого схему БД :(
думал “забить” на БД и заюзать средства Джанго, а он мне уже нагенерит нужных таблиц :)
Приветствуются любые ответы, ткните носом что почитать. (только плиз не в гугл, “БД для чайников” и т.д.)
Спасибо.



Офлайн

#2 Фев. 10, 2010 18:54:36

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Вообще-то у реляционных баз данных “наследования” в принципе нету. Есть связи только.
Почитайте нормальной форме. Будет понятнее.

Вот, например, такая схема:

class ObjPropeties(models.Model):
""" Возможные свойства """
name = ...

class AdvType(models.Model):
""" Тип обьявления с сылками на свои свойства"""
name = ...
properties = ManyToMany(ObjProp)

class Advertisement(models.Model):
""" Объявление - связано с типом и с дополнительными свойствами"""
type = model.ForeignKey(AdvType)
special_properties = ManyToMany(ObjProp, blank=True)
title = models.CharField()
price = models.IntegerField()
Но возможно дублирование свойств в “типе” и “индивидуальных”.
Да, как прикрутить поле для значений сами догадаетесь.

Отредактировано (Фев. 10, 2010 19:02:14)

Офлайн

#3 Фев. 10, 2010 19:14:49

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Нет, не так.

Офлайн

#4 Фев. 11, 2010 14:28:39

fanat1k
От:
Зарегистрирован: 2010-01-28
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Ferroman
Вообще-то у реляционных баз данных “наследования” в принципе нету. Есть связи только.
Почитайте нормальной форме. Будет понятнее.
Я ожидал, что Джанга реализует это наследование как-то эффективнее :), а не просто дублированием полей. Такая реализация я бы сказал противоречит принципам построения БД. Она вроде не нарушает 3 нормальные формы, но я не вижу смысла использовать эту фичу. (может ошибаюсь, так кажется на первый взгляд)

Но возможно дублирование свойств в “типе” и “индивидуальных”.
может имелось ввиду дублирование в “обявление” и “индивидуальных” ? Так как в “типе” (AdvType) будет только список возможных девайсов, без каких либо свойств. Если так, то это будет полностью на моей совести и должен следить за тем, чтобы общие свойства вынести в Advertisement, а специфичные в ObjPropeties

Нет, не так.
Хм ? Что не так ? Все не так ? :) В любом случае что-то уже обрисовывается, отпишусь, когда получится или же не получится - буду спрашивать.

PS: еще очень интересует такая вещь как хранение в поле одной таблицы названия других таблиц. насколько адекватно такое решение ?
например для таблицы advertisement (id, title, price, size,…, property_table_name), в поле property_table_name хранить имена других таблиц comp_property, player_property, …
В таком случае средствами Джанго можно будет одним запросом получить все свойства ? Подозреваю что нет, так как надо сначала будет получить данные с advertisement (price, size, …), а вторым запросом все данные из comp_property.



Отредактировано (Фев. 11, 2010 14:35:22)

Офлайн

#5 Фев. 11, 2010 15:38:06

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Так как в “типе” (AdvType) будет только список возможных девайсов, без каких либо свойств.
Значит я не правильно понял условие задачи. “Общие” свойства разве не есть “общие” для определённого типа устройств?
Я себе представил так:
1. Есть общие свойства для всех устройств. (неизменные. Цена, к примеру.)
2. Есть обобщённые свойства для определённого типа устройств (у каждого типа - свои) (ёмкость и цвет у кружки)
3. Есть (или нету) индивидуальные свойства для отдельного устройства (дополнительно к типам) (картинка на кружке)
Или не так?
Хм ? Что не так ? Все не так ?
Да, всё не так. Мой ответ, как минимум, неполон, а скорее всего и вообще не правилен. Надо подумать, как это красивше сделать.

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

Офлайн

#6 Фев. 11, 2010 15:46:27

fanat1k
От:
Зарегистрирован: 2010-01-28
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Ferroman
Значит я не правильно понял условие задачи. “Общие” свойства разве не есть “общие” для определённого типа устройств?
Я себе представил так:
1. Есть общие свойства для всех устройств. (неизменные. Цена, к примеру.)
2. Есть обобщённые свойства для определённого типа устройств (у каждого типа - свои) (ёмкость и цвет у кружки)
3. Есть (или нету) индивидуальные свойства для отдельного устройства (дополнительно к типам) (картинка на кружке)
Или не так?
Все правильно, пункт 3 вычеркиваем. Есть просто индивидуальные свойства для каждого типа устройств, как сказано в п.2. Более глубокой детализации нету.



Офлайн

#7 Фев. 18, 2010 16:58:45

fanat1k
От:
Зарегистрирован: 2010-01-28
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Значит сделал так:

class AdvObjectParam(models.Model):
""" Список всех возможных параметров характеризующих недвижимость """

name = models.CharField(unique=True, max_length=15)


class HouseType(models.Model):
""" тип жилья: квартира, оффис, помещения, земельный участок, ... """

name = models.CharField(unique=True, max_length=15)
advobjectparam = models.ManyToManyField(AdvObjectParam, blank=True, null=True)

class Adv(models.Model):
""" Объявление """

title = models.CharField(max_length=100)
date_create = models.DateTimeField(auto_now_add=True)
housetype = models.ForeignKey(HouseType)

class ParamValue(models.Model):
""" Соответствие объявление->параметр жилья->значение параметра """"

advobject = models.ForeignKey(Adv)
advobjectparam = models.ForeignKey(AdvObjectParam)
value = models.CharField(max_length=25)
Подскажите, если где-нибудь что-то “криво”.
Возникла сразу же проблема извлечения всех данных для объявления, а именно:

adv_list = Adv.objects.all() не дает мне значений конечных параметров из таблицы “paramvalue”.

Как мне добраться до них ? В отдельности я могу их получить без проблем:
adv_params = ParamValue.objects.all(),
но как мне "связать adv_list и adv_params?
Интересует вообще практика решения подобных задач, когда не получается достать данные одним запросом, то что делать правильно ? Вижу 2 решения:
1. Объеденять их в шаблонеь. Например в цикле при выводе каждого объявления обращаться к соответствующим параметрам. Так и пробовал, только возникла одна проблемка, а имено:
У вью сформировал хеш айди_объявления => массив и передал в темплейт adv_params
{% for adv in adv_list %}
{{ adv.title }}
{% for param in adv_params.ADV_ID %}
параметр:{{ param.advobjectparam }}
значение:{{ param.value }}
{% endfor %}
{% endfor %}
Только загвоздка в том, что у меня нету ADV_ID! Отдельно я могу его получить {{ adv.id }}, но adv_params.adv.id естественно не работает. Хочется создать переменную {% var adv_id = {{ adv.id }}%} и потом ее заюзать. Но объявлять переменные в темплейте нельзя :(
Можно конечно сделать цикл по ВСЕМ параметрам, но это тупо
    {% for element in adv_params.items %}
{% ifequal adv.id element.0 %}
выводим параметры, для данного объявления
{% endif %}
{% endfor %}
2. Объединять не в темплейте а у вью, или объединить куерисеты. Тут темный лес, если так можно/лучше делать то подскажите.

PS: начал с компов и плееров, а теперь квартиры и дома. не спрашивайте че так :) в общем суть не поменялась.
Спасибо.



Офлайн

#8 Фев. 18, 2010 22:59:20

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Наследование моделей (и не только)

Хочется создать переменную {% var adv_id = {{ adv.id }}%} и потом ее заюзать. Но объявлять переменные в темплейте нельзя
Это замечательное свойство джанговских темплейтов, специально для таких случаев.
Формируйте список в контроллере, а уже готовый передавайте в темплейт.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version