使用 Django FORM 自定义表单 API

Customize Form with Django FORM API

我目前正在使用 Django 框架创建一个 register/login 表单,因为我是这个框架的新手,所以我对 FORM API.

了解不多

我没有使用 FORM API,因为我不知道是否可以自定义它。 有什么方法可以将我的样式与 FORM API 一起使用吗? 作为现在的状态,我只是在创建自己的一个,而不使用 API,但是由于 FORM API 更安全并且可以更快地设置用户创建,我想使用它。

所以我的问题是,我可以使用 FORM API 实现自定义样式吗?包括<input>,<div>等..

这是我的 HTML 表格:

{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}

    <div class="limiter">
        <div class="container-login100" style="background:black;">
            <div class="wrap-login100">
                <form class="login100-form validate-form"  method='POST' action="{% url 'users:register' %}" >
                    {% csrf_token %}
                    <span class="login100-form-logo">
                        <i class="zmdi zmdi-landscape"></i>
                    </span>
                    <span class="login100-form-title p-b-34 p-t-27">
                        Register
                    </span>
                    <div class="wrap-input100 validate-input" data-validate = "Enter username">
                        <input class="input100" type="text" name="username" placeholder="Username" required>
                        <span class="focus-input100" data-placeholder="&#xf207;"></span>
                    </div>
                    <div class="wrap-input100 validate-input" data-validate="Enter password">
                        <input class="input100" type="password" name="pass" placeholder="Password" required>
                        <span class="focus-input100" data-placeholder="&#xf191;"></span>
                    </div>
    
                    <div class="wrap-input100 validate-input" data-validate="Confirm password">
                        <input class="input100" type="password" name="pass-confirm" placeholder="Confirm Password" required>
                        <span class="focus-input100" data-placeholder="&#xf191;"></span>
                    </div>
    
                    <div class="wrap-input100 validate-input" data-validate="Enter Email">
                        <input class="input100" type="email" name="mail" placeholder="E-Mail" required>
                        <span class="focus-input100" data-placeholder="&#xf191;"></span>
                    </div>
    
                    <div class="container-login100-form-btn">
                        <button class="login100-form-btn" type="submit" name="submit" value="submit">
                            Register
                        </button>
                    </div>
    
                    <div class="text-center p-t-90">
                        <a class="txt1" href="login">
                            Already registered?
                        </a>
                    </div>
    
                </form>
            </div>
        </div>
    </div>

这是我的 views.py 后端:

