django - 将具有 OneToOne 关系的两个模型合并为一种形式 - Django

标签 django django-models django-forms django-views

我创建了两个自定义用户模型(AbstractBaseUser 和一个单独的额外信息模型)。有没有一种方法可以将两个模型结合起来创建一个表单,用户可以使用该表单来更新两个模型之间的所有信息?

例如,最好有这样的东西(尽管我知道不可能):

class ProfileChangeForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ['username', 'email', first_name', 'last_name', 'bio', 'website']

预先感谢您的帮助!型号如下:

我的用户:

class MyUser(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=30, unique=True)
    email = models.EmailField(max_length=255, unique=True)
    first_name = models.CharField(max_length=120, null=True, blank=True)
    last_name = models.CharField(max_length=120, null=True, blank=True)

用户配置文件:

class UserProfile(models.Model):
    user = models.OneToOneField(MyUser)
    bio = models.TextField(null=True, blank=True)
    website = models.CharField(max_length=120, null=True, blank=True)

最佳答案

以下解决方案对我有用。我使用表单集来创建这个解决方案。 我的模型如下,

型号:

#Custom user model
class CustomUserManager(BaseUserManager):
    def create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError(_('The Email must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

class CustomUser(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

#Related model(One-to-One relationship with custom user)
class Student(models.Model):
    user = models.OneToOneField(CustomUser,on_delete = models.CASCADE)
    first_name = models.CharField(max_length=50)
    middle_name = models.CharField(max_length=50,blank=True,null=True)
    last_name = models.CharField(max_length=50,blank=True,null=True)

之后我创建了两个 ModelForm

表格

from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser,Student
from django import forms

# Form for custom user
class SignUpForm(UserCreationForm):
   class Meta:
      model = CustomUser
      fields = ('email', 'password1', 'password2')

class StudentCreationForm(forms.ModelForm):
    class Meta:
        model = Student
        fields = ['user','first_name','middle_name','last_name']

现在是主要部分,我创建了一个简单的内联 formset工厂将学生模型作为内联表单处理。

表单集

from django.forms import inlineformset_factory
from .models import CustomUser,Student
from .forms import StudentCreationForm

# As parameters I provided parent Model(CustomUser),child Model(Student) and the Child 
# ModelForm(StudentCreationForm) 

StudentCreationFormSet = inlineformset_factory(CustomUser, Student,form=StudentCreationForm,extra=1,can_delete = False)

在 View 中,我分别创建了 SignUpForm 和 StudentCreationFormSet 对象。首先在 POST 请求中,我验证了 CustomUser 表单并保存它而不提交它(commit=False)。我创建了一个自定义用户的对象,并将其作为实例传递给 StudentCreationFormSet 以验证相关表单。如果一切顺利,我的两个表单都将被保存,否则错误将显示在模板中。

查看

from django.shortcuts import render,redirect
from .forms import SignUpForm
from .formsets import StudentCreationFormSet 

def createAccountView(request):
    student_account_form = SignUpForm()
    student_details_formset = StudentCreationFormSet()

    if request.method == 'POST':
        student_account_form = SignUpForm(request.POST)

        if student_account_form.is_valid():
            # Validating Custom User form and creating object of it(not comitting as  formset needed to be verified)
            student_account = student_account_form.save(commit=False)
            # Getting Custom User object as passing it as instance to formset
            student_details_formset = StudentCreationFormSet (request.POST,instance=student_account)

            if student_details_formset.is_valid():
                student_account_form.save()
                student_details_formset.save()
                return redirect('login')    
            else:
                student_details_formset = StudentCreationFormSet (request.POST)

    context = {
        'student_account_form':student_account_form,
        'student_details_form':student_details_formset
    }
    return render(request, 'account/createStudentPage.html',context=context)

另请注意,我在单个帖子请求中传递表单和表单集。

模板(createStudentPage.html)

<form method="POST" >
    {% csrf_token %}
    {{ student_account_form.as_p }}
    {{ student_details_form.as_p }}
<button type="submit">Sign Up</button>
</form>

关于django - 将具有 OneToOne 关系的两个模型合并为一种形式 - Django,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31323497/

相关文章:

django - 如何在 django 中的 SelectDateWidget 中设置默认日期

Python,Django,在类内部使用 Import,似乎无法解决这个问题

html - django 为未选中的复选框保存一个值

python - 找不到 Django 模板

django rest 框架请求与 self.request

jquery - 如何使用 jQuery ajax 实时搜索 Django 中的模型?

Django:如果用户不是 super 用户,则在模板中隐藏按钮

django - 使用 ModelForm 和 UserProfile 编辑配置文件

Django:根据最新的子模型字段订购QuerySet

django __str__ 返回所有属性