Django内置form表单和ajax制作注册页面

settings.py
import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'j_tk9_=-$do&e0zih&zn+%=k0z@i8z(g31+j7699v33!fsoiib'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'about_formday71.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'about_formday71.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'

# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^login/', views.login),
    url(r'^reg/', views.reg),
    url(r'^index/', views.index),
]

 forms.py

from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from app01.models import GENDER_CHOICES, DEFAULT_GENDER, UserInfo


class RegForm(forms.Form):
    name = forms.CharField(
        max_length=12,
        min_length=3,
        label='用户名',
        widget=forms.widgets.TextInput()
    )
    password = forms.CharField(
        max_length=20,
        min_length=6,
        label='密码',
        widget=forms.widgets.PasswordInput()
    )
    re_password = forms.CharField(
        max_length=20,
        min_length=6,
        label='确认密码',
        widget=forms.widgets.PasswordInput()
    )
    phone = forms.CharField(
        max_length=11,
        min_length=11,
        label='手机',
        widget=forms.widgets.TextInput(),
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号码格式不正确'), ]
    )
    email = forms.CharField(
        label='邮箱',
        widget=forms.widgets.EmailInput(),
        validators=[RegexValidator(r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$', '邮箱格式不正确'), ]
    )
    gender = forms.ChoiceField(
        label='性别',
        widget=forms.widgets.RadioSelect(),
        choices=GENDER_CHOICES,
        initial=DEFAULT_GENDER,
    )

    # 写一个局部钩子方法,校验用户名是否已被注册
    def clean_name(self):
        name_value = self.cleaned_data.get('name')
        is_exist = UserInfo.objects.filter(name=name_value)
        if is_exist:
            raise ValidationError('用户名已存在')
        else:
            return name_value

    # 写一个局部钩子方法,校验手机号是否已被注册
    def clean_phone(self):
        phone_value = self.cleaned_data.get('phone')
        is_exist = UserInfo.objects.filter(phone=phone_value)
        if is_exist:
            raise ValidationError('手机号已存在')
        else:
            return phone_value

    def clean(self):
        # 判断密码和确认密码是否相等
        # self.cleaned_data  --> 所有经过校验的数据
        pwd = self.cleaned_data.get('password')
        re_pwd = self.cleaned_data.get('re_password')
        if pwd == re_pwd:
            # print(self.cleaned_data)
            # print('-' * 120)
            return self.cleaned_data  # 明确返回
        else:
            self.add_error('re_password', '两次密码不一致')
            raise ValidationError('两次密码不一致')

    def __init__(self, *args, **kwargs):
        super(RegForm, self).__init__(*args, **kwargs)
        for field in iter(self.fields):
            # print(field, type(field))
            if field == 'gender':
                continue
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })

models.py

from django.db import models

# Create your models here.

GENDER_CHOICES = ((0, ''), (1, ''), (2, '保密'))
DEFAULT_GENDER = 2


class UserInfo(models.Model):
    name = models.CharField(max_length=12, unique=True)
    password = models.CharField(max_length=20)
    phone = models.CharField(max_length=11, unique=True)
    email = models.EmailField()
    gender = models.PositiveIntegerField(choices=GENDER_CHOICES, default=DEFAULT_GENDER)


    def __str__(self):
        return self.name

views.py

from django.shortcuts import render, HttpResponse, redirect
from app01.forms import RegForm
from app01.models import UserInfo
from django.http import JsonResponse
# Create your views here.


# 登录
def login(request):
    return HttpResponse('login')


# 注册
def reg(request):
    if request.method == 'POST':
        res = {'code': 0}
        # 利用post提交的数据实例化form类
        form_obj2 = RegForm(request.POST)
        # 校验数据的有效性
        if form_obj2.is_valid():  # form_obj2.cleaned_data
            form_obj2.cleaned_data.pop('re_password')
            UserInfo.objects.create(**form_obj2.cleaned_data)
            res['url'] = '/login/'
        else:
            # 数据有问题
            res['code'] = 1
            res['error_msg'] = form_obj2.errors
        return JsonResponse(res)

    form_obj = RegForm()
    # print(locals())
    # print('-' * 120)
    # return render(request, 'reg.html', locals())
    return render(request, 'reg.html', {'form_obj': form_obj})


# 首页
def index(request):
    return HttpResponse('index')

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7/css/bootstrap.css' %}">
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="/reg/" method="post" novalidate id="f1">
                {% csrf_token %}
                {% for field in form_obj %}
                    <div class="form-group">
                        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                        {{ field }}
                        <span class="help-block"></span>
                    </div>
                {% endfor %}
                <div>
                    <button type="button" id="b1" class="btn btn-success">注册</button>
                </div>
            </form>
        </div>
    </div>
</div>
<script src="{% static 'jquery.js' %}"></script>
<script>
    $('#b1').click(function () {
        // 清除之前的报错提示
        var dataObj = {};
        $('input').each(function () {
            dataObj[$(this).attr('name')] = $(this).val();
        });
        console.log(dataObj);
        // 取到input标签的值
        $.ajax({
            url: '/reg/',
            type: 'post',
            data: dataObj,
            success: function (res) {
                console.log(res);
                // 把所有的错误提示信息展示到页面的指定位置
                if (res.code === 0){
                    // 没错
                    location.href = res.url;
                }else {
                    $.each(res.error_msg, function (k, v) {
                        // 根据k找到对应的input框,把v中第一个字符串显示出来
                        $('#id_'+k).next('span').text(v[0]).parent().addClass('has-error');
                    })
                }
            }
        })
    });
    // input标签获取焦点之后清除之前的错误提示
    $('form input').focus(function () {
        $(this).next('span').text('').parent().removeClass('has-error');
    })
</script>
</body>
</html>

 

posted @ 2018-11-16 15:28  从入门到出师  阅读(395)  评论(0编辑  收藏  举报