Reputation: 1
I am having a problem where my chained filter using many to many lookups are not performing as I expected. Here are the pertinent details:
views.py
def cs_edit_result(request, ctype=None, survey_id=None):
#if POST request resume answering survey answers from a selected customer survey.
if request.method == 'GET':
sid = Survey.objects.get(pk=survey_id)
if request.method == 'POST':
sid = Survey.objects.get(pk=survey_id)
form = CustomerSurveyForm(request.POST, instance=sid)
#filter placeholders to only form data from customer survey:
if form.is_valid():
cs_result = form.save()
answers = SurveyAnswers.objects.filter(surveyid=sid.id)
for x in answers:
x.status=False
x.save()
print(form)
citype = form.cleaned_data['institution_type']
cproducts = form.cleaned_data['products']
cpurchases = form.cleaned_data['purchase']
cservices = form.cleaned_data['services']
colb = form.cleaned_data['olb_vendor']
cph1 = SurveyAnswers.objects.filter(surveyid=cs_result).filter(
Q(placeholder__purchase__in=cpurchases),
Q(placeholder__institution_type__in=citype),
Q(placeholder__olb_vendor__in=colb),
models.py
class PlaceHolder(models.Model):
output_choices = [
('link','Link'),
('plain text', 'Plain Text'),
('html', 'HTML')
]
purchase = models.ManyToManyField(Purchase, related_name='purchase_place')
institution_type = models.ManyToManyField(InstitutionType, related_name='itype_place')
products = models.ManyToManyField(Product,blank=True, related_name='products_place')
services = models.ManyToManyField(Service,blank=True, related_name='services_place')
olb_vendor = models.ManyToManyField(OLB_Vendor,blank=True, related_name='olb_place')
output_type = models.ManyToManyField(Output_Type)
question = models.TextField(null=True, verbose_name = 'question/title')
silvercloud_placeholder = models.CharField(max_length=50)
output_type = models.CharField(
max_length=100,
choices= output_choices,
default='Plain Text')
answer = models.TextField(blank=True,null=True, verbose_name='url/answer')
def __str__(self):
return self.silvercloud_placeholder
class Survey(models.Model):
customer = models.CharField(max_length=50)
purchase = models.ManyToManyField(Purchase)
institution_type = models.ManyToManyField(InstitutionType)
products = models.ManyToManyField(Product)
services = models.ManyToManyField(Service,blank=True)
olb_vendor = models.ManyToManyField(OLB_Vendor)
def __str__(self):
return ('{} Survey {}'.format(self.customer, str(self.id)))
class SurveyAnswers(models.Model):
#contributor = admin.
surveyid = models.ForeignKey(Survey,on_delete=models.CASCADE)
placeholder = models.ForeignKey(PlaceHolder,on_delete=models.CASCADE)
answer = models.TextField(blank=True,null=True)
status = models.BooleanField(default=False)
class meta:
constraints = [
models.UniqueConstraint(fields=['surveyid', 'placeholder'], name='Unique Answer')
]
def __str__(self):
return ('{} Survey {} {}'.format(self.surveyid.customer, str(self.surveyid.id),self.placeholder.silvercloud_placeholder))
So the issue is that cph1 will not return the appropriate SurveyAnswer objects. If I remove all but one of the Q objects the expected SurveyAnswer will return in the queryset but once I add a second Q object the expected Survey Answer does not get met by the filter. Any help would be greatly appreciated. If there are any missing details I can add them in.
Upvotes: 0
Views: 60
Reputation: 6052
filter
arguments are combined with AND
by default. If you are looking for OR
you can combine the Q objects using the |
operator:
cph1 = SurveyAnswers.objects.filter(surveyid=cs_result).filter(
Q(placeholder__purchase__in=cpurchases) |
Q(placeholder__institution_type__in=citype) |
Q(placeholder__olb_vendor__in=colb) |
)
Upvotes: 1