def register(request):
    if request.method == "POST":
        username = request.POST["username"]
        password = request.POST["pass"]
        password_confirm = request.POST["pass-confirm"]
        email = request.POST["mail"]
        submit = request.POST["submit"]
        
        
        print("UserName : ", username)
        print('Email : ', email)
        print('Password : ', password)
        print('Password Confirm : ', password_confirm)
        
        SpecialSym =['$', '@', '#', '%', '?']
        confirm = False
        
        if request.POST.get("submit"):
            if len(username) < 7:
                
                print('Username must be more than 10 char.')
                confirm = False
                messages.error(request, "Username must be more than 10 char.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if len(username) > 15:
          
                print('Username must be less than 15 char.')
                confirm = False
                messages.error(request, "Username must be less than 15 char.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if any(char in SpecialSym for char in username):
                print('Username can\'t contain special characters.')
                confirm = False
                messages.error(request, "Username can't contain special characters", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if len(password) < 8:
                print("Your password is too short")
                confirm = False
                messages.error(request, "Your password is too short.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if len(password) > 25:
                print("Your password must be less than 25 char")
                confirm = False
                messages.error(request, "Your password must be less than 25 char.", 'red')
                return HttpResponseRedirect(reverse('users:register')) 
            
            if not any(char.isdigit() for char in password):
                print('Password should have at least one numeral')
                confirm = False
                messages.error(request, "Your password should have at least one numeral ", 'red')
                return HttpResponseRedirect(reverse('users:register'))

            if not any(char.isupper() for char in password):
                print('Password should have at least one uppercase letter')
                confirm = False
                messages.error(request, "Your password should have at least one uppercase letter ", 'red')
                return HttpResponseRedirect(reverse('users:register'))
                
            if not any(char.islower() for char in password):
                print('Password should have at least one lowercase letter')
                confirm = False
                messages.error(request, "Your password should have at least one lowercase letter ", 'red')
                return HttpResponseRedirect(reverse('users:register'))
                        
            if not any(char in SpecialSym for char in password):
                print('Password should have at least one of the symbols $@#?')
                confirm = False
                messages.error(request, "Your password should have at least one of these symbols: $@#? ", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if (password != password_confirm):
                print("Passwords don't match")
                confirm = False
                messages.error(request, "Passwords don't match.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
                
            if confirm == True:
                
                messages.success(request, "Success! form submitted.", 'green')
                return HttpResponseRedirect(reverse('users:register'))
                
                
    return render(request, 'users/register.html')

可以使用in-builtUserCreationForm[django-doc],在路径from django.contrib.auth.forms import UserCreationForm.

现在,作为您当前的代码,您不需要使用 messages 框架,因为 in-built Form 已经有很多验证,您已经完成了。

在您的代码中,您可以通过以下方式实现,只需这样做:

我只提供了一个最小的可复制示例,因为模板中有很多 css class,所以我只在每个字段中添加 my_class,您可以添加自己的class,用Ctrl+Upage source即可看到。

urls.py

from django.urls import path
from . import views
app_name = 'users'
urlpatterns = [
    path('', views.register, name='home'),
    path('success/', views.success, name='success')
]

views.py

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
from django.urls import reverse

from home.forms import MyUserCreationForm


def register(request):
    if request.method == 'POST':
        form = MyUserCreationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password1 = form.cleaned_data['password1']
            email = form.cleaned_data['email']
            user_data = User(username=username,
                             password=make_password(password1), email=email)

            user_data.save()
            return HttpResponseRedirect(reverse('users:success'))
    else:
        form = MyUserCreationForm()
    return render(request, 'users/register.html', {'form': form})


def success(request):
    return render(request, 'users/thanks.html')

forms.py

from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth import password_validation

from django.utils.translation import gettext, gettext_lazy as _
from django.contrib.auth.models import User


class MyUserCreationForm(UserCreationForm):
    password1 = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput(
            attrs={'autocomplete': 'new-password', 'class': 'my_class', 'placeholder': 'password'}),
        help_text=password_validation.password_validators_help_text_html(),
        error_messages={'required': 'password is required'}
    )
    password2 = forms.CharField(
        label=_("Password confirmation"),
        widget=forms.PasswordInput(
            attrs={'autocomplete': 'new-password', 'class': 'my_class', 'placeholder': 'confirm password'}),
        strip=False,
        help_text=_("Enter the same password as before, for verification."),
        error_messages={'required': 'password confirm is required'}
    )
    email = forms.CharField(widget=forms.EmailInput(
        attrs={'class': 'my_class', 'placeholder': 'Email'}), error_messages={'required': 'Email is required'})

    class Meta:
        model = User
        fields = ['username', 'email']
        error_messages = {
            'username': {'required': 'Username is required'},
        }
        widgets = {
            'username': forms.TextInput(attrs={'class': 'myclass', 'placeholder': 'Username'}),
        }

Note: you can use any class in any field, you can change here for every field attrs={'class': 'my_class'), I have used my_class in every field just for example, you can view it in page source.

Note: The example might be a bit complex, since I have inherited and changed the django's inbuilt form for adding css classes.

register.html 或模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .red{
            color:red;
            font-size:1.15rem;
        }
    </style>
</head>
<body>
    {% if form %}
    <form method="POST" novalidate>
        {% csrf_token %}
        {% if form.non_field_errors %}
        {% for error in form.non_field_errors %}
        <div class="red">
            <p>{{error}}</p>
        </div>
        {% endfor %}
        {% endif %}

        {% for field in form %}
        <div>
            {{field.label_tag}} {{field}}
            <br>
            {% for error in field.errors  %}
                <div class="red">
                    <span>{{error}}</span>
                </div>
            {% endfor %}
        </div>
        {% endfor %}
        <input type="submit" value="Save">
    </form>
    {% else %}
    <p>There is some error, form does not come from view.</p>
    {% endif %}
</body>
</html>

thanks.html(提交成功后用于重定向)

<body>
    <h2>You are now a user! logged in !</h2>
</body>

通过这个例子,你的数据已经成功保存在数据库中,你可以通过创建超级用户,通过python manage.py createsuperuser 并登录到管理站点,在Users [=72]中看到它=].

基于class authentication views[django-doc].

,上述工作可以变得更容易