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

Django自定义表单中raise forms.ValidationError不生效及表单优化咨询

Hey there! Let's fix those two issues you're facing with your Django signup form—getting validation errors to show up on the form page instead of jumping to an error screen, and simplifying your custom template setup.

Fixing Validation Error Display

The core problem here is that your view is raising a ValidationError when forms are invalid, which triggers Django's default error page instead of keeping the user on the signup form. Here's how to fix this step by step:

Step 1: Update Your View Logic

Instead of throwing an exception, just pass the invalid form instances back to the template. This way, all error messages stay attached to the forms and can be displayed directly. Here's the revised views.py code:

def user_signup(request):
    registered = False
    if request.method == 'POST':
        user_form = UserSignupForm(data=request.POST)
        user_pro_form = UserProfileSignupForm(data=request.POST)
        if user_form.is_valid() and user_pro_form.is_valid():
            # Save user with hashed password
            user = user_form.save()
            user.set_password(user.password)
            user.save()
            # Link and save user profile
            user_pro = user_pro_form.save(commit=False)
            user_pro.user = user
            user_pro.save()
            registered = True
            # Redirect to avoid duplicate submissions on page refresh
            # return redirect('your_login_url_name')
        # No need for raise—invalid forms are retained and passed to template
    else:
        # Initialize empty forms for GET requests
        user_form = UserSignupForm()
        user_pro_form = UserProfileSignupForm()
    
    # Pass forms and registration status to the template
    return render(request, 'accounts/registration/customer_signup.html', {
        'user_form': user_form,
        'user_pro_form': user_pro_form,
        'registered': registered
    })

Step 2: Modify the Template to Show Errors

Since you're manually writing input fields, you need to add error display for each field and global non-field errors. Update your template like this:

{% extends 'accounts/registration/base.html' %}
{% block content %}
{% load bootstrap3 %}
<div class="container">
    <h1>Sign Up</h1>
    
    <!-- Show success message if registration is complete -->
    {% if registered %}
        <div class="alert alert-success">
            Registration successful! Please log in.
        </div>
    {% endif %}
    
    <!-- Show global non-field errors -->
    {% if user_form.non_field_errors or user_pro_form.non_field_errors %}
        <div class="alert alert-danger">
            {% for error in user_form.non_field_errors %}
                <p>{{ error }}</p>
            {% endfor %}
            {% for error in user_pro_form.non_field_errors %}
                <p>{{ error }}</p>
            {% endfor %}
        </div>
    {% endif %}
    
    <form method="POST">
        {% csrf_token %}
        
        <!-- Email field with error feedback -->
        <div class="form-group">
            <label for="email">Email</label>
            <input type="email" name="email" id="email" 
                   value="{{ user_form.email.value|default_if_none:'' }}" 
                   class="form-control {% if user_form.email.errors %}is-invalid{% endif %}">
            {% if user_form.email.errors %}
                <div class="invalid-feedback">
                    {% for error in user_form.email.errors %}
                        {{ error }}
                    {% endfor %}
                </div>
            {% endif %}
        </div>
        
        <!-- Repeat this pattern for all other fields -->
        <div class="form-group">
            <label for="phonenumber">Phone Number</label>
            <input type="text" name="phonenumber" id="phonenumber" 
                   value="{{ user_pro_form.phonenumber.value|default_if_none:'' }}" 
                   class="form-control {% if user_pro_form.phonenumber.errors %}is-invalid{% endif %}">
            {% if user_pro_form.phonenumber.errors %}
                <div class="invalid-feedback">
                    {% for error in user_pro_form.phonenumber.errors %}
                        {{ error }}
                    {% endfor %}
                </div>
            {% endif %}
        </div>
        
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" name="name" id="name" 
                   value="{{ user_pro_form.name.value|default_if_none:'' }}" 
                   class="form-control {% if user_pro_form.name.errors %}is-invalid{% endif %}">
            {% if user_pro_form.name.errors %}
                <div class="invalid-feedback">
                    {% for error in user_pro_form.name.errors %}
                        {{ error }}
                    {% endfor %}
                </div>
            {% endif %}
        </div>
        
        <div class="form-group">
            <label for="password1">Password</label>
            <input type="password" name="password1" id="password1" 
                   class="form-control {% if user_form.password1.errors %}is-invalid{% endif %}">
            {% if user_form.password1.errors %}
                <div class="invalid-feedback">
                    {% for error in user_form.password1.errors %}
                        {{ error }}
                    {% endfor %}
                </div>
            {% endif %}
        </div>
        
        <div class="form-group">
            <label for="password2">Confirm Password</label>
            <input type="password" name="password2" id="password2" 
                   class="form-control {% if user_form.password2.errors %}is-invalid{% endif %}">
            {% if user_form.password2.errors %}
                <div class="invalid-feedback">
                    {% for error in user_form.password2.errors %}
                        {{ error }}
                    {% endfor %}
                </div>
            {% endif %}
        </div>
        
        <div class="form-group">
            <label for="alternavite_mobile_number">Alternative Mobile Number</label>
            <input type="text" name="alternavite_mobile_number" id="alternavite_mobile_number" 
                   value="{{ user_pro_form.alternavite_mobile_number.value|default_if_none:'' }}" 
                   class="form-control {% if user_pro_form.alternavite_mobile_number.errors %}is-invalid{% endif %}">
            {% if user_pro_form.alternavite_mobile_number.errors %}
                <div class="invalid-feedback">
                    {% for error in user_pro_form.alternavite_mobile_number.errors %}
                        {{ error }}
                    {% endfor %}
                </div>
            {% endif %}
        </div>
        
        <input type="submit" class="btn btn-default" value="SignUp">
    </form>
</div>
{% endblock %}

Simplifying Your Custom Form Template

Since you're already using bootstrap3, you can skip writing all those input fields manually—use Bootstrap's form rendering tags to handle fields, labels, and errors automatically. This cuts down on repetitive code drastically:

Revised Simplified Template

{% extends 'accounts/registration/base.html' %}
{% block content %}
{% load bootstrap3 %}
<div class="container">
    <h1>Sign Up</h1>
    
    {% if registered %}
        <div class="alert alert-success">
            Registration successful! Please <a href="{% url 'login' %}">log in</a>.
        </div>
    {% endif %}
    
    <form method="POST">
        {% csrf_token %}
        
        <!-- Show global errors -->
        {% if user_form.non_field_errors or user_pro_form.non_field_errors %}
            <div class="alert alert-danger">
                {% for error in user_form.non_field_errors %}
                    <p>{{ error }}</p>
                {% endfor %}
                {% for error in user_pro_form.non_field_errors %}
                    <p>{{ error }}</p>
                {% endfor %}
            </div>
        {% endif %}
        
        <!-- Render entire user form with Bootstrap styling -->
        {% bootstrap_form user_form %}
        
        <!-- Render entire profile form with Bootstrap styling -->
        {% bootstrap_form user_pro_form %}
        
        <button type="submit" class="btn btn-default">Sign Up</button>
    </form>
</div>
{% endblock %}

This works because {% bootstrap_form %} automatically renders each field with its label, input, and associated error messages (in proper Bootstrap error styling). Just make sure your UserSignupForm and UserProfileSignupForm classes are correctly defined—for example, set password1 and password2 as PasswordInput widgets, and add a clean method to check password matches.

One final tip: After successful registration, always redirect the user (like to the login page) instead of just rendering the template. This prevents duplicate form submissions if the user refreshes the page.

内容的提问来源于stack exchange,提问作者Pankaj Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:47:55