使用Django模型继承时如何避免这种冗余?

时间:2016-07-12 18:22:24

标签: python django inheritance django-models

我的Django网站上的所有页面都有一个页脚链接"反馈/问题"。如果新用户访问该网站并点击该链接,则应将其定向到带有下拉菜单的表单,以指示他们是否有针对其电子邮件地址及其反馈或问题的问题和字段的反馈。该页面将具有所有未经过身份验证的用户将看到的简单标头。另一方面,如果网站成员登录并进行身份验证,他们应该看到相同的表单,但没有电子邮件字段(因为我已经知道他们的电子邮件地址)和包含该网站内部导航栏的其他经过身份验证的标题,按钮等。

我最初的想法是创建一个抽象类FeedbackQuestion:

class FeedbackQuestion(models.Model):
  submission_type = ...  (type, i.e. feedback or question)
  submission_text = ...  (actual feedback or question)
  ...
  class Meta:
    abstract = True

然后我创建两个单独的具体子类:

class AnonFeedbackQuestion(FeedbackQuestion):
  email = models.EmailField(...)
  class Meta:
    db_table = anon_feedback_question

class AuthFeedbackQuestion(FeedbackQuestion):
  user = models.ForeignKey(User, related_name="user")
  class Meta:
    db_table = auth_feedback_question

这两个类将有自己的模型形式:

class AnonFeedbackQuestionForm(ModelForm):
  class Meta:
    model = AnonFeedbackQuestion
    fields = ['submission_type', 'submission_text', 'email']

class AuthFeedbackQuestionForm(ModelForm):
  class Meta:
    model = AuthFeedbackQuestion
    fields = ['submission_type', 'submission_text']

我预见到的问题是我必须在我的视图中执行以下操作以显示反馈表:

def get_feedback_questions(request, template):
  if request.method == 'POST':
    ...
    if request.user.is_authenticated():
      form = AuthFeedbackQuestionForm(request.POST)
    else:
      form = AnonFeedbackQuestionForm(request.POST)
    if form.is_valid():
      (process form)
      ...
  else:
    if request.user.is_authenticated():
      form = AuthFeedbackQuestionForm(request.POST)
    else:
      form = AnonFeedbackQuestionForm(request.POST)
    ...
  context = {'form': form}
  return render(request, template, context)

必须重复这些if / then / else块来识别使用哪种形式似乎相当不优雅。是否有更好,更清洁的" Django"这样做的方法?

谢谢!

1 个答案:

答案 0 :(得分:1)

我不会将您的模型子类化 - 如果这是一个匿名问题,您可以在user和{{1}的一个模型上包含email属性和blank=True属性}}:

null=True

这样,您可以为匿名用户的反馈/问题添加class FeedbackQuestion(models.Model): submission_type = ... (type, i.e. feedback or question) submission_text = ... (actual feedback or question) email = models.EmailField(..., blank=True, null=True) user = models.ForeignKey(User, related_name="user", blank=True, null=True) ... class Meta: abstract = True ,或者在email进行身份验证时添加user

然后我将您的表单合并为一个,包括电子邮件字段,但删除电子邮件字段取决于用户是否经过身份验证(请参阅this answer):

def __init__(self, *args, **kwargs):
    self.user = kwargs.pop('user', None)
    super(UserForm, self).__init__(*args, **kwargs)
    if self.user:
        # For logged-in users, email field not necessary
        self.fields.pop('email')
    else:
        # Otherwise, the field needs to be required
        self.fields['email'].required = True

然后,您只需要确保在清理表单数据时适当地创建用户(例如,确保电子邮件地址尚未被删除等)。