【问题标题】:Accessing field from OneToOne field in ModelForm从 ModelForm 中的 OneToOne 字段访问字段
【发布时间】:2016-02-09 08:46:00
【问题描述】:

我正在尝试扩展 Django 身份验证系统,但在尝试为其创建 modelForm 时遇到问题。正如您在下面看到的,我已经通过建议的 OneToOnefield 引用了身份验证后端,但是当我创建 ModelForm 时,如果我尝试引用诸如“用户名”、“密码”等字段,它会吐出一个错误,说它们是未知字段。我正在创建的表格是来自的注册。我在这里做错了什么?干杯

型号-

class StudentModel(models.Model):
    user = models.OneToOneField(User, unique=True)
    birth_date = models.DateField()
    contact_number = models.IntegerField()
    referral = models.CharField(max_length=100, choices=referral_choices)

模型表单 -

from django import forms
from opus_login.models import StudentModel, EmployerModel

class StudentForm(forms.ModelForm):

    class Meta:
        model = StudentModel
        fields = ['username', 'first_name']

错误 -

django.core.exceptions.FieldError: Unknown field(s) (username, first_name) specified for StudentModel

【问题讨论】:

  • 那些字段在用户模型上,你不只需要你的模型表单到那个模型吗? birth_date 和其他字段不能为空,因此单独显示这两个字段将不起作用
  • ModelForm 只能访问模型的字段。 stackoverflow.com/questions/27832076/…

标签: django


【解决方案1】:

当您需要用另一个模型扩展User 模型时,一个常见的解决方案是使用两个ModelForms:一个用于User,另一个用于扩展模型(在您的情况下为Student)。首先,您访问User 模型的所需字段,然后访问Student 模型的所需字段。

class UserForm(forms.ModelForm):
    password = forms.CharField(label='Password',widget=forms.PasswordInput)
    password2 = forms.CharField(label='Repeat password',widget=forms.PasswordInput)

    class Meta:
    model = User
    fields = ('username', 'first_name')

    def clean_password2(self):
        .......
        return password2

class StudentForm(forms.ModelForm):
    class Meta:
        model = StudentModel
        fields = ['birthdate', 'contact_number']

然后,在视图中,您使用两种形式而不是一种形式。例如:

def register(request):
    if request.method == 'POST':
        user_form = UserForm(request.POST)
        student_form = StudentForm(request.POST)
        if user_form.is_valid() and student_form.is_valid():
            user_form.save()
            student_form.save()

在您的模板中,您将两种形式合二为一:

<form action="." method="post">
  {{ user_form.as_p }}
  {{ student_form.as_p }}
  {% csrf_token %}
  <p><input type="submit" value="Register"></p>
</form>

【讨论】:

  • 您好,我一直在尝试使用您的方法,因为这似乎是 imo 最合乎逻辑的。但是我遇到了一个问题,即您无法修改 User 模型,例如,我计划为密码字段添加一个 clean() 函数,但是使用这种方法是不可能的。有什么建议吗?
  • @eZ_Harry 我已经编辑了答案。您不必修改 User 模型,因为它有一个密码字段。
【解决方案2】:

您不能像这样直接访问 One2One 字段。您需要首先创建User 的对象并添加到 One2One 关系。你可以这样尝试:

from django import forms
from opus_login.models import StudentModel, EmployerModel

class StudentForm(forms.ModelForm):
    username = forms.CharField()
    first_name = forms.CharField()

    class Meta:
        model = StudentModel
        fields = ['__all__']

    def save(self, **kwargs):
        student = super().save(commit=False)
        user = User.objects.create(username=self.cleaned_data['username'], first_name=self.cleaned_data['first_name'])
        user.set_password(self.cleaned_data['password']) #if there is a password field
        student.user = user
        student.save(commit=True)
        return student

【讨论】:

  • 我想save() 方法在首先调用super().save() 时会引发错误,因为它是ModelForm 并且这些字段不在模型中。
猜你喜欢
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 2016-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多