БД/производительность:макет модели django, которая редко ссылается на своего родителя более одного раза
-
10-07-2019 - |
Вопрос
У меня есть приложение, в котором представлены вымышленные упрощенные города.
Пожалуйста, рассмотрите следующие модели 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 в двух направлениях, и позволяет более четко обозначить в коде разделение интересов (моделирование с одной стороны, производительность с другой).
Вкратце я разработал два проекта, на которые стоит обратить внимание для обучения и, возможно, предоставления кредита или подачи заявки напрямую:
- Джанго-запомнить
- github.com/husio/django-easycache/
Возможно, кому-то это тоже будет полезно.