БД/производительность:макет модели django, которая редко ссылается на своего родителя более одного раза

StackOverflow https://stackoverflow.com/questions/1821778

Вопрос

У меня есть приложение, в котором представлены вымышленные упрощенные города.

Пожалуйста, рассмотрите следующие модели 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 view, мне пришлось бы перебирать любые здания «дополнительного» типа, что нормально и нормально.

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

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

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

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

(A2) Через try и .get(...)

(A3) Через try и .filter(...).latest()

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

Это безумие использовать следующий вариант?

(B) конкретные ФК в модели города, по одному для каждого из наиболее важных базовых типов.

Вопрос:

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

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

Пожалуйста, порекомендуйте!:)

Заранее спасибо!

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

  1. Джанго-запомнить
  2. github.com/husio/django-easycache/

Возможно, кому-то это тоже будет полезно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top