在我的模型中,我设置了一个自定义模型(CodeUser
(,外键指向django.contrib.auth
User
模型。我实际上正在使用django-auth-ldap
,但User
模型是相同的。然后我有一个Code
模型,它有一个custodian
字段,它是特定CodeUser
的外键。
class CodeUser(models.Model):
user = models.ForeignKey('User')
# Other fields...
class Code(models.Model):
custodian = models.ForeignKey('CodeUser')
# Other fields...
我正在使用Code
模型的ModelForm
,并希望表单接受custodian
字段的CodeUser
的电子邮件地址。我认为这可以通过简单地使用 ModelChoiceField
的to_field_name
选项来完成。
但是,如果用户尚不存在,我希望能够创建用户。为此,我进行LDAP
查询以确保电子邮件可以与用户关联,然后使用 populate
django-auth-ldap
方法。
填充用户的过程工作正常,我只是无法弄清楚这段代码应该在我的 django 应用程序中的位置。我尝试创建一个自定义字段class
,然后将其用于代码模型窗体中custodian
字段的field_classes
。我为我的字段实现了自定义validate
方法,但在 Code
ModelForm 验证期间从未调用此方法。似乎验证仅降级到模型窗体的模型中。
class UserByEmailField(forms.ModelChoiceField):
def validate(self, value):
# Check e-mail is valid
# Check user already exists or populate from LDAP
def to_python(self, value):
# Return CodeUser instance
class CodeForm(forms.ModelForm):
class Meta:
fields = ['custodian']
field_classes = {'custodian' : UserByEmailField}
最后,我的问题是,电子邮件地址的CodeUser
验证/填充代码应该去哪里? 还有其他几种形式也需要此过程,因此我认为自定义字段类最有意义。
你可以在两个不同的地方做。 您可以覆盖代码表单的change_form.html并通过JavaScript执行此操作。
或者我过去所做的是在模型表单中执行此操作并覆盖"def clean"功能。 这是我在自定义更改密码表单中执行此操作的示例。
def clean(self):
cleaned_data = super(ChangePasswordForm, self).clean()
oldpass = cleaned_data.get('oldpassword')
if not self.user.check_password(oldpass):
raise forms.ValidationError("Invalid Password")
pass1 = cleaned_data.get('password1')
pass2 = cleaned_data.get('password2')
if pass1 != pass2:
raise forms.ValidationError("Passwords do not match")
也应该在模型表单中工作。
https://docs.djangoproject.com/en/1.9/ref/forms/validation/