2013-02-20 92 views
0

我有以下模型结构,其中每个匠人与两个属性具有多对多关系;语言和纪律。在表格中,用户可以通过过滤这些属性来选择一个Tradesman的子集。Django多对多查询空表单和模型值

我想发生,就是:

  1. 如果用户过滤器只有一个属性,形式选择所有 未经过滤的属性。例如。如果选择一种语言,但 将该规则留空,它不会过滤规则。
  2. 如果用户过滤了一个商家没有 一个集合(即它为空)的语言,它将排除该商人。

我想我可以通过巴洛克式非pythonesque,非django方法从查询中提取主键并使用它们来解决此问题,但宁可使用更简洁的方法。

我认为可以解决这个问题将是:

  1. 动态Django的过滤器,会掉落或包含取决于条件上的if-else逻辑
  2. 一个参数,会匹配一切(包括空值)我可以存储在一个变量中,例如。

    return_everything=**everything()!** 
    Q(discipline__id__in=return_everything) 
    

我一直在寻找在Django的docmentation和计算器并不能找到做任何的方法。 感谢您的帮助。

models.py:

class Discipline(models.Model): 
    discipline=models.CharField(max_length=200, unique=True) 

class Language(models.Model): 
    language=models.CharField(max_length=200, unique=True) 

class Tradesman(models.Model): 
    discipline=models.ManyToManyField(Discipline, blank=True, null=True) 
    language=models.ManyToManyField(Language, blank=True, null=True) 

forms.py

class TradesmanForm(forms.Form): 
    #select all values to output in the form 
    discipline_all=.Discipline.objects.all() 
    language_all=Language.objects.all() 

    #declare form variables 
    discipline=forms.ModelMultipleChoiceField(queryset=discipline_all,required=False) 
    language=forms.ModelMultipleChoiceField(queryset=language_all,required=False) 

    #clean data 
    def clean(self) 
     cleaned_data=super(TradesmanForm, self).clean() 
     return cleaned_data 

views.py

def TrademanLookup(request) 
    if request.method == 'POST':  
     if form.is_valid() 
      discipline=form.cleaned_data['discipline'] 
      language=form.cleaned_data['language'] 
      ################################################# 
      # how can I make the below query dynamic,  # 
      # or else pass a variable into it that selects # 
      # everything, including nulls?     # 
      ################################################# 
      tradesman_return=Tradesman.objects.filter(
       Q(discipline__id__in=discipline), 
       Q(language__id__in=language) 
       ) 
      ...work with returned data... 
     else: 
      ...something else... 
    else: 
      ...something else... 

    return render_to_response('some.html','somevar':somevar) 

回答

1
def TrademanLookup(request) 
    if request.method == 'POST':  
     if form.is_valid() 
      discipline=form.cleaned_data['discipline'] 
      language=form.cleaned_data['language'] 
      query = [] 
      if disciplines: 
       query.append(Q(discipline__in=discipline)) 
      if language: 
       query.append(Q(language__in=language)) 

      if query:  
       tradesman_return=Tradesman.objects.filter(*query) 
      else: 
       tradesman_return=Tradesman.objects.all() 

      #...work with returned data... 

NB:它被认为GoodPractice(TM)使用复数形式对于收藏(应该真的是“纪律”和“浪漫” es“在Trademan模型和表单中。

NB2:该约定是使用all_lower_with_underscore名字的功能,所以你的观点应该被命名为“trademan_lookup”

+0

这样的作品,太感谢了。关于NB,大写的视图是简化鳕鱼换行的错字,但是不能在管理员中使用多个模型?由于这个原因,我一直在将我的模型名称从复数变为单数。假设这意味着这是最佳实践。再次感谢你的帮助。 – sean 2013-02-21 02:17:43