Form 表单 py文件
from django import forms
#定义一个form类注册用
class RegForm (forms.Form):
username =forms.CharField(
max_length=16,
label='用户名',
error_messages={
" max_length":"用户名长度最长为16位",
'required':'用户名不能为空',
},
widget=forms.widgets.TextInput(
attrs={'class': 'form-control'},
)
)
password =forms.CharField(
min_length=6,
label='密码',
widget=forms.widgets.PasswordInput(
attrs={"class": "form-control"},
render_value=True,
),
error_messages = {
"min_length": "密码至少要6位!",
"required": "密码不能为空",
}
)
re_password= forms.CharField(
min_length=6,
label='密码',
widget=forms.widgets.PasswordInput(
attrs={ 'class': 'form-control'},
render_value=True,
),
error_messages= {
'min_length':'密码至少要6位',
'required':'密码不能为空',
}
)
email =forms.EmailField(
label='邮箱',
widget=forms.widgets.EmailInput(
attrs={'class':'form-control'},
),
error_messages= {
'invalid': '邮箱格式不正确!',
'required':'邮箱不能为空',
}
)
settings文件
"""
Django settings for day77 project.
Generated by 'django-admin startproject' using Django 1.11.12.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
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 = '@qbulznqai1k%twz$(m)76#ztkt6%^+k2airzl5-pt@lu2v)oz'
# 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 = 'day77.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 = 'day77.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'),
# },
'default':{
'ENGINE':'django.db.backends.mysql',
'NAME':'day77',
'USER':'root',
'PASSWORD':'123456',
'HOST':'127.0.0.1',
'PORT':3306,
}
}
# 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'
TIME_ZONE = 'UTC'
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')
]
# 告诉Djanog 项目用哪张表做认证
AUTH_USER_MODEL='app01.UserInfo'
modules文件
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
'''
用户表
'''
nid =models.AutoField(primary_key=True)
phone =models.CharField(max_length=11,null=True,unique=True)
avatar = models.FileField(upload_to='avatars/',default='avatars/default.png',verbose_name='头像')
create_time =models.DateTimeField(auto_now_add=True)
blog =models.OneToOneField(to='Blog',to_field='nid',null=True)
def __str__(self):
return self.username
class Blog(models.Model):
'''
博客信息
'''
nid =models.AutoField(primary_key=True)
title =models.CharField(max_length=64)
site =models.CharField(max_length=32,unique=True)
theme =models.CharField(max_length=32)
def __str__(self):
return self.title
#
class Category(models.Model):
'''
个人博客文章分类
'''
nid =models.AutoField(primary_key=True)
title =models.CharField(max_length=32)#分类标题
blog = models.ForeignKey(to ='Blog',to_field='nid')#外键关联博客,一个博客站点可以有多个分类
def __str__(self):
return self.title
class Tag(models.Model):
''''
标签
'''
nid =models.AutoField(primary_key=True)
title =models.CharField(max_length=32)
blog =models.ForeignKey(to='Blog',to_field='nid') #所属博客
def __str__(self):
return self.title
class Article(models.Model):
'''
文章
'''
nid =models.AutoField(primary_key=True)
title = models.CharField(max_length=50) #文章标题描述
desc =models.CharField(max_length=255) #文章描述
create_time =models.DateTimeField()#创建时间
category = models.ForeignKey(to ='Category',to_field='nid',null=True)
user = models.ForeignKey(to='UserInfo',to_field='nid')
tags =models.ManyToManyField( # 中介模型
to ='Tag',
through='Article2Tag',
through_fields=('article','tag')#注意顺序
)
def __str__(self):
return self.title
class ArticleDetail(models.Model):
'''
文章详情
'''
nid =models.AutoField(primary_key=True)
content = models.TextField()
article =models.OneToOneField(to ='Article',to_field='nid')
class Article2Tag(models.Model):
'''
文章和标签的多对多关系表
'''
nid =models.AutoField(primary_key=True)
article =models.ForeignKey(to='Article',to_field='nid')
tag =models.ForeignKey(to ='Tag',to_field='nid')
class Meta:
unique_together = (('article','tag'),)
class ArticleUpDown(models.Model):
'''
点赞
'''
nid= models.AutoField(primary_key=True)
user =models.ForeignKey(to ='UserInfo',null=True)
article = models.BooleanField(default=True)
class Meta:
unique_together = (('article','user'),)
class Comment(models.Model):
'''
评论表
'''
nid = models.AutoField(primary_key=True)
article =models.ForeignKey(to ='Article',to_field='nid')
user =models.ForeignKey(to ='UserInfo',to_field='nid')
content =models.CharField(max_length=255)#评论内容
create_time =models.DateTimeField(auto_now_add=True)
parent_comment =models.ForeignKey('self',null=True)
def __str__(self):
return self.content
views文件
from app01 import form,models
from django.db import models
def reg(request):
if request.method=='POST':
ret={'status':0,'msg':''}
form_obj =form.RegForm(request.POST)
#帮我做校验
if form_obj.is_valid():
#校验通过,去数据库创建一个新的用户
form_obj.cleaned_data.pop('re_password')
avatar_img =request.FILES.get('avatar')
models.UserInfo.objects.create_user(**form_obj.cleaned_data,avatar =avatar_img)
ret['msg']= '/index/'
return JsonResponse(ret)
以上代码代表注册成功的情况
以下代码是注册失败的代码
else:
print(form_obj.errors)
ret['status']=1
ret['msg']= form_obj.errors
print(ret)
return JsonResponse(form_obj.errors)
# return render(request,'ret.html',{'form_obj': form_obj})
#生成一个form对象
form_obj = form.RegForm()
print(form_obj)
print("== "*120)
return render(request,'reg.html',{'form_obj': form_obj})
输入 web地址


前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/mystyle.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form novalidate autocomplete="off" action="/reg/" method="post" class="form-horizontal reg-form" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="{{ form_obj.username.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.username.label }}</label>
<div class="col-sm-8">
{{ form_obj.username }}
<span class="help-block">{{ form_obj.username.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{ form_obj.password.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.password.label }}</label>
<div class="col-sm-8">
{{ form_obj.password }}
<span class="help-block">{{ form_obj.password.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{ form_obj.re_password.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.re_password.label }}</label>
<div class="col-sm-8">
{{ form_obj.re_password }}
<span class="help-block">{{ form_obj.re_password.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label for="{{ form_obj.email.id_for_label }}"
class="col-sm-2 control-label">{{ form_obj.email.label }}</label>
<div class="col-sm-8">
{{ form_obj.email }}
<span class="help-block">{{ form_obj.email.errors.0 }}</span>
</div>
</div>
<div class="form-group">
<label
class="col-sm-2 control-label">头像</label>
<div class="col-sm-8">
<label for="id_avatar"><img id="avatar-img" src="/static/img/default.png" alt=""></label>
<input accept="image/*" type="file" name="avatar" id="id_avatar" style="display: none">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="button" class="btn btn-success" id="reg-submit">注册</button>
</div>
</div>
</form>
</div>
</div>
</div>
<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script>
// 找到头像的input标签绑定change事件
$("#id_avatar").change(function () {
// 1. 创建一个读取文件的对象
var fileReader = new FileReader();
// 取到当前选中的头像文件
// console.log(this.files[0]);
// 读取你选中的那个文件
fileReader.readAsDataURL(this.files[0]); // 读取文件是需要时间的
fileReader.onload = function () {
// 2. 等上一步读完文件之后才 把图片加载到img标签中
$("#avatar-img").attr("src", fileReader.result);
};
});
// AJAX提交注册的数据
$("#reg-submit").click(function () {
// 取到用户填写的注册数据,向后端发送AJAX请求
var formData = new FormData();
formData.append("username", $("#id_username").val());
formData.append("password", $("#id_password").val());
formData.append("re_password", $("#id_re_password").val());
formData.append("email", $("#id_email").val());
formData.append("avatar", $("#id_avatar")[0].files[0]);
formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
$.ajax({
url: "/reg/",
type: "post",
processData: false, // 告诉jQuery不要处理我的数据
contentType: false, // 告诉jQuery不要设置content类型
data: formData,
success:function (data) {
if (data.status){
// 有错误就展示错误
// console.log(data.msg);
// 将报错信息填写到页面上
$.each(data.msg, function (k,v) {
// console.log("id_"+k, v[0]);
// console.log($("#id_"+k));
$("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
})
}else {
// 没有错误就跳转到指定页面
location.href = data.msg;
}
}
})
});
// 将所有的input框绑定获取焦点的事件,将所有的错误信息清空
$("form input").focus(function () {
$(this).next().text("").parent().parent().removeClass("has-error");
});
// 给username input框绑定一个失去焦点的事件,失去焦点之后就校验用户名是否已被注册
{#$("#id_username").blur(function () {#}
$("#id_username").on("input", function () {
// 取到用户填写的值
var username = $(this).val();
// 发请求
$.ajax({
url: "/check_username_exist/",
type: "get",
data: {"username": username},
success: function (data) {
if (data.status){
// 用户名已被注册
$("#id_username").next().text(data.msg).parent().parent().addClass("has-error");
}
}
})
})
</script>
</body>
</html>
密码输入错误的案例
打印结果


传到前端的 代码
登录 views
def logout(request):
auth.logout(request)
return redirect('/index/')
def login(request):
# if request.is_ajax(): # 如果是AJAX请求
if request.method == "POST":
# 初始化一个给AJAX返回的数据
ret = {"status": 0, "msg": ""}
# 从提交过来的数据中 取到用户名和密码
username = request.POST.get("username")
pwd = request.POST.get("password")
# 获取极验 滑动验证码相关的参数
gt = GeetestLib(pc_geetest_id, pc_geetest_key)
challenge = request.POST.get(gt.FN_CHALLENGE, '')
validate = request.POST.get(gt.FN_VALIDATE, '')
seccode = request.POST.get(gt.FN_SECCODE, '')
status = request.session[gt.GT_STATUS_SESSION_KEY]
user_id = request.session["user_id"]
if status:
result = gt.success_validate(challenge, validate, seccode, user_id)
else:
result = gt.failback_validate(challenge, validate, seccode)
if result:
# 验证码正确
# 利用auth模块做用户名和密码的校验
user = auth.authenticate(username=username, password=pwd)
if user:
# 用户名密码正确
# 给用户做登录
auth.login(request, user) # 将登录用户赋值给 request.user
ret["msg"] = "/index/"
else:
# 用户名密码错误
ret["status"] = 1
ret["msg"] = "用户名或密码错误!"
else:
ret["status"] = 1
ret["msg"] = "验证码错误"
return JsonResponse(ret)
return render(request, "login.html")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/mystyle.css"> </head> <body> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">The Blog</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if request.user.username %} <li><a href="#">{{ request.user.username }}</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">个人中心<span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="/logout/">注销</a></li> </ul> </li> {% else %} <li><a href="/login/">登录</a></li> <li><a href="/reg/">注册</a></li> {% endif %} </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <!-- 主页面 开始--> <div class="container"> <div class="row"> <div class="col-md-2"> <div class="panel panel-primary"> <div class="panel-heading">左侧广告位一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-info"> <div class="panel-heading">左侧广告位二</div> <div class="panel-body"> Panel content </div> </div> </div> <div class="col-md-8"> <!-- 文章列表 开始 --> <div class="article-list"> {% for article in article_list %} <div class="article"> <h3><a href="">{{ article.title }}</a></h3> <div class="media"> <div class="media-left"> <a href="#"> <img class="media-object author-img" src="/media/{{ article.user.avatar }}" alt="..."> </a> </div> <div class="media-body"> <p>{{ article.desc }}</p> </div> </div> <div class="article-footer"> <span><a href="">{{ article.user.username }}</a></span>发布于 <span>{{ article.create_time|date:'Y-m-d H:i:s' }}</span> <span class="glyphicon glyphicon-comment">评论({{ article.comment_count }})</span> <span class="glyphicon glyphicon-thumbs-up">点赞({{ article.up_count }})</span> </div> </div> {% endfor %} </div> <!-- 文章列表 结束--> </div> <div class="col-md-2"> <div class="panel panel-primary"> <div class="panel-heading">右侧广告位一</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-info"> <div class="panel-heading">右侧广告位二</div> <div class="panel-body"> Panel content </div> </div> </div> </div> </div> <!-- 主页面 结束--> <script src="/static/jquery-3.3.1.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> </body> </html>
基于object查询 于基于queryset查询.

