2016-02-11 3 views
1

Рассмотрим эти две модели:Непосредственно обеспечивая значение внешнего ключа в Джанго

class CarType(models.Model): 
    code_name = models.SlugField(primary_key=True) 
    name = models.CharField(max_length=20) 

class Car(models.Model): 
    name = models.CharField(max_length=30) 
    car_type = models.ForeignKey('CarType') 

Предположим, что мы хотим получить все седан автомобили, вместо этого запроса:

Car.objects.filter(car_type=CarType.objects.get(code_name='sedan')) 

Мы можем использовать этот запрос:

sedan_cars = Car.objects.filter(car_type__code_name='sedan') 

Поскольку code_name является первичным ключом в CarType, второй код выиграл» t генерирует 2 запроса (например, первый) или даже использует соединение SQL.

Как это можно сделать при создании Car объектов? наивный способ, как это:

Car.objects.create(name='Tesla S', car_type=CarType.objects.get(code_name='sedan')) 

Это запрос CarType, чтобы узнать значение первичного ключа строки с критериями code_name='sedan' и использовать этот первичный ключ в car_type поле Car таблицы. Поскольку мы уже знаем значение первичного ключа CarType, это будет действительно лишний дополнительный запрос. (ИЛИявляется Джанго достаточно умны, чтобы избежать этого?)

Как car_type значение будет предоставляться непосредственно? Я попробовал эти два, но оба потерпел неудачу:

Car.objects.create(name='Tesla S', car_type='sedan') 
Car.objects.create(name='Tesla S', car_type__code_name='sedan') 
+0

я волновался бы больше на влиянии на производительности, не имея добавочный первичный ключ (я довольно уверен, что это сделает поиск намного сложнее). – Sayse

+0

@Sayse, но это семантически более корректно ... –

+0

Я не говорил, что это неправильно, я просто сказал, что это может сделать индексирование и поиск менее результативными, возможно, в зависимости от типа db – Sayse

ответ

4

Существует также дополнительное поле car_type_id, который содержит необработанный идентификатор инородного объекта. Вы можете написать ему при создании нового объекта Car. Поэтому код:

Car.objects.create(name='Tesla S', car_type_id='sedan') 

Должен работать нормально.

+0

Nice ... Спасибо :-) –

+1

Обратите внимание, что вы также можете использовать это поле для поиска. – GwynBleidD

-1

Как вы уже даете car_type в качестве внешнего ключа вам необходимо предоставить объект автомобиля первым, а затем объявить car_type:

c = Car.objects.filter(car_type=CarType.objects.get(code_name='sedan')) 
c.car_type = 'sedan' 
Смежные вопросы