2009-11-30 3 views
0

У меня есть приложение, в котором представлены вымышленные упрощенные города.DB/performance: макет модели django, которая редко ссылается на своего родителя более одного раза

Пожалуйста, обратите внимание на следующие модели Django:

class City(models.Model): 
    name = models.CharField(...) 
    ... 

TYPEGROUP_CHOICES = (
    (1, 'basic'), 
    (2, 'extra'), 
) 

class BldgType(models.Model): 
    name = models.CharField(...) 
    group = models.IntegerField(choices=TYPEGROUP_CHOICES) 

class Building(models.Model): 
    created_at = models.DateTimeField(...) 
    city = models.ForeignKey(City) 
    type = models.ForeignKey(BldgType) 
    other_criterion = models.ForeignKey(...) 

    class Meta: 
     get_latest_by = 'created_at' 

Пояснения для выбора этой установки:

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

(2) В определенных видах все здания (независимо от города и т. Д.) Должны фильтроваться в соответствии с различными критериями, например, other_criterion.

Проблема/беспокойство:

В city_detail зрения, я бы перебрать любых зданий «дополнительных» типа, который нормально и нормально.

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

Будет не более дюжины «базовых» типов зданий, из которых примерно половина будет представлена ​​все время.

Я склонна к письменной форме удобных методов на модели города, и я сталкиваюсь три варианта:

(A1) Via try и индекс: .filter(...)[0]

(A2) Via try и .get(...)

(A3) Via try и .filter(...).latest()

Но ни один из них не выглядит элегантным. Или один из этих трех вариантов хорош для сочетания с каким-то кешированием, например, в методе Django get_profile() на модели User? К сожалению, у меня пока нет опыта кэширования.

Можно ли использовать следующий вариант?

(B) специфический ФКС в модели города, один для каждого из наиболее важных основных типов

Вопрос:

Какого варианта имеет смысл чаще всего?
Или схема вообще не подходит для такого рода сценариев?

В особенности относительно производительности БД, что вы предлагаете? Нужен ли мне совершенно другой подход?

Обратите внимание! :)

Заранее благодарен!

ответ

1

Если в городе может быть не более одного места в мэрии, пожарной части, полицейском участке, больнице, школе и т. Д., То я думаю, что самый простой способ обеспечить соблюдение этого положения - объявить каждый из них как поле на модели :

class City(models.Model): 
    name = models.CharField(...) 
    city_hall = models.ForeignKey(Building) 
    fire_station = models.ForeignKey(Building) 
    # ... et cetera 

Если вы находите это слишком «грязный» в модели города, вы можете рассмотреть вопрос о промежуточной CityBuildings модели:

class CityBuildings(models.Model): 
    city_hall = models.ForeignKey(Building) 
    fire_station = models.ForeignKey(Building) 
    # ... et cetera 

class City(models.Model): 
    name = models.CharField(...) 
    buildings = models.OneToOneField(CityBuildings) 

Затем вы ссылаетесь зданий, как, например, city.buildings.fire_station

Это только предложения ... Я не уверен, что так или иначе более «правильный»

+0

+1 Я согласен с этим решением - для записи: рекомендуется использовать 'ForeignKey' с аргументом' unique = True' вместо OneToOne = D – Jiaaro

+0

@Jim Я не думаю, что это ; это был совет около 0,96, когда было много времени, когда «семантика OneToOnes скоро изменится», но в наши дни нет оснований не использовать OneToOne. –

+0

Привет! Спасибо за ваш ответ и комментарии до сих пор, это действительно оценено! Джим, ты прав насчет моего дополнительного беспокойства о «модельной беспорядке». ;) Моя текущая проблема с моделью CityBuildings, однако, будет заключаться в том, что «никто другой» не использует ее, кроме модели City, тем самым вводя ненужный дополнительный JOIN через OneToOneField, который вернет меня к опции (B) выше, т.е. , до первой версии вашего ответа. Любые мысли о проблеме производительности, т. Е. Будут ли параметры (B) все же лучше, чем любые из (A) вариантов? Кроме того, опять же, я, безусловно, не специалист по кешированию. Спасибо! – Geradeausanwalt

0

Для тех, кто заинтересован: глупый меня обнаружили существование техники запоминания, поэтому я буду использовать некоторые формы, которые применяются к (A2), завернутый в множество удобных методов в модели City, поскольку у меня есть «базовые» типы зданий.

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

На быстро, я сделал два проекта, чтобы смотреть на для обучения и, возможно, предоставляя материал или нанесения непосредственно:

  1. django-memoize
  2. github.com/husio/django-easycache/

Возможно, кто-то найдет это полезным.