2011-09-28 48 views
0

我有以下的基本模型......如何「到」對象查詢/過濾M2M在Django

class Campaign(models.Model): 
    name = models.CharField(_('name'), max_length=80, unique=True) 
    recipients = models.ManyToManyField('Person', blank=True, null=True, through='Recipient') 


    class Recipient(models.Model): 
    campaign = models.ForeignKey(Campaign) 
    person = models.ForeignKey('Person') 


    class Person(models.Model): 
    first_name = models.CharField(_('first name'), max_length=30, blank=True) 
    last_name = models.CharField(_('last name'), max_length=30, blank=True) 

我想有一個查詢不屬於某個廣告活動中的所有Person對象一個查詢集。

這將會是好的,如果它是一樣簡單:

Person.objects.all().exclude(<mycampaign>.recipients.all()) 

但我們知道,不能正常工作。

更具體地講,我試圖讓這個在窗體類的工作方式如下與Q對象註釋似乎是正確的,但我不能讓它的工作......這是我的形式:

class RecipientsForm(forms.Form): 
    def __init__(self, campaign, *args, **kwargs): 
    self.campaign = campaign 
    self.helper = FormHelper() 
    self.helper.add_input(Submit('submit','Add',css_class='primaryAction')) 
    self.helper.layout = Layout(
     Fieldset(
      '', 
      'recipients', 
      css_class='inlineLabels') 
    ) 
    return super(RecipientsForm, self).__init__(*args, **kwargs) 

    recipients = forms.ModelMultipleChoiceField(
    # old queryset queryset=Person.objects.all(), 
       queryset=Person.objects.filter(~Q(id__in=self.campaign.recipients.all())), 
       widget=forms.widgets.CheckboxSelectMultiple, 
       label="Add Recipients", 
       required=True,) 

    def save(self, force_insert=False, force_update=False, commit=True): 
    recipients = self.cleaned_data['recipients'] 
    for person in recipients: 
     recipient = Recipient(campaign=self.campaign,person=person) 
     recipient.save() 

回答

1

我相信這樣做。

from django.db.models import Q 
Person.objects.filter(~Q(id__in=<mycampaign>.recipients.all()) 
+0

你能看看我的表單類並告訴我我做錯了什麼嗎?我已經更新了問題內容 - – mogga

+0

當您使用舊的queryset(queryset = Person.objects.all())時,它是否顯示所有這些內容?另外,驗證對self.campaign的訪問,你可以在'recipients = forms.ModelMultipleChoiceField()之上做一個簡單的'raise Exception(self.campaign.name)''我想知道self.campaign是否在main可能是因爲它在執行時未初始化。如果是這種情況,您可能只需聲明類中的收件人,並使__init __()方法根據self.campaign初始化收件人列表。 – Furbeenator

1

這裏的答案......問題是,我的形式是爲收件人對象,而不是運動物體...的Furbeenator答案是朝正確方向邁出的良好一步......與Django的IRC一些幫助沿着

class RecipientsForm(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
    self.campaign = kwargs.pop('campaign', None) 
    super(RecipientsForm, self).__init__(*args, **kwargs) 

    if self.instance and self.campaign: 
     self.fields['recipients'] = forms.ModelMultipleChoiceField(
     queryset=Person.objects.filter(~Q(id__in=self.campaign.recipients.all())), 
     widget=forms.widgets.CheckboxSelectMultiple, 
     label='Recipients', help_text='Pick the recipients to add to the campaign', 
     required=False, 
    ) 
    elif self.campaign: 
     self.fields['recipients'] = forms.ModelMultipleChoiceField(
     queryset=Person.objects.filter(~Q(id__in=self.campaign.recipients.all())), 
     widget=forms.widgets.CheckboxSelectMultiple, 
     label='Recipients', help_text='Pick the recipients to add to the campaign', 
     required=False, 
    ) 
    else: 
     pass 

    def save(self, force_insert=False, force_update=False, commit=True): 
    recipients = self.cleaned_data['recipients'] 
    for person in recipients: 
     recipient = Recipient(campaign=self.campaign,person=person) 
     recipient.save() 

    class Meta: 
    model = Campaign 
    fields = ['recipients',] 
+0

太棒了,很高興你明白了。 – Furbeenator