【问题标题】:Django many to many query with null form and model values带有空表单和模型值的 Django 多对多查询
【发布时间】:2013-02-05 11:00:46
【问题描述】:

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

我希望发生的是:

  1. 如果用户只过滤一个属性,表单会选择所有 未过滤的属性。例如。如果选择 a 选择一种语言但 将学科留空,它不会过滤学科。
  2. 如果用户过滤了商人没有的语言 一组(即它为空),它不包括那个商人。

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

我认为可以解决的方法是:

  1. 一个动态的 django 过滤器,它会根据 if-else 逻辑删除或包含条件
  2. 一个与我可以存储在变量中的所有内容(包括空值)匹配的参数,例如。

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

我一直在查看 django 文档和 stackoverflow,但也找不到方法。 感谢您的帮助。

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)

【问题讨论】:

    标签: django django-forms many-to-many django-queryset


    【解决方案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...
    

    注意:在集合中使用复数形式被认为是 GoodPractice(TM)(在 Trademan 模型和表单中都应该是“学科”和“语言”。

    NB2 : 惯例是对函数使用 all_lower_with_underscore 名称,因此您的视图应命名为“trademan_lookup”

    【讨论】:

    • 这行得通,谢谢一百万。至于 NB,在简化 stackoverflow 的 cod 时,大写视图是一个错字,但 django 不是在管理员中多元化模型吗?出于这个原因,我一直在将我的代码我的模型名称从复数更改为单数;假设这意味着这是最佳做法。再次感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2011-06-10
    • 2015-11-12
    • 2014-05-27
    • 2018-02-09
    • 2010-12-14
    • 2013-05-17
    • 2021-04-12
    • 1970-01-01
    相关资源
    最近更新 更多