Web框架本质 web系统概念
1. Http,无状态,短连接 2. 浏览器(socket客户端)、网站(socket服务端)
web框架本质
import socket def handle_request (client ): buf = client.recv(1024 ) client.send("HTTP/1.1 200 OK\r\n\r\n" ) client.send("Hello, Seven" ) def main (): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost' ,8000 )) sock.listen(5 ) while True : connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__' : main()
自定义Web框架
a. socket服务端 b. 根据URL不同返回不同的内容 路由系统: URL -> 函数 c. 字符串返回给用户 模板引擎渲染: HTML充当模板(特殊字符) 自己创造任意数据 字符串
静态网站处理方式:
import socket def f1 (request ): f = open ('index.fsw' ,'rb' ) data = f.read() f.close() return data def f2 (request ): f = open ('aricle.tpl' ,'rb' ) data = f.read() f.close() return data routers = [ ('/xxx' , f1), ('/ooo' , f2), ] def run (): sock = socket.socket() sock.bind(('127.0.0.1' ,8080 )) sock.listen(5 ) while True : conn,addr = sock.accept() data = conn.recv(8096 ) data = str (data,encoding='utf-8' ) headers,bodys = data.split('\r\n\r\n' ) temp_list = headers.split('\r\n' ) method,url,protocal = temp_list[0 ].split(' ' ) conn.send(b"HTTP/1.1 200 OK\r\n\r\n" ) func_name = None for item in routers: if item[0 ] == url: func_name = item[1 ] break if func_name: response = func_name(data) else : response = b"404" conn.send(response) conn.close() if __name__ == '__main__' : run()
动态网站处理方式一(手动进行替换的模版引擎):
import socketdef f3 (request ): import pymysql conn = pymysql.connect(host='127.0.0.1' , port=3306 , user='root' , passwd='123' ,db='db666' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('select id,username,password from userinfo' ) user_list = cursor.fetchall() cursor.close() conn.close() content_list=[] for row in user_list: tp = '<tr><td>%s</td><td>%s</td><td>%s</td></tr>' %(row['id' ],row['username' ],row['password' ]) content_list.append(tp) content = "" .join(content_list) f = open ('userlist.html' ,'r' ,encoding='utf-8' ) template = f.read() f.close() data = template.replace('@@sdfsdffd@@' , content) return bytes (data, encoding='utf-8' ) routers = [ ('/userlist.htm' , f3), ] def run (): sock = socket.socket() sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) sock.bind(('127.0.0.1' ,8080 )) sock.listen(5 ) while True : conn,addr = sock.accept() data = conn.recv(8096 ) data = str (data,encoding='utf-8' ) headers,bodys = data.split('\r\n\r\n' ) temp_list = headers.split('\r\n' ) method,url,protocal = temp_list[0 ].split(' ' ) conn.send(b"HTTP/1.1 200 OK\r\n\r\n" ) func_name = None for item in routers: if item[0 ] == url: func_name = item[1 ] break if func_name: response = func_name(data) else : response = b"404" conn.send(response) conn.close() if __name__ == '__main__' : run()
Django项目前期配置
pip3 install django # 创建Django程序 django-admin startproject mysite # 进入程序目录 cd mysite # 启动socket服务端,等待用户发送请求 python manage.py runserver 127.0.0.1:8080
Django配置文件:
settings.py
……
DIRS’: [os.path.join(BASE_DIR, ‘template’)],
……
Mysql数据库: DATABASES = { 'default' : { 'ENGINE' : 'django.db.backends.mysql' , 'NAME' :'dbname' , 'USER' : 'root' , 'PASSWORD' : 'xxx' , 'HOST' : '' , 'PORT' : '' , } } import pymysql pymysql.install_as_MySQLdb()
静态文件路径: static目录
STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static' ), )
额外配置(跨站请求伪装crsf):
项目案例
网站请求
urlpatterns = [ url(r'^index/' ,index), ] def index (request ): return render(request, 'index.html' ,{ 'name' : 'tom' , 'users' :['李志' ,'李杰' ], 'user_dict' :{ 'k1' :'v1' , 'k2' :'v2' }, 'user_list_dict' :[ { 'id' :1 ,'name' : 'tom' , 'email' :'tom@1231.com' }, { 'id' :1 , 'name' :'tom' , 'email' :'tom@1231.com' }, { 'id' :1 , 'name' :'tom' , 'email' :'tom@1231.com' }, ] })
网站登陆
import url from django.contrib import admin from django.shortcuts import HttpResponse,render,redirect urlpatterns = [ url(r'^login/' ,login), ] def login (request ): return HttpResponse('<input type="text" />' )
django学员管理系统
数据库设计结构
表结构:班级\学生\老师 (班级表): id title 1 全4 期 2 全5 期 学生表): id name 班级ID(FK) 1 张杰 1 老师表): id name 1 林峰 2 林狗 3 苑天 老师班级关系表): id 老师ID 班级ID 1 1 1 2 1 2 3 2 2
班级管理模块
查(母版继承)
urlpatterns = [ url(r'classes/' , views.classes), ]
import render,redirect import pymysql def classes (request ): conn = pymysql.connect(host='127.0.0.1' , port=3306 , user='root' , password='123' , db='s4db65' , charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select id, title from class" ) class_list = cursor.fetchall() cursor.close() conn.close() print(class_list) return render(request, 'classes.html' ,{'class_list' :class_list})
增
urlpatterns = [ url(r'^add_class/' , views.add_class), ]
def add_class (request ): if request.method == 'GET' : return render(request,'add_class.html' ) else : print(request.POST) v = request.POST.get('title' ) conn = pymysql.connect(host='127.0.0.1' ,port=3306 ,user='root' ,passwd='123' ,db='s4db65' ,charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('insert into class(title) value(%s)' , [v,]) conn.commit() cursor.close() conn.close() return redirect('/classes/' )
删
urlpatterns = [ url(r'^del_class/' , views.del_class), ]
def del_class (request ): nid = request.GET.get('nid' ) conn = pymysql.connect(host='127.0.0.1' , port=3306 , user='root' , passwd='123' , db='s4db65' , charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('delete from class where id=%s' ,[nid,]) conn.commit() cursor.close() conn.close() return redirect('/classes/' )
改
urlpatterns = [ url(r'^edit_class/' , views.edit_class), ]
def edit_class (request ): if request.method == 'GET' : nid = request.GET.get('nid' ) conn = pymysql.connect(host='127.0.0.1' ,port=3306 ,user='root' ,passwd = '123' , db='s4db65' ,charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('select id, title from class where id=%s' , [nid,]) result = cursor.fetchone() cursor.close() conn.close() print(result) return render(request,'edit_class.html' ,{'result' :result}) else : nid = request.GET.get('nid' ) title = request.POST.get('title' ) print(nid, title) conn = pymysql.connect(host='127.0.0.1' ,port=3306 ,user='root' ,passwd='123' ,db='s4db65' , charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('update class set title=%s where id=%s' ,[title,nid,]) conn.commit() cursor.close() conn.close() return redirect('/classes/' )
模态对话框实现增加班级功能
urlpatterns = [url(r'^modal_add_class/' , views.modal_add_class]
def modify (sql,args ): conn = pymysql.connect(host='127.0.0.1' , port=3306 , user='root' , passwd='123' , db='s4db65' , charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute(sql,args) conn.commit() cursor.close() conn.close() ---------- def modal_add_class (request ): title = request.POST.get('title' ) if len (title) > 0 : sqlheper.modify('insert into class (title) value(%s)' ,[title,]) return HttpResponse('ok' ) else : return HttpResponse('班级标题不能为空' )
学生管理模块
查
url(r'^students/' ,views.students),
def students (request ): conn = pymysql.connect(host='127.0.0.1' ,port=3306 ,user='root' ,passwd='123' ,db='s4db65' ,charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('select student.id,student.name,class.title from student left JOIN class on student.class_id = class.id' ) student_list = cursor.fetchall() cursor.close() conn.close() print('结果:' ,student_list) return render(request,'students.html' ,{'student_list' :student_list})
增
url(r'^add_student/' ,views.add_student)
def add_student (request ): if request.method == 'GET' : conn = pymysql.connect(host='127.0.0.1' ,port=3306 ,user='root' ,passwd='123' ,db='s4db65' ,charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('select id,title from class' ) class_list = cursor.fetchall() cursor.close() conn.close() return render(request,'add_student.html' ,{'class_list' :class_list}) else : name = request.POST.get('name' ) class_id = request.POST.get('class_id' ) conn = pymysql.connect(host='127.0.0.1' ,port=3306 ,user='root' ,passwd='123' ,db='s4db65' ,charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute('insert into student(name,class_id)values(%s,%s)' ,[name,class_id,]) conn.commit() cursor.close() conn.close() return redirect('/students/' )
改
url(r'^edit_student/' ,views.edit_student),
from utils import sqlheper def edit_student (request ): if request.method == "GET" : nid = request.GET.get('nid' ) class_list = sqlheper.get_list("select id,title from class" ,[]) current_student_info = sqlheper.get_one('select id,name,class_id from student where id=%s' ,[nid,]) print('结果:' ,class_list,current_student_info,nid) return render(request,'edit_student.html' ,{'class_list' : class_list,'current_student_info' :current_student_info}) else : nid = request.GET.get('nid' ) name = request.POST.get('name' ) class_id = request.POST.get('class_id' ) sqlheper.modify('update student set name=%s,class_id=%s where id=%s' ,[name,class_id,nid,]) return redirect('/students/' )
模态对话框实现增
url(r'^modal_add_student/' , views.modal_add_student),
def modal_add_student (request ): ret = {'status' :True ,'message' :None } try : name = request.POST.get('name' ) print('result' ,name) class_id = request.POST.get('class_id' ) sqlheper.modify('insert into student (name,class_id)values(%s,%s)' ,[name,class_id,]) except Exception as e: ret['status' ]=False ret['message' ]=str [e] return HttpResponse(json.dumps(ret))
模态对话框实现改
url(r'^modal_edit_student/' , views.modal_edit_student),
def modal_edit_student (request ): ret = {'status' : True ,'message' : None } try : nid = request.POST.get('nid' ) name = request.POST.get('name' ) class_id = request.POST.get('class_id' ) sqlheper.modify('update student set name=%s,class_id=%s where id=%s' ,[name,class_id,nid,]) except Exception as e: ret['status' ] = False ret['message' ] = str (e) return HttpResponse(json.dumps(ret))
老师管理模块
查
url(r'^teachers/' , views.teachers),
def teachers (request ): teacher_list = sqlheper.get_list('select id,name from teacher' ,[]) teacher_list = sqlheper.get_list( LEFT JOIN teacher2class on teacher.id = teacher2class.teacher_id print(teacher_list) result = {} for row in teacher_list: tid =row['tid' ] if tid in result: result[tid]['titles' ].append(row['title' ]) lse: result[tid] = {'tid' : row['tid' ],'name' :row['name' ],'titles' : [row['title' ],]} return render(request,'teacher.html' ,{'teacher_list' :result.values()})
增
url(r'^add_teacher/' , views.add_teacher),
def add_teacher (request ): if request.method == "GET" : class_list = sqlheper.get_list('select id,title from class' ,[]) return render(request,'add_teacher.html' ,{'class_list' : class_list}) else : name = request.POST.get('name' ) teacher_id = sqlheper.create('insert into teacher(name) values(%s)' ,[name,]) class_ids = request.POST.getlist('class_ids' ) for cls_id in class_ids: temp = (teacher_id,cls_id,) data_list.append(temp) obj = sqlheper.SqlHelper() obj.multiple_modify('insert into teacher2class(teacher_id,class_id) values(%s,%s)' ,data_list) obj.close() return redirect('/teachers/' )
改
url(r'^edit_teacher/' ,views.edit_teacher),
def edit_teacher (request ): if request.method == "GET" : nid = request.GET.get('nid' ) obj = sqlheper.SqlHelper() teacher_info = obj.get_one('select id,name from teacher where id =%s' ,[nid,]) class_id_list = obj.get_list('select class_id from teacher2class where teacher_id=%s' ,[nid,]) class_list = obj.get_list('select id,title from class' ,[]) obj.close() print('当前老师信息' ,teacher_info) print('当前老师任教的班级id' ,class_id_list) temp = [] for i in class_id_list: temp.append(i['class_id' ]) print('所有班级' ,class_list) return render(request,'edit_teacher.html' ,{ 'teacher_info' : teacher_info, 'class_id_list' : temp, 'class_list' : class_list, }) else : nid = request.GET.get('nid' ) name = request.POST.get('name' ) class_ids = request.POST.getlist('class_ids' ) obj = sqlheper.SqlHelper() obj.modify('update teacher set name=%s where id=%s' ,[name,nid]) obj.modify('delete from teacher2class where teacher_id=%s' ,[nid,]) data_list = [] for cls_id in class_ids: temp = (nid,cls_id,) data_list.append(temp) obj = sqlheper.SqlHelper() obj.multiple_modify('insert into teacher2class(teacher_id,class_id) values(%s,%s)' ,data_list) obj.close() return redirect('/teachers/' )
模态对话框增
url(r'^get_all_class/' , views.get_all_class), url(r'^modal_add_teacher/' , views.modal_add_teacher),
def get_all_class (request ): obj = sqlheper.SqlHelper() class_list = obj.get_list('select id,title from class' ,[]) return HttpResponse(json.dumps(class_list)) def modal_add_teacher (request ): ret = {'status' : True ,'message' : None } try : name = request.POST.get('name' ) class_id_list = request.POST.getlist('class_id_list' ) teacher_id = sqlheper.create('insert into teacher(name) values(%s)' ,[name,]) data_list = [] for cls_id in class_id_list: temp = (teacher_id,cls_id,) data_list.append(temp) obj = sqlheper.SqlHelper() obj.multiple_modify('insert into teacher2class(teacher_id,class_id) values(%s,%s)' ,data_list) obj.close() except Exception as e: ret['status' ] = False ret['message' ] = "处理失败" return HttpResponse(json.dumps(ret))
def create (sql,args ): conn = pymysql.connect(host='127.0.0.1' , port=3306 , user='root' , passwd='' , db='s4db65' , charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute(sql,args) conn.commit() last_row_id = cursor.lastrowid cursor.close() conn.close() return last_row_id class SqlHelper (object ): def __init__ (self ): self.connect() def connect (self ): self.conn = pymysql.connect(host='127.0.0.1' , port=3306 , user='root' , passwd='' , db='s4db65' , charset='utf8' ) self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor) def multiple_modify (self,sql,args ): self.cursor.executemany(sql,args) self.conn.commit() def close (self ): self.cursor.close() self.conn.close()
用户登陆(包含cookies内容)
url(r'^login/' , views.login),
def login (request ): if request.method == "GET" : return render(request,'login.html' ) else : user = request.POST.get('username' ) pwd = request.POST.get('password' ) if user == 'tom' and pwd == '123' : obj = redirect('/classes/' ) obj.set_signed_cookie('ticket' ,"567" ,salt='jjjjjj' ,max_age=900 ,path='/' ) return obj else : return render(request,'login.html' ) def classes (request ): tk = request.get_signed_cookie('ticket' ,salt='jjjjjj' ) print(tk) if not tk: return redirect('/login/' ) conn = pymysql.connect(host='127.0.0.1' , port=3306 , user='root' , passwd='' , db='s4db65' , charset='utf8' ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select id,title from class" ) class_list = cursor.fetchall() cursor.close() conn.close() return render(request, 'classes.html' , {'class_list' : class_list})
def index (request ): obj = HttpResponse('...' ) obj.set_cookie(.....) request.COOKIES.get(...) obj.set_signed_cookie(.....) request.get_signed_cookie(....)
动态路由
urls
views
def edit (request,*args,**kwargs ): print(args,kwargs) return HttpResponse('...' )
路由分发
#路由分发实现不同模块分开编辑,团队协作开发 url(r'^app01/' , include('app01.urls' )), url(r'^app02/' , include('app02.urls' )),
反向生成URL(Django独有)
通过别名反射成URL,简化URL的填写, 用于权限管理
url(r'^edit/(\w+)/(\w+)/' , views.edit,name='n2' ),
ORM基本操作(数据表+数据行操作
操作前的配置步骤
__init__.py文件 (ORM默认使用SQLlite连接数据库,需改成Mysql) 添加: import pymysql pymysql.install_as_MySQLdb()
在mysql中手动创建数据库
TEMPLATES = [ …… 'DIRS' : [os.path.join(BASE_DIR,'templates' )],…… ] DATABASES = { 'default' : { 'ENGINE' : 'django.db.backends.mysql' , 'NAME' :'s4day70db' , 'USER' : 'root' , 'PASSWORD' : '' , 'HOST' : 'localhost' , 'PORT' : 3306 , } }
操作表
创建表
from django.db import models class UserInfo (models.Model ): nid = models.BigAutoField(primary_key=True ) username = models.CharField(max_length=32 ) password = models.CharField(max_length=64 )
NSTALLED_APPS = [ …… 'app01' , ]
python manage.py makemigrations python manage.py migrate
修改表:
class UserInfo (models.Model ): …… age = models.IntegerField(default=1 )
python manage.py makemigrations python manage.py migrate
删除表:
创建外键关联:
class UserGroup (models.Model ): title = models.CharField(max_length=32 ) class UserInfo (models.Model ): …… ug = models.ForeignKey('UserGroup' ,null=True ,on_delete='' )
操作单表数据行:
from app01 import models models.UserGroup.objects.create(title='销售部' )
models.UserGroup.objects.filter (id =2 ).delete()
models.UserGroup.objects.filter (id =2 ).update(title='公关部' )
group_list = models.UserGroup.objects.all () group_list = models.UserGroup.objects.filter (id =1 ) group_list = models.UserGroup.objects.filter (id__gt=1 ) group_list = models.UserGroup.objects.filter (id__lt=1 )
Django视图CBV
urls
url(r'^login.html$' , views.Login.as_view),
views
from django.views import View class Login (View ): def dispatch (self, request, *args, **kwargs ): print('before' ) obj = super (Login,self).dispatch(request, *args, **kwargs) print('after' ) return obj def get (self,request ): return render(request,'login.html' ) def post (self,request ): print(request.POST.get('user' )) return HttpResponse('Login.post' )
ORM连表操作(一对多)(一对多中,外键存在于从表中)
models
from django.db import models class UserType (models.Model ): title = models.CharField(max_length=32 ) class UserInfo (models.Model ): 用户表 name = models.CharField(max_length=16 ) age = models.IntegerField() ut = models.ForeignKey('UserType' ,on_delete='' )
urls
url(r'^test.html$' , views.test),
views
一对多的正向操作(让存在外键的从表进行跨表,去查询关联主表中的字段):
obj = models.UserInfo.objects.all ().first() print(obj.name,obj.age,obj.ut.title)
v1 = models.UserInfo.objects.values('id' ,'name' ,'ut__title' )
result = models.UserInfo.objects.all ().values_list('id' ,'name' .'ut__title' )
一对多的反向操作(让主表进行跨表,去查询(有外键关联字段)从表中相应的字段作为查询条件或查询结果):
obj = models.UserType.objects.all ().first() for row in obj.userinfo_set.all (): print(row.name,row.age)
v2 = models.UserType.objects.values('id' ,'title' ,'userinfo__name' )
result = models.UserType.objects.all ().values_list('id' ,'name' ,'userinfo__name' )
一对多其他参考:
1. q = UserInfo.objects.all ().first() q.ug.title 2. UserInfo.objects.values('nid' ,'ug_id' ) UserInfo.objects.values('nid' ,'ug_id' ,'ug__title' ) 3. UserInfo.objects.values_list('nid' ,'ug_id' ,'ug__title' ) 1. 小写的表名_set obj = UserGroup.objects.all ().first() result = obj.userinfo_set.all () [userinfo对象,userinfo对象,] 2. 小写的表名 v = UserGroup.objects.values('id' ,'title' ) v = UserGroup.objects.values('id' ,'title' ,'小写的从表名称' ) v = UserGroup.objects.values('id' ,'title' ,'小写的从表名称__age' ) 3. 小写的表名 v = UserGroup.objects.values_list('id' ,'title' ) v = UserGroup.objects.values_list('id' ,'title' ,'小写的表名称' ) v = UserGroup.objects.values_list('id' ,'title' ,'小写的表名称__age' )
ORM连表操作(多对多)
(多对多中,主表与从表的外键都共同存在于第3张关联表中) ##
手动创建第三张关联表(推荐,手动更灵活)
from django.db import models class Boy (models.Model ): name = models.CharField(max_length=32 ) class Girl (models.Model ): nick = models.CharField(max_length=32 ) class Love (models.Model ): b = models.ForeignKey('Boy' ,on_delete='' ) g = models.ForeignKey('Girl' ,on_delete='' ) class Meta : unique_together = [ ('b' ,'g' ), ]
objs = [ models.Boy(name='方少伟' ), models.Boy(name='由秦兵' ), models.Boy(name='陈涛' ), models.Boy(name='闫龙' ), models.Boy(name='吴彦祖' ), ] models.Boy.objects.bulk_create(objs,5 ) objss = [ models.Girl(nick='小鱼' ), models.Girl(nick='小周' ), models.Girl(nick='小猫' ), models.Girl(nick='小狗' ), ] models.Girl.objects.bulk_create(objss,5 )
Django自动生成第三张关联表(无法再手动添加其它字段)
class Boy (models.Model ): name = models.CharField(max_length=32 ) m = models.ManyToManyField('Girl' ) class Girl (models.Model ): nick = models.CharField(max_length=32 )
手动与自动结合
class Boy (models.Model ): name = models.CharField(max_length=32 ) m = models.ManyToManyField(to='Girl' ,through="Love" ,through_fields=('b' ,'g' ,)) class Girl (models.Model ): nick = models.CharField(max_length=32 ) class Love (models.Model ): b = models.ForeignKey('Boy' ,on_delete='' ) g = models.ForeignKey('Girl' ,on_delete='' ) class Meta : unique_together = [ ('b' ,'g' ), ]
obj = models.Boy.objects.filter (name='方少伟' ).first() obj.m.add(1 )
ORM连表操作(多对多自关联)
原理:等同于复制出一张新表
models
class UserInfo (models.Model ): nickname = models.CharField(max_length=32 ) username = models.CharField(max_length=32 ) password = models.CharField(max_length=64 ) gender_choices = ( (1 ,'男' ), (2 ,'女' ), ) gender = models.IntegerField(choices=gender_choices) m = models.ManyToManyField('UserInfo' )
def test (request ): xz = models.UserInfo.objects.filter (id =1 ).first() u = xz.m.all () for row in u: print(row.nickname) xz = models.UserInfo.objects.filter (id =4 ).first() v = xz.userinfo_set.all () for row in v: print(row.nickname) return HttpResponse('...' )
外键自关联(常用于评论表功能)
等同于复制出一张新表,用原表中的外键作连表操作
class Comment (models.Model ): news_id = models.IntegerField() content = models.CharField(max_length=32 ) user = models.CharField(max_length=32 ) reply = models.ForeignKey('Comment' ,null=True ,blank=True ,related_name='xxxx' ) 新闻ID reply_id 1 别比比 root null 1 就比比 root null 1 瞎比比 shaowei null 2 写的正好 root null 1 拉倒吧 由清滨 2 1 拉倒吧1 xxxxx 2 1 拉倒吧2 xxxxx 5 新闻1 别比比 就比比 - 拉倒吧 - 拉倒吧2 - 拉倒吧1 瞎比比 新闻2 : 写的正好
ORM操作补充(models模块中数据表属性定义操作)
models
from django.db import models from django.core.validators import RegexValidator class UserAdmin (models.Model ): username = models.CharField(max_length=32 ) email = models.EmailField( ull=True , default='111' , db_index=True , unique=True , blank=True , verbose_name='邮箱' , editable=True , help_text='字段提示信息的内容' , ) file = models.FileField() ctime = models.DateTimeField() test = models.CharField( max_length=32 , error_messages={ 'c1' : '优先错信息1' , }, validators=[RegexValidator(regex='root_\d+' , message='错误了' , code='c1' )], null=True ) num = models.DecimalField(max_digits=30 ,decimal_places=10 ) olor_list = ( (1 ,'黑色' ), (2 ,'白色' ), (3 ,'蓝色' ) ) color = models.IntegerField(choices=color_list) class Meta : unique_together=( ('email' ,'username' ) ) index_together=( ('email' ,'username' ) ) 的∂
from django.contrib import admin from app01 import models admin.site.register(models.UserAdmin)
分页查询
内置分页函数
urls
url(r'^index.html$' , views.index),
views
from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage def index (request ): user_list = models.UserInfo.objects.all () paginator = Paginator(user_list,10 ) current_page = request.GET.get('page' ) try : posts = paginator.page(current_page) except PageNotAnInteger as e: posts = paginator.page(1 ) except EmptyPage as e: posts = paginator.page(1 ) return render(request,'index.html' ,{'posts' :posts})
ORM补充之基本操作(数据行高级操作)
排序
user_list = models.UserInfo.objects.all ().order_by('-id' ,'name' )
分组
from django.db.models import Count,Sum,Max,Min v =models.UserInfo.objects.values('ut_id' ).annotate(xxxx=Count('id' )) SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id `) AS `xxxx` FROM `app01_userinfo` GROUP BY `app01_userinfo`.`ut_id` ORDER BY NULL
v =models.UserInfo.objects.values('ut_id' ).annotate(xxxx=Count('id' )).filter (xxxx__gt=2 ) SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id `) AS `xxxx` FROM `app01_userinfo` GROUP BY `app01_userinfo`.`ut_id` HAVING COUNT(`app01_userinfo`.`id `) > 2 ORDER BY NULL
v =models.UserInfo.objects.filter (id__gt=2 ).values('ut_id' ).annotate(xxxx=Count('id' )).filter (xxxx__gt=2 ) SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id `) AS `xxxx` FROM `app01_userinfo` WHERE `app01_userinfo`.`id ` > 2 GROUP BY `app01_userinfo`.`ut_id` HAVING COUNT(`app01_userinfo`.`id `) > 2 ORDER BY NULL
分组格式:model.类名.objects.values(显示的字段名).annotate(作为字段查结结果的别名=Count(字段id /1 ))
条件过滤
models.UserInfo.objects.filter (id__gt=1 ) ……(id__lt=1 ) ……(id__lte=1 ) ……(id__gte=1 ) ……(id__in=[1 ,2 ,3 ]) ……(name__startswith='xxxx' ) ……(name__contains='xxxx' ) ……exclude(id =1 ) not in (id =1 )
F,Q,extra方法
F
from django.db.models import F models.UserInfo.objects.all ().update(age=F("age" )+1 )
Q(构造复杂的查询条件)
from django.db.models import Q models.UserInfo.objects.filter (Q(id__gt=1 )) models.UserInfo.objects.filter (Q(id =8 ) | Q(id =2 )) models.UserInfo.objects.filter (Q(id =8 ) & Q(id =2 ))
方法方式
from django.db.models import Q q1 = Q() q1.connector = 'OR' q1.children.append(('id__gt' , 1 )) q1.children.append(('id' , 10 )) q2 = Q() q2.connector = 'OR' q2.children.append(('c1' , 1 )) q2.children.append(('c1' , 10 )) q3 = Q() q3.connector = 'AND' q3.children.append(('id' , 1 )) q3.children.append(('id' , 2 )) q1.add(q3,'OR' ) con = Q() con.add(q1, 'AND' ) con.add(q2, 'AND' )
方法方式实际应用(多条件组合查询时)
condition_dict = { 'k1' :[1 ,2 ,3 ,4 ], 'k2' :[1 ,], } con = Q() for k,v in condition_dict.items(): q = Q() q.connector = 'OR' for i in v: q.children.append(('id' , i)) con.add(q,'AND' ) models.UserInfo.objects.filter (con) *********************************************************************** q1 = Q() q1.connector = 'OR' q1.children.append(('id' , 1 )) q1.children.append(('id' , 10 )) q1.children.append(('id' , 9 )) q2 = Q() q2.connector = 'OR' q2.children.append(('c1' , 1 )) q2.children.append(('c1' , 10 )) q2.children.append(('c1' , 9 )) q3 = Q() q3.connector = 'AND' q3.children.append(('id' , 1 )) q3.children.append(('id' , 2 )) q1.add(q3,'OR' ) con = Q() con.add(q1, 'AND' ) con.add(q2, 'AND' )
extra(添加额外的自定义sql语句)
models.UserInfo.objects.extra(self, select=None , where=None , params=None , tables=None , order_by=None , select_params=None ) a. 映射 select select_params=None select 此处 from 表 b. 条件 where=None params=None , select * from 表 where 此处 c. 表 tables select * from 表,此处 c. 排序 order_by=None select * from 表 order by 此处
v = models.UserInfo.objects.all ().extra( select={ 'n' :"select count(1) from app01_usertype where id=%s or id=%s" , 'm' :"select count(1) from app01_usertype where id=%s or id=%s" , }, select_params=[1 ,2 ,3 ,4 ] ) for obj in v: print(obj.name,obj.id ,obj.n) ---------- 等价于将查询结果作为字段显示列:
models.UserInfo.objects.extra( select={ 'newid' :'select count(1) from app01_usertype where id>%s' }, select_params=[1 ,], where = ['age>%s' ], params=[18 ,], order_by=['-age' ], tables=['app01_usertype' ] ) ---------- 等价于原生sql语句如下: select app01_userinfo.id , (select count(1 ) from app01_usertype where id >1 ) as newid from app01_userinfo,app01_usertype where app01_userinfo.age > 18 order by app01_userinfo.age desc
result = models.UserInfo.objects.filter (id__gt=1 ).extra( where=['app01_userinfo.id < %s' ], params=[100 ,], tables=['app01_usertype' ], order_by=['-app01_userinfo.id' ], select={ 'uid' :1 , 'sw' :"select count(1) from app01_userinfo" } ) ---------- SELECT (1 ) AS "uid" , (select count(1 ) from app01_userinfo) AS "sw" , "app01_userinfo" ."id" , "app01_userinfo" ."name" , "app01_userinfo" ."age" , "app01_userinfo" ."ut_id" FROM "app01_userinfo" , "app01_usertype" WHERE ("app01_userinfo" ."id" > 1 AND (app01_userinfo.id < 100 )) ORDER BY ("app01_userinfo" .id ) DESC
取特定字段值
v = models.UserInfo.objects.all ().only('id' ,'name' )
取当前字段以外的所有值
v = models.UserInfo.objects.all ().defer('name' )
反转
v = models.UserInfo.objects.all ().order_by('-id' ,'name' ).reverse()
使用数据库引擎
models.UserInfo.objects.all ().using('db2' )
聚合
from django.db.models import Count result = models.UserInfo.objects.aggregate(k=Count('ut_id' , distinct=True ), n=Count('id' ))
以字典格式添加数据
obj = models.UserType.objects.create(**{'title' : 'xxx' })
以关键字参数添加数据
obj = models.UserType.objects.create(title='xxx' )
批量增加数据
objs = [ models.UserInfo(name='r11' ), ] models.UserInfo.objects.bulk_create(objs, 10 )
创建/获取
obj, created = models.UserInfo.objects.get_or_create( username='root1' , pwd='ff' , defaults={'email' : '1111111' ,'u_id' : 2 , 't_id' : 2 } )
条件范围
models.UserInfo.objects.in_bulk([1 ,2 ,3 ]) models.UserInfo.objects.filter (id__in=[1 ,2 ,3 ])
raw(书写原生sql语句)
name_map = {'title' : 'name' } v1 = models.UserInfo.objects.raw('SELECT id,title FROM app01_usertype' ,translations=name_map) for i in v1: print(i,type (i))
select_related:查询主动做连表,一次性获取所有连表中的数据(性能相关:数据量少的情况下使用)
q = models.UserInfo.objects.all ().select_related('ut' ,'gp' )
prefetch_related:不做连表,但会做多次查询(性能相关:数据量多,查询频繁下使用)
q = models.UserInfo.objects.all ().prefetch_related('ut' )
XSS攻击(跨站脚本攻击)
模拟攻击时:前提需要将对应设置注释 MIDDLEWARE = [ ]
urls
url(r'^index/' , views.index), url(r'^comment/' , views.comment),
views
def comment (request ): if request.method == "GET" : return render(request,'comment.html' ) else : v = request.POST.get('content' ) msg.append(v) return render(request,'comment.html' ) def index (request ): return render(request,'index.html' ,{'msg' :msg})
def test (request ): from django.utils.safestring import mark_safe temp = "<a href='http://www.baidu.com'>百度</a>" newtemp = mark_safe(temp) return render(request,'test.html' ,{'temp' :newtemp})
黑客可通过伪造网站,进行xss攻击,获得用户访问正式网站中的cookies, 从而伪装该用户可到正式网站进行操作,所以cookies很重要,要xss要处于启动状态(默认xss为启用状态)
CSRF(跨站请求伪装攻击)
urls
views
def csrf1 (request ): if request.method == 'GET' : return render(request,'csrf1.html' ) else : return HttpResponse('ok' )
补充:csrf第二种处理方式:添加装饰器
from django.views import View from django.utils.decorators import method_decorator def wrapper (func ): def inner (*args,**kwargs ): return func(*args,**kwargs) return inner
class Foo (View ): @method_decorator(wrapper) def get (self,request ): pass def post (self,request ): pass
@method_decorator(wrapper,name='XXX') class Foo (View ): def get (self,request ): pass def post (self,request ): pass
views
def csrf1 (request ): if request.method == 'GET' : return render(request,'csrf1.html' ) else : return HttpResponse('ok' )
ORM函数相关(html模版上使用函数)simple_tag
setting注册程序块
INSTALLED_APPS = [ …… 'app01' , ]
总结:
- simple_filter - 最多两个参数,格式: {{第一个参数|函数名称:"第二个参数" }} - 可以做条件判断 - simple_tag - 无限制: {% 函数名 参数 参数%}
cookie和session(推荐使用session)
cookie是保存在客户端浏览器上的键值对, Session是保存在服务端的数据(本质是键值对) 因为单独使用cookies,它会保留用户具体的明文形式(不转化成字符串的敏感信息)发送给浏览器(不安全),所以推荐使用session, session发送的是随机字符串,不包含用户敏感信息(安全),其中session依赖于cookies,
urls
urlpatterns = [ …… url(r'^login/' , views.login), url(r'^index/' , views.index), ]
views
def login (request ): if request.method == 'GET' : return render(request,'login.html' ) else : u = request.POST.get('user' ) p = request.POST.get('pwd' ) obj = models.UserAdmin.objects.filter (username=u,password=p).first() if obj: { 'username' :'alex' , 'email' :'x' ... } return redirect('/index/' ) else : return render(request,'login.html' ,{'msg' :'用户名或密码错误' }) def index (request ): v = request.session.get('username' ) if v: return HttpResponse('登录成功:%s' %v) else : return redirect('/login/' )
setting
用户登陆demo
models
from django.db import models class Boy (models.Model ): nickname = models.CharField(max_length=32 ) username = models.CharField(max_length=32 ) password = models.CharField(max_length=63 ) class Girl (models.Model ): nickname = models.CharField(max_length=32 ) username = models.CharField(max_length=32 ) password = models.CharField(max_length=63 ) class B2G (models.Model ): b = models.ForeignKey(to='Boy' , to_field='id' ,on_delete='' ) g = models.ForeignKey(to='Girl' , to_field='id' ,on_delete='' )
urls
urlpatterns = [ url('admin/' , admin.site.urls), url(r'^login.html$' , account.login), url(r'^index.html$' , love.index), url(r'^loginout.html$' ,account.loginout), url(r'^others.html$' ,love.others), ]
views(创立文件夹的形式用来区分模块关系)
account模块
from django.shortcuts import render,HttpResponse,redirect from app01 import models def login (request ): :param request: :return : if request.method == 'GET' : return render(request,'login.html' ) else : user = request.POST.get('username' ) pwd = request.POST.get('password' ) gender = request.POST.get('gender' ) rmb = request.POST.get('rmb' ) if gender == "1" : obj = models.Boy.objects.filter (username=user,password=pwd).first() else : obj = models.Girl.objects.filter (username=user,password=pwd).first() if not obj: return render(request,'login.html' ,{'msg' : '用户名或密码错误' }) else : request.session['user_info' ] = {'user_id' :obj.id ,'gender' :gender,'username' :user,'nickname' :obj.nickname} return redirect('/index.html' ) def loginout (request ): param request: :return : if request.session.get('user_info' ): request.session.clear()
love模块
from django.shortcuts import render,redirect,HttpResponse from app01 import models def index (request ): 首页信息展示 :param request: :return : if not request.session.get('user_info' ): return redirect('/login.html' ) else : gender = request.session.get('user_info' ).get('gender' ) if gender == '1' : user_list = models.Girl.objects.all () else : user_list = models.Boy.objects.all () return render(request,'index.html' ,{'user_list' :user_list}) def others (request ): 获取与当前用户有关系的异性 :param request: :return : current_user_id = request.session.get('user_info' ).get('user_id' ) gender = request.session.get('user_info' ).get('gender' ) if gender == '1' : user_list = models.B2G.objects.filter (b_id=current_user_id).values('g__nickname' ) else : user_list = models.B2G.objects.filter (g_id=current_user_id).values('b__nickname' ) print('result' , user_list) return render(request,'others.html' ,{'user_list' :user_list})
建立html组件:user_header
urls
urlpatterns = [ …… url(r'^login/$' , views.login), ]
views
from django.forms import Form,fields class LoginForm (Form ): username = fields.CharField( max_length=18 , min_length=6 , required=True , error_messages={ 'required' : '用户名不能为空' , 'min_length' : '太短了' , 'max_length' : '太长了' , } ) password = fields.CharField(min_length=16 ,required=True ) def login (request ): if request.method == "GET" : return render(request,'login.html' ) else : obj = LoginForm(request.POST) if obj.is_valid(): print(obj.cleaned_data) return redirect('http://www.baidu.com' ) else : return render(request,'login.html' ,{'obj' :obj})
Form验证流程分析
第一步: 实例化,将字段转换为self.fields格式 LoginForm实例化时, self.fields={ 'user' : 正则表达式 'pwd' : 正则表达式 }
第二步: 循环self.fields,获得字段 flag = True errors cleaned_data for k,v in self.fields.items(): input_value = request.POST.get(k) 校验input_value的值是否匹配正则表达式 flag = False return flag --------------------------------------- if obj.is_valid(): print(obj.cleaned_data) else : print(obj.errors) return render(request,'login.html' )
urls
…… url(r'^ajax_login/' , views.ajax_login),
views
class LoginForm (Form ): user = fields.CharField(required=True ,min_length=6 ) pwd = fields.CharField(min_length=18 ) def ajax_login (request ): import json ret={'status' : True ,'msg' :None } obj = LoginForm(request.POST) if obj.is_valid(): print(obj.cleaned_data) else : ret['status' ]=False ret['msg' ]=obj.errors v=json.dumps(ret) print(obj.errors) return HttpResponse(v)
Form组件常用字段及参数
class TestForm (Form ): t1 = fields.CharField( required=True , max_length=8 , min_length=2 , error_messages={ 'required' : '不能为空' , 'max_length' : '太长' , 'min_length' : '太短' , } ) t2 = fields.IntegerField( min_value=10 , max_value=1000 , error_messages={ 'required' : 't2不能为空' , 'invalid' : 't2格式错误,必须是数字' , 'min_value' : '必须大于10' , 'max_value' : '必须小于1000' , }, ) t3 = fields.EmailField( error_messages={ 'required' : 't3不能为空' , 'invalid' : 't3格式错误,必须是邮箱格式' , } ) t4=fields.URLField() t5=fields.SlugField() t6=fields.GenericIPAddressField() t7=fields.DateField() t8=fields.DateTimeField() t9=fields.RegexField('139\d+' )
生成HTML标签: widget=widgets.Select, ******** 用于指定生成怎样的HTML,select,text,input /. label='用户名' ,
urls
url(r'^register/' , views.register),
views
class RegiterForm (Form ): user = fields.CharField(min_length=8 ) email = fields.EmailField() password = fields.CharField() phone = fields.RegexField('139\d+' ) def register (request ): if request.method == 'GET' : obj = RegiterForm() return render(request,'register.html' ,{'obj' :obj}) else : obj = RegiterForm(request.POST) if obj.is_valid(): print(obj.cleaned_data) else : print(obj.errors) return render(request,'register.html' ,{'obj' :obj})
Form组件完成学员管理系统
models
from django.db import models class Classes (models.Model ): title = models.CharField(max_length=32 ) def __str__ (self ): return self.title class Student (models.Model ): name = models.CharField(max_length=32 ) email = models.CharField(max_length=32 ) age = models.IntegerField(max_length=32 ) cls = models.ForeignKey('Classes' ,on_delete='' ) class Teacher (models.Model ): tname = models.CharField(max_length=32 ) c2t = models.ManyToManyField('Classes' )
班级管理
查
def class_list (request ): cls_list = models.Classes.objects.all () return render(request,'class_list.html' ,{'cls_list' :cls_list})
增
class ClassForm (Form ): title = fields.RegexField('全栈\d+' ) def add_class (request ): if request.method == 'GET' : obj = ClassForm() return render(request,'add_class.html' ,{'obj' :obj}) else : obj = ClassForm(request.POST) if obj.is_valid(): models.Classes.objects.create(**obj.cleaned_data) return redirect('/class_list/' ) return render(request, 'add_class.html' , {'obj' : obj})
改
…… 省略Form组件定义类 …… def edit_class (request, nid ): if request.method == 'GET' : row = models.Classes.objects.filter (id =nid).first() obj = ClassForm(initial={'title' : row.title}) return render(request,'edit_class.html' ,{'nid' :nid,'obj' :obj}) else : obj = ClassForm(request.POST) if obj.is_valid(): models.Classes.objects.filter (id =nid).update(**obj.cleaned_data) return redirect('/class_list/' ) return render(request,'edit_class.html' ,{'nid' : nid,'obj' :obj})
学生管理
查
def student_list (request ): stu_list = models.Student.objects.all () return render(request, 'student_list.html' , {'stu_list' :stu_list})
增
class StudentForm (Form ): name = fields.CharField( min_length=2 , max_length=6 , widget=widgets.TextInput(attrs={'class' : 'form-control' }) ) email = fields.EmailField( widget=widgets.TextInput(attrs={'class' : 'form-control' }) ) age = fields.IntegerField( min_value=18 , max_value=25 , widget=widgets.TextInput(attrs={'class' : 'form-control' }) ) cls_id = fields.IntegerField( widget=widgets.Select( choices=models.Classes.objects.values_list('id' ,'title' ), attrs={'class' : 'form-control' } ) cls_id=fields.ChoiceField( choices = models.Class.objests.values_list('id' ,'title' ) widget = widgets.Select(attr={'class' :'' form-control}) ) ) def add_student (request ): if request.method == 'GET' : obj = StudentForm() return render(request,'add_student.html' ,{'obj' :obj}) else : obj = StudentForm(request.POST) if obj.is_valid(): models.Student.objects.create(**obj.cleaned_data) return redirect('/student_list/' ) else : return render(request,'add_student.html' ,{'obj' :obj})
改
……省略Form组件…… def edit_student (request,nid ): if request.method == 'GET' : row = models.Student.objects.filter (id =nid).values('name' ,'email' ,'age' ,'cls_id' ).first() obj = StudentForm(initial=row) return render(request,'edit_student.html' ,{'nid' :nid, 'obj' :obj}) else : obj = StudentForm(request.POST) if obj.is_valid(): models.Student.objects.filter (id =nid).update(**obj.cleaned_data) return redirect('/student_list/' ) else : return render(request,'/edit_student.html' ,{'nid' :id , 'obj' :obj})
老师管理
查
def teacher_list (request ): tea_list = models.Teacher.objects.all () return render(request,'teacher_list.html' ,{'tea_list' :tea_list})
增
class TeacherForm (Form ): tname=fields.CharField(min_length=2 ) cls_id = fields.MultipleChoiceField( ) def __init__ (self,*args,**kwargs ): super (TeacherForm,self).__init__(*args,**kwargs) self.fields['cls_id' ].widget.choices=models.Classes.objects.values_list('id' ,'title' ) def add_teacher (request ): if request == 'GET' : obj = TeacherForm() return render(request,'add_teacher.html' ,{'obj' :obj}) else : obj = TeacherForm(request.POST) if obj.is_valid(): cls_id= obj.cleaned_data.pop('cls_id' ) row = models.Teacher.objects.create(**obj.cleaned_data) row.c2t.add(*cls_id) return redirect('/teacher_list/' ) return render(request,'add_teacher.html' ,{'obj' :obj})
改
def edit_teacher (request,nid ): if request.method == "GET" : row = models.Teacher.objects.filter (id =nid).first() class_ids = row.c2t.values_list('id' ) id_list = list (zip (*class_ids))[0 ] if list (zip (*class_ids)) else [] obj = TeacherForm(initial={'tname' :row.tname,'cls_id' :id_list}) return render(request,'edit_teacher.html' ,{'obj' :obj})
Form常用组件定制
class TestForm (Form ): t1 = fields.MultipleChoiceField( choices =[(1 ,'篮球' ),(2 ,'足球' )], widget=widgets.CheckboxSelectMultiple ) t2 =fields.MultipleChoiceField( choices=[(1 ,'篮球' ),(2 ,'足球' )], widget=widgets.RadioSelect ) t3 = fields.FileField( widget=widgets.FileInput )
Form组件中的钩子(扩展自定义函数)
class TestForm (Form ): user = fields.CharField( validators=[RegexValidator(r'^[0-9]+$' , '请输入数字' ), RegexValidator(r'^159[0-9]+$' , '数字必须以159开头' )], ) email = fields.EmailField() def clean_user (self ): v = self.cleaned_data['user' ] if models.Student.object .filter (name=v).count(): raise ValuedationError('用户已存在' ) return self.cleaned_data['user' ] def clean (self ): user=self.cleaned_data.get('user' ) email=self.cleaned_data.get('email' ) if models.Stuent.objects.filter (user=user,email=email).count(): raise ValuedationError('用户名和邮箱联合已经存在' ) return self.cleaned_data
Ajax提交数据部分
views
import os def upload (request ): if request.method == 'GET' : return render(request, 'upload.html' ) else : file_obj = request.FILES.get('fafafa' ) file_path = os.path.join('static' , file_obj.name) with open (file_path, 'wb' ) as f: for chunk in file_obj.chunks(): f.write(chunk) return HttpResponse(file_path)
自定义API用作返回数据
urls
url(r'^users/' , views.users),
views
def users (request ): print('请求到来' ) callback = request.GET.get('funcname' ) user_list=[ 'leo' , 'tom' , 'jack' ] temp = '%s(%s)' %(callback, user_list) print(temp) return HttpResponse(temp)
setting配置‘
ALLOWED_HOSTS = ['www.s4.com' ]
本地PC配置
C:\Windows\System32\drivers\etc 往hosts文件中添加内容:127.0 .0 .1 www.s4.com
CORS解决跨域问题(跨来源资源共享)(响应头添加值)
第三方服务器
url(r'^new_users/' , views.new_users),
def new_users (request ): user_list = [ 'lleo' , 'tom' , 'jack' ] obj = HttpResponse(json.dumps(user_list)) obj["Access-Control-Allow-Origin" ]='http://www.s5.com:8000' return obj
复杂请求
第三方服务器
def new_users (request ): if request.method == 'OPTIONS' : obj = HttpResponse() obj["Access-Control-Allow-Origin" ] ='*' obj["Access-Control-Allow-Origin" ] ='DELETE' return obj obj = HttpResponse('adsf' ) obj["Access-Control-Allow-Origin" ] = '*' return obj