我开发了一些Django应用程序,就我如何与模型进行交互而言都非常直接。
我现在正在构建一个具有多个不同视图的视图,由于缺少更好的术语,这些视图是“预制”搜索结果页面。这些页面都返回来自同一模型的结果,但它们在不同的列上进行过滤。我们可能在类型上过滤了一个页面,另一个我们可能在类型和大小上进行过滤,而在另一个页面上我们可能只过滤了大小等等...
我在views.py中编写了一个函数,每个页面都使用了这个函数,它需要一个kwargs,并且是搜索的标准。最小值是一个过滤器,但其中一个视图最多有4个。
我只是看看kwargs dict是否包含其中一种过滤器类型,如果有的话我会过滤掉该值的结果(我现在只是写了这段代码,如果有任何错误我道歉,但你应该明白这一点):< / p>
def get_search_object(**kwargs):
q = Entry.objects.all()
if kwargs.__contains__('the_key1'):
q = q.filter(column1=kwargs['the_key1'])
if kwargs.__contains__('the_key2'):
q = q.filter(column2=kwargs['the_key2'])
return q.distinct()
现在,根据django文档(http://docs.djangoproject.com/en/dev/topics/db/queries/#id3),这些很好,因为在评估集合之前不会命中数据库,但最近我听说这不是最有效的方法。这样做,而且应该使用Q对象。
我想我正在寻找其他开发者的答案。我的方式目前工作正常,如果我的方式从资源POV完全错误,那么我会尽快改变。
提前致谢
答案 0 :(得分:3)
从资源方面来说,你很好,但有很多方法可以在风格上进行改进,以避免使用双下划线方法,并使其更灵活,更易于维护。
如果正在使用的kwargs
是实际的列名,那么您应该能够非常轻松地简化它,因为您正在做的是解构kwargs
并手动重建它,但仅限于此具体的关键词。
def get_search_object(**kwargs):
entries = Entry.objects.filter(**kwargs)
return entries.distinct()
主要区别在于它没有强制键是实际列,并且非常需要在那里进行一些异常处理。如果要将其限制为特定字段集,可以指定该列表,然后使用有效条目构建dict。
def get_search_object(**kwargs):
valid_fields = ['the_key1', 'the_key2']
filter_dict = {}
for key in kwargs:
if key in valid_fields:
filter_dict[key] = kwargs[key]
entries = Entry.objects.filter(**filter_dict)
return entries.distinct()
如果您想要一个更好的解决方案,只需检查该模型上的 有效字段,您就可以(ab)使用_meta
:
def get_search_object(**kwargs):
valid_fields = [field.name for field in Entry._meta.fields]
filter_dict = {}
for key in kwargs:
if key in valid_fields:
filter_dict[key] = kwargs[key]
entries = Entry.objects.filter(**filter_dict)
return entries.distinct()
答案 1 :(得分:2)
在这种情况下,从效率的角度来看,您的使用情况很好。如果需要使用OR过滤器而不是AND,则只需要使用Q对象。