Django:优化MultilingualQuerySet特定对象过滤代码
解决MultilingualQuerySet无法用字典推导式的问题,实现更简洁的筛选写法
Hey there! Let's fix this up for you.
为什么会报错?
首先,你遇到的'MultilingualQuerySet' object has no attribute 'items'报错原因很清晰:MultilingualQuerySet是Django QuerySet的多语言扩展版本,它本质上是模型实例的集合(类似列表),而不是键值对结构的字典,所以字典推导式里的items()方法完全不适用在这里。
更简洁高效的替代写法
根据你的需求(找到focus为QuestionFocus.FEELING_ABOUT_ATTENDING_AGAIN的问题并放到context里),有几种更优雅且高效的写法:
1. 确定只有一个匹配项时(推荐)
如果业务上保证这个focus对应的问题只会有一个,直接用get()方法——这是最简洁的方式:
questions_and_answers = self.request.event.surveys.get_results(settings.SURVEY_POST_EVENT) context["feeling_about_attending_again"] = questions_and_answers.get( focus=QuestionFocus.FEELING_ABOUT_ATTENDING_AGAIN )
提示:如果没有找到匹配项,
get()会抛出DoesNotExist异常。如果想避免报错,可以加default=None参数:context["feeling_about_attending_again"] = questions_and_answers.get( focus=QuestionFocus.FEELING_ABOUT_ATTENDING_AGAIN, default=None )
2. 可能有多个匹配项,只需要第一个
如果不确定有多少个匹配,但只需要第一个结果,用filter()加first():
questions_and_answers = self.request.event.surveys.get_results(settings.SURVEY_POST_EVENT) feeling_question = questions_and_answers.filter( focus=QuestionFocus.FEELING_ABOUT_ATTENDING_AGAIN ).first() if feeling_question: context["feeling_about_attending_again"] = feeling_question
这种写法更安全,找不到匹配项时first()会返回None,不会抛出异常。
3. 需要所有匹配项(如果有多个)
如果需要把所有符合条件的问题都放进context(比如作为列表),直接把filter结果转成列表即可:
context["feeling_about_attending_again"] = list( questions_and_answers.filter(focus=QuestionFocus.FEELING_ABOUT_ATTENDING_AGAIN) )
为什么这些写法更好?
和你原来的循环写法相比,这些QuerySet方法是在数据库层面完成筛选,而不是把所有实例拉到内存后再循环判断——数据量大的时候,性能差异会非常明显,而且代码更简洁易读。
内容的提问来源于stack exchange,提问作者Joey Coder
相关产品推荐
相关产品推荐

