1

Все,Django производительность запросы: однонаправленное включение с использованием ForeignKey против Двунаправленного с использованием ForeignKey & Related_name

Какой из них вы предпочитаете, когда дело доходит до надлежащего дизайна & чистоты, а также производительность запросов?

Вариант А: (двунаправленная ссылка)

class Country(models.Model): 
    name = models.CharField(max_length=128) 
    capital = models.ForeignKey('City',related_name="country_capital", null=True) 

class State(models.Model): 
    name = models.CharField(max_length=128) 
    capital = models.ForeignKey('City', related_name="state_capital", null=True) 
    country = models.ForeignKey('Country', null=True) 

class City(models.Model): 
    name = models.CharField(max_length=128) 
    state = models.ForeignKey('State', null=True) 
    country = models.ForeignKey('Country', null=True) 

Вариант B: (однонаправленный ссылка)

class Country(models.Model): 
    name = models.CharField(max_length=128) 

class State(models.Model): 
    name = models.CharField(max_length=128) 
    country = models.ForeignKey('Country', null=True) 

class City(models.Model): 
    name = models.CharField(max_length=128) 
    state = models.ForeignKey('State', null=True) 
    state_capital = models.BooleanField(default=False) 
    country_capital = models.BooleanField(default=False) 


Search will be done as: 
Get me all cities where name is Waterloo and country is US. 
Get me all cities where country is UK. 
Get me all states where country is US. 
Get me a country where country is US. and capital is Washington DC. 
Get me the capital where country is US. 

ответ

1

Есть несколько вещей неправильно с опцией B, с моей точки Посмотреть. Во-первых, нет ничего, что могло бы помешать двум или более городам быть отмеченными как капитал для определенного государства или страны. Вам нужно будет добавить дополнительную проверку на свои формы, чтобы этого не произошло.

С точки зрения запроса, я думаю, что A по-прежнему предпочтительнее. Например, если вы хотите, чтобы получить все города в государстве, столицей которого является город X, в первом вы могли бы сделать:

cities = City.objects.filter(state__capital__name="City X") 

, а во втором вы должны сделать это:

cities = City.objects.filter(state=City.objects.get(name="City X")) 

, который разрешает подзапрос, который, вероятно, будет менее эффективным.

Однако, в варианте A я не думаю, что вам обязательно нужен FK из города в страну. В вашей модели (*) все города находятся в штатах, поэтому вы всегда можете получить страну через государство - лишний FK снова означает, что вам нужна дополнительная проверка, чтобы вы не могли присвоить город стране, которая отличается от страны его государства.

(* хотя отмечают, что это на самом деле не соответствует действительности: не все страны имеют государства так или иначе, и даже те, которые часто имеют города, которые находятся за пределами всех государств, как Канберра в Австралии)

+0

Я поставил как государство, так и страну в Город() в варианте А по той же самой причине, что некоторые города не попадают под состояние. Таким образом, состояние будет NULL. Кроме того, unique_together будет использоваться для обеспечения отсутствия дубликатов в любых моделях, что выходит за рамки этого вопроса. Итак, вы говорите, что поедете с вариантом A, правильно? Thx Daniel. – un33k

1

Вариант A лучше, потому что он содержит ту же информацию, не требуя набора полей, которые почти всегда будут пустыми (state_capital и country_capital).

Как вы заметили, не во всех странах есть штаты/провинции, поэтому у вас должны быть как поля страны, так и государства для модели города. В любом случае, это очень небольшое количество избыточности для огромного выигрыша, и вы вряд ли столкнетесь с проблемами нормализации (например, крайне редко, что данное государство меняет свою страну). Даже если у каждого города есть связанное состояние в вашей модели, все равно лучше добавить избыточное поле для ускорения запроса - тогда вы имеете дело не более чем с одним табличным соединением вместо двух.

Обратите внимание, что Вашингтон, округ Колумбия состоит из двух мест: Вашингтон - город и округ Колумбия. Таким образом, ваш запрос:

Получите мне страну, в которой находится страна. и столица - Вашингтон.

Если читать

Country.objects.filter(code__iexact='US', capital__name__iexact='Washington', capital__state__code__iexact='DC') 

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

Я хотел бы отметить, что некоторые из этих запросов кажутся довольно избыточными: почему вам нужно сопоставлять страны как с названием страны , так и с столицей?

+0

Washington, D.C. - это «Вашингтонский округ Колумбия», который является столицей США. – un33k

+0

Да, я знаю об этом. Просто хотел указать, что по почтовым адресам, по крайней мере, Вашингтон - это город, а округ Колумбия - государство. Я полагаю, что нет никакого вреда в создании названия города «Вашингтон, Д.К.» и задание значения состояния «Нет». –

+0

Получил это. Да, оставляя пустое государство, имеет смысл, поскольку оно удерживает общее число состояний на уровне 50. – un33k