我有一个模型,根据对象是由用户还是系统创建,对其名称字段使用不同的验证。
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 },
)
我想创建一个 Form 和一个 CreateView,用户可以使用它们创建对象。当用户创建这样的对象时,应该将用户用作“creator”字段的值。
目前它看起来像这样:
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)
我这样写是因为这是这个相关问题的答案:
在基于类的通用视图 CreateView 中访问 request.user 以在 Django 中设置 FK 字段 https://stackoverflow.com/questions/5785727/accessing-request-user-in-class-based-generic-view-createview-in-order-to-set-fk/5785767#5785767
不幸的是,它不起作用:视图只允许我创建以下划线开头的符号,而它应该做相反的事情。但是,当我创建符号时,创建者字段无论如何都会被正确设置。
我认为问题在于创建者字段仅在 clean() 方法运行后才设置。
如何在调用 clean() 方法之前设置创建者字段?
或者,有没有更好的方法来完成我想做的事情?
在我看来,应该有一种更有效的方法来自动化逻辑,我对名称字段有两个不同的验证器,其选择取决于创建者字段。