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

问题描述 投票:0回答:2

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

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

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

谢谢您的帮助!型号如下:

MyUser:] >>

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)

UserProfile:

] >>
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)

我创建了两个自定义用户模型(AbstractBaseUser和一个用于获取更多信息的单独模型)。有没有一种方法可以将两个模型结合起来以创建一种表单,用户可以使用该表单来更新其所有......>

我认为您可以执行类似的操作:

class ProfileChangeForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ['user__username', 'user__email', 'user__first_name', 'user__last_name', 'bio', 'website']

以下解决方案为我工作。我使用表单集来创建此解决方案。我的模型如下,

型号:

#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)

之后,我创建了两个ModelForms

表格

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工厂,以嵌入式形式处理Student模型。

表单集

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)

在视图中,我分别创建了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 django-models django-forms django-views
2个回答
1
投票

我认为您可以执行类似的操作:


1
投票

以下解决方案为我工作。我使用表单集来创建此解决方案。我的模型如下,

型号:

© www.soinside.com 2019 - 2024. All rights reserved.