我有父母,姓名和孩子模特:
models.py
class Parent(models.Model):
title = models.CharField(max_length=250)
address = models.CharField(max_length=250)
class Name(models.Model):
title = models.CharField(max_length=250)
class Kid(models.Model):
family = models.ForeignKey(Parent)
name = models.ForeignKey(Name)
age = models.IntegerField()
city = models.CharField(max_length=250)
我有一个view函数,只有当与Parent相关的Kid对象都在字典中时才显示Parent对象:
views.py
def index(request):
patterns = [
{'name__title': 'samy', 'age__lt': 15, 'city': 'paris'},
{'name__title': 'sally', 'age__gt': 20, 'city': 'london'}
]
filter_q = reduce(operator.or_, map(lambda p: Q(**p), patterns))
qs = Kid.objects.filter(filter_q).values_list('id', 'family_id')
family_ids = set()
child_ids = list()
for child_id, family_id in qs:
family_ids.add(family_id)
child_ids.append(child_id)
incomplete_family_ids = set(Kid.objects.exclude(id__in=child_ids).filter(family_id__in=family_ids).values_list('family_id', flat=True).distinct())
complete_family_ids = family_ids - incomplete_family_ids
parents = Parent.objects.filter(id__in=complete_family_ids)
template = 'index.html'
context = {'parents': parents}
return render(request, template, context)
如果我想用模型对象替换模式字典,例如:
,该怎么办?class Pattern(models.Model):
title = models.CharField(max_length=250)
class PatternItems(models.Model):
name = models.ForeignKey(Name)
age = models.integer()
city = models.CharField(max_length=250)
pattern = models.ForeignKey(Pattern)
所以不是字典。我想知道是否有可能从Pattern模型中选择一个模式来显示Parent对象,如果它所有相关的Kid对象都使用Pattern对象在PatternItems中。
整个想法是让过滤器动态化,并允许用户自己制作过滤器。
帮助?
答案 0 :(得分:3)
您可以替换这段代码:
patterns = [
{'name__title': 'samy', 'age__lt': 15, 'city': 'paris'},
{'name__title': 'sally', 'age__gt': 20, 'city': 'london'}
]
filter_q = reduce(operator.or_, map(lambda p: Q(**p), patterns))
使用循环添加任意数量的过滤器:
# init patterns as a list of PatternItems
patterns = [ PatternItem(name=Name(title='samy'), age=15, city='paris'),
PatternItem(name=Name(title='sally'), age=20, city='london'),
]
# iterate through the list normally
filters = []
for pt_item in patterns:
filters.append(Q(name__title=pt_item.name.title) &
Q(age__lt=pt_item.age) & Q(city=pt_item.city))
filter_q = filters[0]
for f in filters[1:]:
filter_q |= f
获取patterns
的另一种方法是评估QuerySet,例如使用filter():
# any_column__gte and value here are just examples
patterns = PatternItem.objects.filter(any_column__gte=value)
# iterate through the patterns using .all()
filters = []
for pt_item in patterns.all():
...
此方法的唯一问题是您必须对列表中的每个age__lt
使用相同的比较(即PatternItem
)。
请注意:我使用循环而不是reduce()函数,因为它在Python 3中不存在。
答案 1 :(得分:0)
所以这个问题的答案可能并不清楚。 @Paolo Stefan代码非常接近我的需要。
<强> view.py 强>
patterns = PatternItems.objects.filter(pattern__title='adults')
filters = []
for pt_item in patterns.all():
filters.append(Q(name__title=pt_item.name.title) &
Q(age__lt=pt_item.age) & Q(city=pt_item.city))
filter_q = filters[0]
for f in filters[1:]:
filter_q |= f
qs = Kid.objects.filter(filter_q).values_list('id', 'family_id')
family_ids = set()
child_ids = list()
for child_id, family_id in qs:
family_ids.add(family_id)
child_ids.append(child_id)
incomplete_family_ids = set(Kid.objects.exclude(id__in=child_ids).filter(family_id__in=family_ids).values_list('family_id', flat=True).distinct())
complete_family_ids = family_ids - incomplete_family_ids
parents = Parent.objects.filter(id__in=complete_family_ids)
template = 'index.html'
context = {'parents': parents}
return render(request, template, context)
唯一的区别是: patterns = PatternItems.objects.filter(pattern__title ='adults')
使用“成人”所需的模式过滤模式项目。