Django CreateView:在验证前设置用户

问题描述:

我有一个模型,根据对象是由用户还是由系统创建,对其名称字段使用不同的验证。Django CreateView:在验证前设置用户

class Symbol(models.Model): 
    name = models.CharField(_('name'), unique=True, max_length=64) 
    creator = models.ForeignKey('User', null=True, on_delete=models.CASCADE) 
    def is_system_internal(self): 
     """ 
     whether or not this Symbol belongs to the system rather than having been created by a user 
     """ 
     return (self.creator is None) 
    def clean(self): 
     """ 
     ensure that the Symbol's name is valid 
     """ 
     if self.is_system_internal(): 
      if not re.match("^_[a-zA-Z0-9\-_]+$", self.name): 
       raise ValidationError(
        _("for system-internal symbols, the name must consist of letters, numbers, dashes (-) and underscores (_) and must begin with an underscore."), 
        params = { 'value' : self.name }, 
       ) 
     else: 
      if not re.match("^[a-zA-Z][a-zA-Z0-9\-_]*$", self.name): 
       raise ValidationError(
        _("the symbol name must consist of letters, numbers, dashes (-) and underscores (_) and must begin with a letter."), 
        params = { 'value' : self.name }, 
       ) 

我想创建一个窗体和一个CreateView,用户可以用它创建对象。当用户创建这样的对象时,用户应该被用作“创建者”字段值的值。

目前,它看起来像这样:

class SymbolCreateForm(forms.ModelForm): 
    name = forms.CharField(max_length=Symbol._meta.get_field('name').max_length, required=True) 
    class Meta: 
     model = Symbol 
     fields = ('name',) 

class SymbolCreateView(LoginRequiredMixin, generic.CreateView): 
    form_class = SymbolCreateForm 
    template_name = 'main/symbol_create.html' 
    def form_valid(self, form): 
     # set the creator of the instance to the currently logged in user 
     form.instance.creator = self.request.user 
     return super(SymbolCreateView, self).form_valid(form) 

我用这种方式写它,因为那是答案此相关的问题:

Accessing request.user in class based generic view CreateView in order to set FK field in Django

不幸的是,它不工作:视图只允许我创建以下划线开头的符号,它应该做相反的操作。但是,当我创建符号时,创建者字段无论如何都会正确设置。

我认为问题在于创建者字段只有在clean()方法已经运行之后才会被设置。

如何在调用clean()方法之前设置创建者字段?

或者,有没有更好的方法来做我想做的事情? 在我看来,应该有一个更有效的方法来自动化逻辑,我有两个不同的名称字段验证器,其选择取决于创建者字段。

您可以在get_form_kwargs方法中设置instance.creator

class SymbolCreateView(LoginRequiredMixin, generic.CreateView): 
    form_class = SymbolCreateForm 

    def get_form_kwargs(self): 
     kwargs = super(SymbolCreateView, self).get_form_kwargs() 
     if kwargs['instance'] is None: 
      kwargs['instance'] = Symbol() 
     kwargs['instance'].creator = self.request.user 
     return kwargs 

检查if kwargs['instance'] is None意味着该代码可以使用两种CreateViewUpdateView

+0

我得到一个TypeError: “**之后的ModelFormMetaclass对象参数必须是映射,而不是NoneType” –

+0

记得返回'kwargs' – Alasdair