Django:如何在验证之前将数据添加到ModelForm子类?

时间:2011-11-13 16:16:49

标签: python django django-forms

作为Django中表单验证的一部分,我想检查用户上次发帖的时间。

我已经查看了有关stackoverflow的thisthis问题,它似乎解决了这个问题,并且最初使用了已接受的答案here。本质上,此过程一直是在

期间添加request.user对象
def form_valid(self, form):

CreateView子类的方法。但是,这不允许在表单验证期间使用用户变量。

由于我想在验证期间访问用户变量,因为自上次发布以来的检查时间是逻辑验证,我需要先将用户变量注入到表单中。

我尝试改变get_initial()方法:

def get_initial(self):
    initial = super(ArticleCreateView, self).get_initial()
    initial['user'] = self.request.user
    return initial

这成功地在初始字典中设置了['user']键,但这从未完成清理过程,该过程仅处理['data']字典中的内容,并删除初始字典中的任何内容。我故意将用户从表单显示中排除,但这似乎也将其从清理过程和验证中删除。

这样做的正确方法是覆盖Form的 init ()方法,以及视图的get_initial()方法,将'user'置于首字母,然后拉出表单从初始到 init ()的形式的额外信息?

我希望将request.user传递给表单,然后我可以在表单范围的clean()方法中访问它来执行额外的检查,这相当于验证。

def clean(self):
    super(ArticleForm, self).clean()
    **check whether user has posted recently, if so, raise ValidationError**
    return self.cleaned_data

Ĵ

3 个答案:

答案 0 :(得分:4)

您可以覆盖CreateView的get_form_kwargs方法(在您的情况下为ArticleCreateView)以将用户传递给表单。

def get_form_kwargs(self):
    kwargs = super(ArticleCreateView, self).get_form_kwargs()
    kwargs['user'] = self.request.user
    return kwargs

覆盖表单的 init 方法

...
def __init__(self, *args, **kwargs):
    self.user = kwargs.pop("user")

现在你可以在clean方法中使用self.user。

答案 1 :(得分:2)

目前我解决这个问题的方法是在表单中保持验证,并在视图中保留其余的业务逻辑。因此,我做了以下事情:

在视图中:

def get_initial(self):
    initial = super(MyCreateView, self).get_initial()
    initial['user'] = self.request.user
    return initial

表格形式:

def __init__(self, *args, **kwargs):
    self.user = kwargs['initial']['user']
    super(MyObjectForm, self).__init__(self, *args, **kwargs)

def clean(self):
    # Clean all the submitted data
    super(MyObjectForm, self).clean()

    # Validate that the user submitted > n time ago
    profile = self.user.get_profile()

    if datetime.now() - profile.lastpost < timedelta(hours=1)
        raise forms.ValidationError("Need to wait longer than n=1 hours")
    else:
        self.cleaned_data['user'] = self.user

    return self.cleaned_data

这似乎有用 - 我有没有看到这个解决方案的缺陷?

答案 2 :(得分:0)

我可能会覆盖表单init方法来获取user参数,并在表单的某处设置它。

class MyForm()
    def __init__(self, user, *args, **kwargs):
        super(MyForm, self)__init__(*args, **kwargs)
        self.user = user


    def clean_field(...)
        if self.user ...