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>