Получение значений из 2 разных таблиц с помощью Django QuerySet - PullRequest
3 голосов
/ 17 сентября 2009

Для следующих моделей:

class Topping(models.Model):
    name = models.CharField(max_length=100)

class Pizza(models.Model):
    name = models.CharField(max_length=100)
    toppings = models.ManyToManyField(Toppping)

Мои данные выглядят следующим образом:

Столы для пиццы и топпинга присоединились:

ID  NAME        TOPPINGS
------------------------------------
1   deluxe      topping_1, topping_2
2   deluxe      topping_3, topping_4
3   hawaiian    topping_1

Я хочу получить идентификатор пиццы вместе с соответствующей начинкой для всей пиццы с именем deluxe. Мой ожидаемый результат:

1   topping_1
1   topping_2
2   topping_3
2   topping_4

Соединительная таблица:

pizza_toppings
--------------
id    
pizza_id    
topping_id

Вот SQL-эквивалент того, чего я хочу достичь:

SELECT p.id, t.name
FROM pizza_toppings AS pt
INNER JOIN pizza AS p ON p.id = pt.pizza_id
INNER JOIN topping AS t ON t.id = pt.topping_id
WHERE p.name = 'deluxe'    

Есть идеи, как выглядит соответствующий Django Queryset? Я также хочу отсортировать полученную начинку по имени, если вышеупомянутое не достаточно сложно.

Ответы [ 2 ]

2 голосов
/ 17 сентября 2009

Я не думаю, что есть чистое решение для этого, так как вам нужны данные из двух разных моделей. В зависимости от вашей структуры данных вы можете использовать select_related, чтобы избежать попадания в базу данных для всех добавок. Идя к желаемому результату, я бы сделал:

result = []
pizzas = Pizza.objects.select_related().filter(name='deluxe')
for pizza in pizzas:
    for toppings in pizza.toppings.all():
        result.append((pizza.pk, topping.name))

Это сгенерирует:

[
    (1, topping_1),
    (1, topping_2),
    (2, topping_3),
    (2, topping_4),
]

Теперь есть разные способы настройки данных, используя списки, кортежи и словари, но я думаю, вы поняли, как вы могли бы это сделать.

0 голосов
/ 17 сентября 2009

Нет прямого способа получить пиццу, если у вас есть топпинг из модели выше. Вы могли бы сделать

pizzas = topping.pizza_set.all()

для всех пицц с топпингом или, возможно, (в случае, если топпинг существует только в одной пицце с названием «люкс»)

pizza = topping.pizza_set.get(name="deluxe")

как только у вас есть начинка. Или вы можете сохранить Пиццу и Топпинг в списке кортежей или словаре (если дубликатов нет):

toppings = {}
pizzas = Pizza.objects.filter(name="deluxe")
for pizza in pizzas:
    for topping in pizza.toppings.all():
        toppings[topping.name] = pizza.name
sorted_toppings = toppings.keys()
sorted_toppings.sort()

Тогда вы можете принести пиццу для долива со словарем.

...