2016-03-16 3 views
2

У меня есть следующие модели:Многих ко многим Исключены по нескольким объектам

class Deal(models.Model): 
    date = models.DateTimeField(auto_now_add=True) 
    retailer = models.ForeignKey(Retailer, related_name='deals') 
    description = models.CharField(max_length=255) 
    ...etc 

class CustomerProfile(models.Model): 
    saved_deals = models.ManyToManyField(Deal, related_name='saved_by_customers', null=True, blank=True) 
    dismissed_deals = models.ManyToManyField(Deal, related_name='dismissed_by_customers', null=True, blank=True) 

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

У меня возникли проблемы, обертывая мою голову вокруг отношений «многие-ко-многим», и мне не повезло выяснить, как это сделать. Я предполагаю, что я должен использовать исключение для Deal.objects(), но все примеры, которые я вижу для исключения, исключают один элемент, а не то, что составляет несколько элементов.

Когда я наивно пытался просто:

сделок = Deal.objects.exclude (customer.saved_deals) .all()

Я получаю ошибку: "объект 'ManyRelatedManager' не итерацию"

Если я говорю:

сделок = Deal.objects.exclude (customer.saved_deals.all()) все()

я получаю "Слишком много значений для распаковки" (хотя я чувствую. Я должен отметить, что в базе данных сейчас всего 5 сделок и 2 клиента)

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

Кроме того, я бегу Джанго 1.5, как это развертывается на App Engine (с помощью CloudSQL)

Где я буду неправильно?

ответ

1

Предлагаем вам использовать customer.saved_deals, чтобы получить список идентификаторов транзакций для исключения (используйте значение_list для быстрого преобразования в плоский список).

Это должно сэкономить ваше поле в соединенном столе.

deals = Deals.exclude(id__in=customer.saved_deals.values_list('id', flat=True)) 
0

Вы хотели бы изменить это:

deals = Deal.objects.exclude(customer.saved_deals).all() 

Чтобы что-то вроде этого:

deals = Deal.objects.exclude(customer__id__in=[1,2,etc..]).all() 

В основном, customer является внешним ключом many-to-many, так что вы не можете использовать его непосредственно с exclude.

0

Сделки, сохраненные и отложенные сделки, представляют собой два поля, описывающих почти то же самое. Существует также риск, что слишком много столбцов могут использоваться в базе данных, если этим двум полям разрешено хранить значения Null. Стоит рассмотреть удаление removeed_deals вообще и использовать save_deal только с инструкцией True или False.

Еще одна вещь, о которой стоит подумать - переместить save_deals из класса CustomerProfile в класс Deals. Saved_deals о предложениях, поэтому он может предпочесть жить в классе Сделки.

class Deal(models.Model): 
    saved = models.BooleandField() 
    ... 

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

class Deal(models.Model): 
    saved = models.BooleanField() 
    customer = models.ForeignKey(CustomerProfile) 
    .... 

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

deals_for_customer = Deals.objects.all().filter(customer__name = "John") 

Существует двойное подчеркивание между клиентом и именем (customer__name), которые позволяют фильтровать MODEL_NAME (клиент связан с CustomerProfile, который является названием модели) и имя поля в этой модели (предполагается, что класс CutomerProfile имеет имя атрибут)

deals_saved = deals_for_customer.filter(saved = True) 

Все, что нужно. Надеюсь, я смогу помочь. Дайте мне знать, если нет.

Смежные вопросы