我有一个Django应用程序,它使用一个抽象基类('Answer'),并根据问题对象所需的答案类型创建不同的答案。(这个项目是作为一个教程开始的)。现在的问题是:
class Question(models.Model):
ANSWER_TYPE_CHOICES = (
('CH', 'Choice'),
('SA', 'Short Answer'),
('LA', 'Long Answer'),
('E3', 'Expert Judgement of Probabilities'),
('E4', 'Expert Judgment of Values'),
('BS', 'Brainstorms'),
('FB', 'Feedback'),
)
answer_type = models.CharField(max_length=2,
choices=ANSWER_TYPE_CHOICES,
default='SA')
question_text = models.CharField(max_length=200, default="enter a question here")
答案是:
class Answer(models.Model):
"""
Answer is an abstract base class which ensures that question and user are
always defined for every answer
"""
question = models.ForeignKey(Question, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
class Meta:
abstract = True
ordering = ['user']
目前,我在Answer中有一个方法(覆盖get\u或\u update\u Answer()),其中包含特定于类型的指令,用于查找正确的表并收集或创建正确类型的对象。你知道吗
@classmethod
def get_or_update_answer(self, user, question, submitted_value={}, pk_ans=None):
"""
this replaces get_or_update_answer with appropriate handling for all
different Answer types. This allows the views answer and page_view to get
or create answer objects for every question type calling this function.
"""
if question.answer_type == 'CH':
if not submitted_value:
# by default, select the top of a set of radio buttons
selected_choice = question.choice_set.first()
answer, _created = Vote.objects.get_or_create(
user=user,
question=question,
defaults={'choice': selected_choice})
else:
selected_choice = question.choice_set.get(pk=submitted_value)
answer = Vote.objects.get(user=user, question=question)
answer.choice = selected_choice
elif question.answer_type == 'SA':
if not submitted_value:
submitted_value = ""
answer, _created = Short_Answer.objects.get_or_create(
user=user,
question=question,
defaults={'short_answer': submitted_value})
else:
answer = Short_Answer.objects.get(
user=user,
question=question)
answer.short_answer = hashtag_cleaner(submitted_value['short_answer'])
etc... etc... (similar handling for five more types)
把这些逻辑都放进去型号.py'时,我可以加载页面视图中任意数量问题的用户答案:
for question in page_question_list:
answers[question] = Answer.get_or_update_answer(user, question, submitted_value, pk_ans)
我相信有一种更具python风格的方法来设计这段代码——一些我还没有学会使用的东西,但我不确定是什么。类似于接口,这样每个对象类型都可以实现其自己的版本答案。获取或更新答案(),而Python将使用适合该对象的版本。这会让你型号.py“整洁多了。你知道吗
根据您所展示的内容,您已经掌握了重新实现Visitor pattern的大部分方法,这是处理这种情况的一种非常标准的方法(您有一堆相关的子类,每个子类都需要自己的处理逻辑,并且希望迭代它们的实例并对每个子类进行处理)。你知道吗
我建议看看这个模式是如何工作的,也许可以更明确地实现它。你知道吗
我最近重新讨论了这个问题,用五行或十行代码替换了一行或两百行代码,并认为有一天找到我在这里所做的事情可能会对某些人有用。你知道吗
我遇到的问题有几个要素——第一,需要创建、保存和检索的答案类型很多;第二,GET和POST二分法(以及我的独特解决方案,总是创建一个答案,并将其发送到表单);第三,一些类型有不同的逻辑(头脑风暴可以为每个用户提供多个答案反馈甚至不需要回应——如果它是为用户创建的,那么它已经被呈现出来了。)这些元素可能掩盖了一些消除重复的机会,这使得访问者模式非常合适。你知道吗
元素1和元素2的解决方案
词典问答式映射到相关答案子类的代码在中创建视图.py(因为很难把它放进去型号.py和解决依赖关系):
然后我就可以得到我想要的答案类,对于任何问题都是'get\u or \u created':
我将其作为参数传递给class方法:
因此,相同的六行代码处理get\或\ U在提交时创建任何答案\ U value=None(get)或not(submitted\ U value)。你知道吗
元素3的解决方案
元素3的解决方案是将模型扩展为至少三种类型的处理,以便用户重新访问同一问题: “S”-单一,允许他们只记录一个答案,重新审视和修改答案,但决不能给出两个不同的答案。 “T”-跟踪,允许他们每次更新答案,但可以记录他们的答案(例如,研究人员) “M”-多个,允许对一个问题提交多个答案。你知道吗
在所有这些更改之后仍然修复bug,所以我不会发布代码。 下一个功能:复合问题和问题模板,所以人们可以使用管理员屏幕,使自己的答案类型。你知道吗
相关问题 更多 >
编程相关推荐