You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python-Django自定义用户模型下多类型用户注册表单与视图实现咨询

Hey there! Let's work through your multi-type user registration setup step by step. I’ll break this down into manageable pieces to get your tabbed registration forms up and running smoothly.

First: Fix Model Consistency

I noticed your PersonalBelow18 model uses multi-table inheritance (directly inheriting from User), while all other user type models use a OneToOneField to link to User. This inconsistency can lead to unexpected database behavior. Let’s align all models to use OneToOneField for uniformity:

# models.py
class PersonalBelow18(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    dob = models.DateField(blank=False)
    customer_id = models.BigIntegerField(blank=False)
    collection_use_personal_data = models.BooleanField(blank=False)

Step 1: Build Registration Forms

We’ll create a base form for the core User fields, plus separate forms for each user type’s unique fields. This keeps things modular and easy to maintain.

# forms.py
from django import forms
from .models import User, PersonalBelow18, PersonalAbove18, Parent, GroupContactPerson

# Base form for core User model fields
class UserBaseForm(forms.ModelForm):
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('email', 'title', 'gender', 'contenst')

    def clean_password2(self):
        # Validate password match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save password in hashed format
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

# Forms for each user type's unique fields
class PersonalBelow18Form(forms.ModelForm):
    class Meta:
        model = PersonalBelow18
        fields = ('dob', 'customer_id', 'collection_use_personal_data')

class PersonalAbove18Form(forms.ModelForm):
    class Meta:
        model = PersonalAbove18
        fields = ('dob', 'customer_id', 'contact_email', 'contact_no', 'collection_use_personal_data')

class ParentForm(forms.ModelForm):
    class Meta:
        model = Parent
        fields = ('contact_email', 'contact_no', 'collection_use_personal_data')

class GroupContactPersonForm(forms.ModelForm):
    class Meta:
        model = GroupContactPerson
        fields = ('contact_email', 'contact_no', 'department', 'address')

Step 2: Handle Form Submissions in Views

Create a single view to manage all form submissions. It’ll validate the core user form first, then save the corresponding user type profile based on the selected tab.

# views.py
from django.shortcuts import render, redirect
from .forms import (
    UserBaseForm, PersonalBelow18Form, PersonalAbove18Form,
    ParentForm, GroupContactPersonForm
)

def register(request):
    if request.method == 'POST':
        user_form = UserBaseForm(request.POST)
        if user_form.is_valid():
            # Save core user first
            user = user_form.save()
            # Get hidden user_type value from the submitted tab
            user_type = request.POST.get('user_type')

            # Save corresponding user type profile
            if user_type == 'PB':
                pb_form = PersonalBelow18Form(request.POST)
                if pb_form.is_valid():
                    profile = pb_form.save(commit=False)
                    profile.user = user
                    profile.save()
            elif user_type == 'PA':
                pa_form = PersonalAbove18Form(request.POST)
                if pa_form.is_valid():
                    profile = pa_form.save(commit=False)
                    profile.user = user
                    profile.save()
            elif user_type == 'Parent':
                parent_form = ParentForm(request.POST)
                if parent_form.is_valid():
                    profile = parent_form.save(commit=False)
                    profile.user = user
                    profile.save()
            elif user_type == 'GC':
                gc_form = GroupContactPersonForm(request.POST)
                if gc_form.is_valid():
                    profile = gc_form.save(commit=False)
                    profile.user = user
                    profile.save()
            
            # Redirect to login page after successful registration
            return redirect('login')
    else:
        # Initialize all forms for GET requests
        user_form = UserBaseForm()
        pb_form = PersonalBelow18Form()
        pa_form = PersonalAbove18Form()
        parent_form = ParentForm()
        gc_form = GroupContactPersonForm()
    
    context = {
        'user_form': user_form,
        'pb_form': pb_form,
        'pa_form': pa_form,
        'parent_form': parent_form,
        'gc_form': gc_form
    }
    return render(request, 'registration/register.html', context)

Step 3: Build the Tabbed UI Template

Use Bootstrap (or custom CSS) to create tabbed sections. Each tab will show the core user fields plus the unique fields for that user type, with a hidden user_type field to tell the view which profile to save.

<!-- templates/registration/register.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Register</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2>Create Your Account</h2>
        
        <!-- Tab Navigation -->
        <ul class="nav nav-tabs mt-3" id="userTabs" role="tablist">
            <li class="nav-item">
                <a class="nav-link active" id="pb-tab" data-toggle="tab" href="#pb" role="tab">Personal (Under 18)</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" id="pa-tab" data-toggle="tab" href="#pa" role="tab">Personal (18+)</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" id="parent-tab" data-toggle="tab" href="#parent" role="tab">Parent/Guardian</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" id="gc-tab" data-toggle="tab" href="#gc" role="tab">Group Contact</a>
            </li>
        </ul>

        <!-- Tab Content & Form -->
        <div class="tab-content mt-3 p-3 border border-top-0" id="userTabContent">
            <form method="post">
                {% csrf_token %}
                
                <!-- Personal Under 18 Tab -->
                <div class="tab-pane fade show active" id="pb" role="tabpanel">
                    {{ user_form.as_p }}
                    <input type="hidden" name="user_type" value="PB">
                    {{ pb_form.as_p }}
                </div>

                <!-- Personal 18+ Tab -->
                <div class="tab-pane fade" id="pa" role="tabpanel">
                    {{ user_form.as_p }}
                    <input type="hidden" name="user_type" value="PA">
                    {{ pa_form.as_p }}
                </div>

                <!-- Parent Tab -->
                <div class="tab-pane fade" id="parent" role="tabpanel">
                    {{ user_form.as_p }}
                    <input type="hidden" name="user_type" value="Parent">
                    {{ parent_form.as_p }}
                </div>

                <!-- Group Contact Tab -->
                <div class="tab-pane fade" id="gc" role="tabpanel">
                    {{ user_form.as_p }}
                    <input type="hidden" name="user_type" value="GC">
                    {{ gc_form.as_p }}
                </div>

                <button type="submit" class="btn btn-primary mt-3">Register</button>
            </form>
        </div>
    </div>

    <!-- Bootstrap JS for tab functionality -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Quick Notes for Improvement

  • Custom Form Rendering: Replace as_p with Bootstrap form classes (like form-control) for a cleaner look.
  • Error Handling: The view will automatically show form errors if submission fails—you can style these to match your UI.
  • Field Prepopulation: Add JavaScript to reset fields when switching tabs, so users don’t see leftover data from other tabs.

内容的提问来源于stack exchange,提问作者Abdul Rehman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:08:55