一、cbv
1 cbv(class-base-view) 基于类的视图 2 fbv(func-base-view) 基于函数的视图
a.基本演示
1 urlpatterns = [ 2 3 url(r'^login.html$', views.Login.as_view()), 4 ]
1 from django.views import View 2 3 class Login(View): 4 """ 5 get 查 6 post 创建 7 put 更新 8 delete 删除 9 """ 10 def dispatch(self, request, *args, **kwargs): 11 print('before') 12 obj = super(Login,self).dispatch(request,*args,**kwargs) 13 print("after") 14 return obj 15 16 def get(self,request): 17 return render(request,"login.html") 18 19 def post(self,request): 20 print(request.POST) 21 22 return HttpResponse("Login.post") 23 24 view.py
二、分页
a.Django分页
1 #浏览器访问 2 http://127.0.0.1:8000/index.html/?page=9
1 urlpatterns = [ 2 3 #django分页 4 url(r'^index', views.index), 5 ]
1 #django 分页 2 from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage 3 def index(request): 4 current_page = request.GET.get("page") 5 user_list = models.User_info.objects.all() 6 paginator = Paginator(user_list,10) #每页显示10条 7 8 """ 9 # count: 数据总个数 10 # num_pages:总页数 11 # page_range:总页数的索引范围,如: (1,10),(1,200) 12 # page: page对象 13 """ 14 try: 15 posts = paginator.page(current_page) #当前页 16 except PageNotAnInteger as e: #http://127.0.0.1:8000/index.html/?page=qqq 处理这种异常 17 posts = paginator.page(1) 18 except EmptyPage as e: #http://127.0.0.1:8000/index.html/?page=-10 捕获这种异常 19 posts = paginator.page(1) 20 21 22 """ 23 # has_next 是否有下一页 24 # next_page_number 下一页页码 25 # has_previous 是否有上一页 26 # previous_page_number 上一页页码 27 # object_list 分页之后的数据列表 28 # number 当前页 29 # paginator paginator对象 30 """ 31 32 return render(request,"index.html",{"posts":posts}) 33 34 views.py
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>用户列表</h1> 9 <ul> 10 {% for row in posts.object_list %} 11 <li>{{ row.name }}</li> 12 {% endfor %} 13 </ul> 14 <div> 15 {% if posts.has_previous %} 16 <a href="/index.html/?page={{ posts.previous_page_number }}">上一页</a> 17 {% endif %} 18 19 {% for num in posts.paginator.page_range %} 20 <a href="/index.html/?page={{ num }}">{{ num }}</a> 21 {% endfor %} 22 23 {% if posts.has_next %} 24 <a href="/index.html/?page={{ posts.next_page_number }}">下一页</a> 25 {% endif %} 26 </div> 27 28 </body> 29 </html> 30 31 index.html
b.自定义分页
1 #浏览器访问 2 http://127.0.0.1:8000/custom/?page=6
1 urlpatterns = [ 2 3 #自定义分页 4 url(r'^custom/', views.custom), 5 ]
1 from utils.pager import PageInfo 2 #自定义分页 3 def custom(request): 4 5 #总页数 6 all_count = models.User_info.objects.all().count() 7 8 #用户当前想要访问的页码 9 current_page = request.GET.get("page") 10 page_info = PageInfo(current_page,all_count,10,"/custom",11) 11 12 user_list = models.User_info.objects.all()[page_info.start():page_info.end()] 13 14 return render(request,"custom.html",{"user_list":user_list,"page_info":page_info}) 15 16 views.py
1 class PageInfo(object): 2 3 def __init__(self,current_page,all_count,per_page,base_url,show_page=11): 4 5 #如果传值错误进入第一页 6 try: 7 self.current_page = int(current_page) 8 except Exception as e: 9 self.current_page = 1 10 self.per_page = per_page #每页显示的个数 11 12 13 a,b = divmod(all_count,per_page) #页数 余数 14 if b: 15 a = a + 1 16 self.all_page = a #总页码 17 self.show_page = show_page 18 self.base_url = base_url 19 20 def start(self): 21 # 1 0: 10 22 # 2 10:20 23 # 3 20:30 24 return (self.current_page-1) * self.per_page 25 26 def end(self): 27 return self.current_page * self.per_page 28 29 def pager(self): 30 31 page_list = [] 32 33 half = int((self.show_page-1)/2) 34 35 if self.all_page < self.show_page: 36 begin = 1 37 stop = self.all_page + 1 38 else: 39 if self.current_page < half: 40 begin = 1 41 stop = self.show_page + 1 42 else: 43 if self.current_page + half > self.all_page: 44 begin = self.all_page - 10 +1 45 stop = self.all_page + 1 46 else: 47 begin = self.current_page - half 48 stop = self.current_page + half +1 49 50 if self.current_page <=1: 51 prev = "<li><a href='#'>上一页</a></li>" 52 else: 53 prev = "<li><a href='%s/?page=%s'>上一页</a></li>"%(self.base_url,self.current_page - 1) 54 55 page_list.append(prev) 56 57 58 59 for i in range(begin,stop): 60 if i == self.current_page: 61 temp = "<li class='active'><a href='/custom/?page=%s'>%s</a></li>"%(i,i) 62 else: 63 temp = "<li><a href='%s/?page=%s'>%s</a></li>"%(self.base_url,i,i) 64 page_list.append(temp) 65 66 67 if self.current_page >= self.all_page: 68 nex = "<li><a href='#'>下一页</a></li>" 69 else: 70 nex = "<li><a href='%s/?page=%s'>下一页</a></li>" % (self.base_url,self.current_page + 1) 71 72 page_list.append(nex) 73 74 return "".join(page_list) 75 76 utils/pager.py
1 from django.db import models 2 3 # Create your models here. 4 5 6 class User_type(models.Model): 7 uid = models.BigAutoField(primary_key=True) 8 title = models.CharField(max_length=32) 9 10 class User_info(models.Model): 11 name = models.CharField(max_length=32) 12 age = models.CharField(max_length=32) 13 ut = models.ForeignKey("User_type") 14 15 models.py
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" /> 7 </head> 8 <body> 9 10 {% for row in user_list %} 11 <li>{{ row.name }}</li> 12 {% endfor %} 13 14 15 <nav aria-label="Page navigation"> 16 <ul class="pagination"> 17 {{ page_info.pager |safe }} 18 19 </ul> 20 </nav> 21 </body> 22 </html> 23 24 custom.html
三、ORM正反向连表操作
1 #ORM正反向连表操作 2 - models 3 from django.db import models 4 5 class Foo(models.Model): 6 """ 7 第三个表 8 """ 9 caption = models.CharField(max_length=16) 10 11 12 class UserType(models.Model): 13 """ 14 用户类型 15 """ 16 title = models.CharField(max_length=32) 17 fo = models.ForeignKey('Foo') 18 19 20 class UserInfo(models.Model): 21 """ 22 用户表 23 """ 24 name = models.CharField(max_length=16) 25 age = models.IntegerField() 26 ut = models.ForeignKey('UserType') 27 28 29 - views 30 ----#跨表(正向操作)---UserInfo----含ForeignKey字段 PS: 一个用户只有一个用户类型 31 # 获取 32 # QuerySet[obj,obj,obj] 33 result = models.UserInfo.objects.all() 34 for obj in result: 35 print(obj.name,obj.age,obj.ut_id,obj.ut.title,obj.ut.fo.caption) 36 37 ----#跨表(反向操作)---UserType----不含ForeignKey字段 PS: 一个用户类型下可以有很多用户 38 39 obj = models.UserType.objects.all().first() 40 print('用户类型',obj.id,obj.title) 41 for row in obj.userinfo_set.all(): #使用的是与之关联的表名小写加_set.all()这个方法取到所有东西 42 print(row.name,row.age)
四、数据获取多个数据时(注意3种情况的不同之处<跨表查询、跨表取值>)
1 # 数据获取多个数据时(注意3种情况的不同之处<跨表查询、跨表取值>) 2 1. [obj,obj,obj,] # .all()和.filter()拿到的结果是QuerySet对象 3 models.UserInfo.objects.all() 4 models.UserInfo.objects.filter(id__gt=1) 5 result = models.UserInfo.objects.all() 6 for item in result: 7 print(item.name,item.ut.title) # 取值方式:item.name,item.ut.title 可以跨表 8 9 10 2. [{id:1,name:fd},{id:1,name:fd},{id:1,name:fd},] # .values()拿到的结果是字典 11 models.UserInfo.objects.all().values('id','name') 12 models.UserInfo.objects.filter(id__gt=1).values('id','name') 13 #无法跨表 14 result = models.UserInfo.objects.all().values('id','name') 15 for item in result: 16 print(item['id'],item['name']) # 取值方式:item['id'],item['name'] #无法跨表 17 #跨表 使用__(双下划线) 18 result = models.UserInfo.objects.all().values('id','name',"ut__title") # 这里查询时跨表使用的是ut__title 双下划线 19 for item in result: 20 print(item['id'],item['name'],item['ut__title']) # 跨表取值时也用的是双下滑线__ 21 22 23 24 3. [(1,df),(2,'df')] # .values_list()拿到的结果是元组 25 models.UserInfo.objects.all().values_list('id','name') 26 models.UserInfo.objects.filter(id__gt=1).values_list('id','name') 27 #无法跨表 28 result = models.UserInfo.objects.all().values_list('id','name') 29 for item in result: 30 print(item[0],item[1]) # 取值方式: item[0],item[1] #无法跨表 31 #跨表 使用__(双下划线) 32 result = models.UserInfo.objects.all().values_list('id','name',"ut__title") # 这里要跨表使用的是ut__title 双下划线 33 for item in result: 34 print(item[0],item[1],item[2]) # 跨表取值时用的是下标
五、CSRF(跨站请求伪造)
CSRF(Cross-site request forgery)跨站请求伪造,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS)
但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
理解:csrf_token防止从别的网站向自己网站发post请求, 客户来访问网站,网站会向客户发送随机字符串,然后客户带随机字符串发送post请求
只有带随机字符串来,网站才认,一般是post请求才要求带随机字符串,其它网站第一次来不会带随机字符串。
a. django开启csrf
MIDDLEWARE = [ 'django.middleware.csrf.CsrfViewMiddleware', ]
b.HTML中使用
{% csrf_token %} #只要写上{% csrf_token %} 会有一个隐藏的input随机字符串,在cookie也有一个随机的字符串,form表单提交数据时,一般会使用
{{ csrf_token }} #生成随机的字符串
c.django中设置防跨站请求伪造功能有分为全局和局部
#局部 from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect settings中没有设置全局中间件,为当前函数强制设置防跨站请求伪造功能。 @csrf_exempt settings中设置了全局中间件,取消当前函数防跨站请求伪造功能。
1 #fbv 2 3 @csrf_protect 4 def func(object): 5 pass 6 7 #cbv 8 9 from django.views import View 10 from django.utils.decorators import method_decorator 11 12 @method_decorator(csrf_exempt,name="dispatch") 13 class foo(View) 14 pass 15 16 fbv和cbv应用装饰器
1 #方式一 类上加装饰器: 2 3 def wrapper(func): 4 def inner(*args,**kwargs): 5 return func(*args,**kwargs) 6 return inner 7 8 @method_decorator(wrapper,name="get") 9 @method_decorator(wrapper,name="post") 10 class foo(View): 11 12 def get(self,request): 13 pass 14 15 def post(self,request): 16 pass 17 18 19 20 #方式二 类上“dispatch”加装饰器: 21 22 def wrapper(func): 23 def inner(*args,**kwargs): 24 return func(*args,**kwargs) 25 return inner 26 27 @method_decorator(wrapper,name="dispatch") 28 class foo(View): 29 30 def dispatch(self,request,*args,**kwargs): 31 return xxx 32 33 def get(self,request): 34 pass 35 36 def post(self,request): 37 pass 38 39 40 #方式三 方法上加装饰器: 41 42 def wrapper(func): 43 def inner(*args,**kwargs): 44 return func(*args,**kwargs) 45 return inner 46 47 class foo(View): 48 49 50 @method_decorator(wrapper) 51 def get(self,request): 52 pass 53 54 def post(self,request): 55 pass 56 57 cbv应用其它装饰器
d. Ajax提交数据 携带CSRF
1. 通过获取隐藏的input标签中的字符串,放置在data中发送
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form method="POST" action="/csrf1.html"> 9 {% csrf_token %} 10 <input id="user" type="text" name="user"/> 11 <a onclick="submitForm();">Ajax提交</a> 12 </form> 13 14 <script src="/static/jquery-1.12.4.js"></script> 15 <script> 16 function submitForm() { 17 var csrf = $('input[name="csrfmiddlewaretoken"]').val(); 18 var user = $("#user").val(); 19 $.ajax({ 20 url:'/csrf1.html', 21 type:'POST', 22 data:{"user":user,"csrfmiddlewaretoken":csrf}, 23 success:function (arg) { 24 console.log(arg); 25 } 26 27 }) 28 } 29 </script> 30 31 32 33 </body> 34 </html> 35 36 csrf1.html
1 urlpatterns = [ 2 3 url(r'^csrf1.html', views.csrf1), 4 ]
1 def csrf1(request): 2 3 if request.method == 'GET': 4 return render(request,'csrf1.html') 5 else: 6 return HttpResponse('ok')
2. 通过获取返回的cookie中的字符串,放置在请求头中发送
通过在console中 document.cookie可以获取 csrftoken=JPv1gIdrBiAlK2RCrgFs0OKwsncPXvwPfMhEWIVzMdMFymIayiuGu2GkBAu57moL 但需要切割字符串,通过引入jquery.cookie.js对cookie操作,使用$.cookie("csrftoken")
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form method="POST" action="/csrf1.html"> 9 {% csrf_token %} 10 <input id="user" type="text" name="user"/> 11 <a onclick="submitForm();">Ajax提交</a> 12 </form> 13 14 <script src="/static/jquery-1.12.4.js"></script> 15 <script src="/static/jquery.cookie.js"></script> 16 <script> 17 function submitForm() { 18 var token = $.cookie("csrftoken"); 19 var user = $("#user").val(); 20 $.ajax({ 21 url:'/csrf1.html', 22 type:'POST', 23 headers:{"X-CSRFToken":token}, 24 data:{"user":user}, 25 success:function (arg) { 26 console.log(arg); 27 } 28 29 }) 30 } 31 </script> 32 33 34 35 36 37 </body> 38 </html> 39 40 csrf1.html
六、Django框架最最最最基础的3+5基本使用步骤 。◕‿◕。
1 1,创建项目文件夹 2 在终端Terminal执行命令: 3 django-admin startproject 项目名 4 5 6 2,配置3个地方 7 (1)模板路径配置 8 TEMPLATES = [ 9 { 10 'BACKEND': 'django.template.backends.django.DjangoTemplates', 11 'DIRS': [os.path.join(BASE_DIR,'templates')], # 这一步 12 'APP_DIRS': True, 13 'OPTIONS': { 14 'context_processors': [ 15 'django.template.context_processors.debug', 16 'django.template.context_processors.request', 17 'django.contrib.auth.context_processors.auth', 18 'django.contrib.messages.context_processors.messages', 19 ], 20 }, 21 }, 22 ] 23 (2) 静态文件配置 24 STATIC_URL = '/static/' 25 STATICFILES_DIRS = ( 26 os.path.join(BASE_DIR,'static'), 27 ) 28 29 (3) # 'django.middleware.csrf.CsrfViewMiddleware', 注释这一行 30 31 32 33 3,Django框架5步 34 在终端Terminal执行命令创建app模块: 35 python manage.py startapp 模块名 36 37 38 (1)连接数据库 39 DATABASES = { 40 'default': { 41 'ENGINE': 'django.db.backends.mysql', 42 'NAME': "studentPro", 43 'USER':'yangzai', 44 'PASSWORD':'Oldsyang=5201314@yangzai', 45 'HOST':'mypy.me', 46 'PORT':3306, 47 } 48 } 49 50 (2)导入pymysql 51 在__init__中写入 52 import pymysql 53 pymysql.install_as_MySQLdb() 54 55 (3)创建model 56 from django.db import models 57 class UserInfo(models.Model): 58 id = 59 name = 60 password = 61 62 (4)注册模块 63 INSTALLED_APPS = [ 64 'django.contrib.admin', 65 'django.contrib.auth', 66 'django.contrib.contenttypes', 67 'django.contrib.sessions', 68 'django.contrib.messages', 69 'django.contrib.staticfiles', 70 'app01' -----这一步 71 ] 72 73 74 (5)初始化数据库 75 python manage.py makemigrations --先执行 76 python manage.py migrate --后执行 77 78 79 基本使用步骤
七、Django框架里面return的3种返回
return render() - 返回页面 - return render(request,'index.html',{'std_list':std_list}) 3个参数含义: request:用户的请求信息 'index.html':需要返回的模板html页面 {'std_list':std_list}:存放模板文件里面要被替换的占位符所对应的值 return HttpResponse() - 返回字符串 - return HttpResponse(json.dumps(ret)) return redirect() - 返回url请求 - return redirect('/teachers/') 提示点:redirect,href,action,这3中url请求,都要在地址前加/斜杠 例子:return redirect('/classes.html') <a href="/edit_class/{{ row.id }}.html"> <form method="POST" action="/edit_class/{{ id }}.html"> return的3中返回
八、cookie
a. 简单应用
1 def login(request): 2 if request.method=="GET": 3 return render(request,"login.html") 4 else: 5 name = request.POST.get("name") 6 password = request.POST.get("password") 7 if name == "alex" and password == "123": 8 obj = redirect("/classes/") 9 obj.set_cookie("ticket","123456",max_age=10) 10 return obj 11 else: 12 return redirect("/login/") 13 14 15 16 def classes(request): 17 sk = request.COOKIES 18 print(sk) 19 if not sk: 20 return redirect("/login/")
b. 过期时间的两种格式
1 方式一: 2 obj.set_cookie("ticket","123456",max_age=10) 3 4 方式二: 5 import datetime 6 from datetime import timedelta #时间的加减 7 ct = datetime.datetime.utcnow() #获取当前日期 8 v= timedelta(seconds=10) #10秒 9 value = ct + v 10 11 obj.set_cookie("ticket","123456",expires=value)
c. 限制路径
1 obj.set_cookie("ticket","123456",max_age=10,path="/") #所有路径都可以访问 2 3 obj.set_cookie("ticket","123456",max_age=10,path="/class") #只有class访问
d. cookie签名
1 #加 2 obj.set_signed_cookie("ticket","123456",salt="abc") 3 4 #解 5 sk = request.get_signed_cookie("ticket",salt="abc")
九、session
1 流程:客户登录网址,验证成功后,服务端生成一个随机字符串和随机字符串对应的键值,然后把随机字符串通过cookie发送给客户端 2 客户端拿着随机字符串通过cookir再次登陆,服务端拿着随机字符串和保存在本地的数据对应,以确定用户的登录状态
Cookie是什么? 保存在客户端浏览器上的键值对 Session是什么? 保存在服务端的数据(本质是键值对) { “aaaaa":{'id':1,'name':'于浩',email='xxxx'} "bbbbb":{'id':2,'name':'陈涛',email='0000'} } 应用:依赖cookie 作用:保持会话(Web网站) 好处:敏感信息不会直接给客户端 梳理: 1. 保存在服务端的数据(本质是键值对) 2. 配置文件中: - 存储位置 - 超时时间、每次刷新更新时间
a. 简单示例
用户访问http://127.0.0.1:8000/login/
urlpatterns = [ url(r'^index/', views.index), url(r'^login/', views.login), ]
1 def login(request): 2 if request.method == 'GET': 3 return render(request,'login.html') 4 else: 5 u = request.POST.get('user') 6 p = request.POST.get('pwd') 7 obj = models.UserAdmin.objects.filter(username=u,password=p).first() 8 if obj: 9 # 1. 生成随机字符串 10 # 2. 通过cookie发送给客户端 11 # 3. 服务端保存 12 # { 13 # 随机字符串1: {'username':'alex','email':x''...} 14 # } 15 request.session['username'] = obj.username 16 return redirect('/index/') 17 else: 18 return render(request,'login.html',{'msg':'用户名或密码错误'}) 19 20 21 def index(request): 22 # 1. 获取客户端端cookie中的随机字符串 23 # 2. 去session中查找有没有随机字符 24 # 3. 去session对应key的value中查看是否有 username 25 v = request.session.get('username') 26 if v: 27 return HttpResponse('登录成功:%s' %v) 28 else: 29 return redirect('/login/') 30 31 views.py
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 <form action="/login/" method="POST"> 10 <input type="text" name="user"> 11 <input type="text" name="pwd"> 12 <input type="submit" value="提交">{{ msg }} 13 </form> 14 15 16 </body> 17 </html> 18 19 login.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 <h1>index page</h1> 10 11 </body> 12 </html> 13 14 index.html
自己的基于session登陆代码:
1 def login(request): 2 if request.method == "GET": 3 return render(request, "login.html") 4 else: 5 input_code = request.POST.get('code') 6 session_code = request.session.get('code') 7 username=request.POST.get("user") 8 password=request.POST.get("pwd") 9 if input_code.upper() == session_code.upper(): 10 # obj = models.UserInfo.objects.filter(username=username,password=password).first() 11 obj = models.UserInfo.objects.filter(username=username,password=password).values("nid","avatar", 12 "nickname", 13 "blog__title", 14 "blog__site").first() 15 print("obj:",obj) 16 17 # print("obj.nid:",obj.nid) 18 if obj: 19 # nid=obj.nid 20 # request.session["userinfo"]={"id":nid} 21 request.session["userinfo"]={"id":obj.get("nid"),"avatar":obj.get("avatar"), 22 "blogname":obj.get("blog__title"), 23 "nickname":obj.get("nickname"),"site":obj.get("blog__site")} 24 # print('.................',request.session['userinfo']) 25 return redirect("/home_page/home_page.html/") 26 else: 27 return render(request, 'login.html', {"msg": "用户名或者密码不对"}) 28 else: 29 return render(request, 'login.html', {"msg": "验证码错误"}) 30 31 32 33 # 退出登陆 34 def logout(request): 35 request.session.clear() # 清除session 36 return redirect('/home_page/home_page.html/')
十、URL(路由配置系统)
1 URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码<br>对于那个URL调用那段代码 2 3 urlpatterns = [ 4 url(正则表达式, views视图函数,参数,别名), 5 ] 6 7 参数说明: 8 9 一个正则表达式字符串 10 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串 11 可选的要传递给视图函数的默认参数(字典形式) 12 一个可选的name参数
1. 单一路由对应
1 url(r'^index$', views.index)
2. 基于正则的路由
1 # $ 2 url(r'^index/(d{4})$',views.index) 3 4 #无命名分组 5 url(r'^index/(d{4})/(d{2})',views.index) 6 7 #有命名分组 8 url(r'^index/(?P<year>d{4})/(?P<month>d{2})',views.index)
1 ############################无命名 2 3 #-----------------() 相当于传参数 4 5 url(r'^index/(d{4})',views.index) 6 7 def index(request,arg): 8 return HttpResponse(arg) 9 10 #url访问http://127.0.0.1:8000/index/1113 11 12 #-----------------() 接受两个参数 13 14 url(r'^index/(d{4})/(d{2})',views.index) 15 16 def index(request,arg,arg1): 17 return HttpResponse("year: %s month: %s"%(arg,arg1)) 18 19 #url访问http://127.0.0.1:8000/index/2017/06 20 year: 2017 month: 06 21 22 23 24 ############################有命名 25 url(r'^index/(?P<year>d{4})/(?P<month>d{2})',views.index) 26 27 def index(request,year,month): 28 return HttpResponse("year: %s month: %s"%(year,month)) 29 30 #url访问http://127.0.0.1:8000/index/2017/06 31 year: 2017 month: 06 32 33 有无命名分组 演示
3. 为路由映射设置名称
1 #应用一: 2 url(r'^index',views.index,name="arg") 3 4 {{ url "arg" }} 匹配index 5 {{ url "arg" i}} 6 7 #应用二: 8 reverse反向获取url
1 ##############根据url反生成名字 2 from django.shortcuts import reverse 3 4 url(r'^index',views.index,name="arg") 5 6 def index(request): 7 v = reverse("arg") 8 print(v) 9 return HttpResponse() 10 11 #用户访问http://127.0.0.1:8000/index 12 /index 13 14 15 ##############根据url改变url 16 17 url(r'^index/(d+)/',views.index,name="n1") 18 19 def index(request,xx): 20 21 v = reverse('n1',args=(1,)) 22 print(v) 23 return HttpResponse("...") 24 25 #访问http://127.0.0.1:8000/index/222/ 26 /index/1/ 27 28 reverse示例 演示
4. 路由分发
1 url(r'^app01/',include("app01.urls")) 2 url(r'^app02/',include("app02.urls")) 3 4 #没有匹配成功,返回默认页面 5 url(r'^',include("views.default"))
十一、Model
a. 创建表
1 from django.db import models 2 3 4 class User_type(models.Model): 5 uid = models.BigAutoField(primary_key=True) 6 title = models.CharField(max_length=32) 7 8 class User_info(models.Model): 9 name = models.CharField(max_length=32) 10 age = models.CharField(max_length=32) 11 ut = models.ForeignKey("User_type") 12 13 14 python3 manage.py makemigrations 15 16 python3 manage.py migrate 17 18 19 ---------------------其它--------------------- 20 21 class part(models.Model): 22 cid = models.BigAutoField(primary_key=True) 23 title = models.CharField(max_length=32,null=False) 24 25 26 class student(models.Model): 27 sid = models.BigAutoField(primary_key=True) 28 name = models.CharField(max_length=32,null=False) 29 pub_data=models.DateField() 30 age = models.IntegerField(default=18) 31 # 新增加的列 如果原先表里有值,写default 32 ug = models.ForeignKey("part",null=True) #如果新增加外键,加null=True
b. ORM操作
1 #增 2 # models.User_type.objects.create(title="黑金用户") 3 4 # obj = models.User_type(title="小白用户") 5 # obj.save() 6 7 8 #删 9 #models.User_type.objects.filter(title="小白用户").delete() # 删除指定条件的数据 10 11 #改 12 #models.User_type.objects.filter(title="黑金用户").update(title="黑卡用户") # 修改指定条件的数据 13 14 #查 15 # models.User_type.objects.get(title="大白用户") # 获取单条数据,不存在则报错(不建议) 16 # models.User_type.objects.all() # 获取全部 17 # models.User_type.objects.filter(title="小白用户") # 获取指定条件的数据 18 # models.User_type.objects.exclude(title="黄金用户") # 排除指定条件的数据 19 20 基本增删改查
1 # 获取个数 2 3 models.User_info.objects.filter(age=18).count() 4 5 6 # 大于 小于 7 8 # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 9 # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值 10 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 11 # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值 12 # models.Tb1.objects.filter(id__gt=1,id__lt=10) # 获取id大于1 且 小于10的值 13 14 15 16 #in 17 18 models.User_info.objects.filter(age__in=[19]) # in 19 models.User_info.objects.exclude(age__in=[19]) # not in 20 21 22 # isnull 23 24 models.User_info.objects.filter(age__isnull=True) # age列为不为空 25 models.User_info.objects.filter(age__isnull=False) # age列是不是 不为空 26 27 28 # contains 29 30 # models.Tb1.objects.filter(name__contains="ven") 31 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 32 # models.Tb1.objects.exclude(name__icontains="ven") 33 34 35 36 # range 37 38 # models.Tb1.objects.filter(id__range=[1, 5]) # 范围bettwen and 39 40 41 #开始 结束 42 43 # startswith,istartswith, endswith, iendswith 44 45 46 47 #order_by 48 49 #models.User_info.objects.all().order_by("id") # asc 50 #models.User_info.objects.all().order_by("-id") # desc 51 52 # models.Tb1.objects.filter(name='seven').order_by('id') # asc 53 # models.Tb1.objects.filter(name='seven').order_by('-id') # desc 54 55 56 57 #group by #后面出现filter代表having 58 59 from django.db.models import Count 60 #models.User_info.objects.values("name","age").annotate() #没有起作用 61 #SELECT "app01_user_info"."name", "app01_user_info"."age" FROM "app01_user_info" 62 63 #models.User_info.objects.values("age").annotate(xxx=Count("age")) 64 #SELECT "app01_user_info"."age", COUNT("app01_user_info"."age") AS "xxx" FROM "app01_user_info" GROUP BY "app01_user_info"."age" 65 66 #models.User_info.objects.values("age").annotate(xxx=Count("age")).filter(xxx__gt=2) #年龄相同次数大于2的查出来 67 #SELECT "app01_user_info"."age", COUNT("app01_user_info"."age") AS "xxx" FROM "app01_user_info" GROUP BY "app01_user_info"."age" HAVING COUNT("app01_user_info"."age") > 2 68 69 70 #注意两次filter 第一次代表where 第二次代表having 71 72 #models.User_info.objects.filter(id__gt=2).values("age").annotate(xxx=Count("age")).filter(xxx__gt=2) 73 #SELECT "app01_user_info"."age", COUNT("app01_user_info"."age") AS "xxx" FROM "app01_user_info" WHERE "app01_user_info"."id" > 2 GROUP BY "app01_user_info"."age" HAVING COUNT("app01_user_info"."age") > 2 74 75 常用方法
1 # F 2 3 # from django.db.models import F 4 # models.User_info.objects.all().update(age=F("age")+5) # age列加5 5 6 7 # Q 8 9 # 方式一: 10 # Q(nid__gt=10) 11 # Q(nid=8) | Q(nid__gt=10) 12 # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 13 14 15 #-------------------------------以下三种查找方式相同效果 16 17 # obj = models.User_info.objects.filter(id=307,name="egon") 18 19 # condition ={ 20 # 'id':307, 21 # 'name':'egon', 22 # } 23 # obj = models.User_info.objects.filter(**condition) 24 25 #obj = models.User_info.objects.filter(Q(id=307) & Q(name="egon")) 26 --------------------------------- 27 28 29 # 方式二: 30 31 32 # q1 = Q() 33 # q1.connector = 'OR' 34 # q1.children.append(('id', 1)) 35 # q1.children.append(('id', 10)) 36 # q1.children.append(('id', 9)) 37 38 # q2 = Q() 39 # q2.connector = 'OR' 40 # q2.children.append(('c1', 1)) 41 # q2.children.append(('c1', 10)) 42 # q2.children.append(('c1', 9)) 43 44 # q3 = Q() 45 # q3.connector = 'AND' 46 # q3.children.append(('id', 1)) 47 # q3.children.append(('id', 2)) 48 # q1.add(q3, 'OR') 49 50 # con = Q() 51 # con.add(q1, 'AND') 52 # con.add(q2, 'AND') 53 54 #(id=1 or id=10 or id=9 or (id=1 and id=2)) and (c1=1 or c1=10 or c1=9) #等于上面 55 56 # models.Tb1.objects.filter(con) 57 58 59 # Q演示 60 condition_dict = { 61 'k1':[1,2,3,4], 62 'k2':[1,], 63 'k3':[11,] 64 } 65 66 con = Q() 67 for k,v in condition_dict.items(): 68 q = Q() 69 q.connector = 'OR' 70 for i in v: 71 q.children.append(('id',1)) 72 con.add(q,'AND') 73 74 models.User_info.objects.filter(con) 75 76 F Q 演示
c. 多对多操作
方式一:通过外键创建第三张表
1 class Boy(models.Model): 2 name = models.CharField(max_length=32) 3 4 class Girl(models.Model): 5 nick = models.CharField(max_length=32) 6 7 class Love(models.Model): 8 b = models.ForeignKey("Boy") 9 g = models.ForeignKey("Girl") 10 11 class Meta: 12 unique_together = [ 13 ("b","g"), 14 ]
1 #表里插入数据 2 3 objs = [ 4 models.Boy(name='方少伟'), 5 models.Boy(name='游勤斌'), 6 models.Boy(name='于浩'), 7 models.Boy(name='陈涛'), 8 ] 9 models.Boy.objects.bulk_create(objs,4) 10 11 result = [ 12 models.Girl(nick='于浩姐姐'), 13 models.Girl(nick='景甜'), 14 models.Girl(nick='刘亦非'), 15 models.Girl(nick='苍老师'), 16 ] 17 models.Girl.objects.bulk_create(result, 4) 18 19 models.Love.objects.create(b_id=1,g_id=1) 20 models.Love.objects.create(b_id=1,g_id=2) 21 models.Love.objects.create(b_id=1,g_id=3) 22 models.Love.objects.create(b_id=2,g_id=4) 23 24 25 ################### 查找和我有关系的女孩 四种方式 ################ 26 27 28 obj = models.Boy.objects.filter(name="方少伟").first() 29 love_list = obj.love_set.all() 30 for row in love_list: 31 print(row.g.nick) 32 33 love_list = models.Love.objects.filter(b__name="方少伟") 34 for row in love_list: 35 print(row.g.nick) 36 37 38 #下面两个效果好 39 40 love_list = models.Love.objects.filter(b__name="方少伟").values("g__nick") 41 for item in love_list: 42 print(item["g__nick"]) 43 44 45 46 love_list = models.Love.objects.filter(b__name="方少伟").select_related("g") 47 for obj in love_list: 48 print(obj.g.nick) 49 50 SQL演示
方式二:通过 ManyToManyField 创建第三张表
1 class Boy(models.Model): 2 name = models.CharField(max_length=32) 3 m = models.ManyToManyField("Girl") 4 5 class Girl(models.Model): 6 nick = models.CharField(max_length=32)
1 obj = models.Boy.objects.filter(name="方少伟").first() 2 # print(obj.id,obj.name) 3 4 # obj.m.add(2) 5 # obj.m.add(1,3) 6 # obj.m.add(*[4,]) 7 8 # obj.m.remove(2) 9 # obj.m.remove(1,3) 10 # obj.m.remove(*[4,]) 11 12 # obj.m.set([1,4,]) 13 14 15 # girl_list = obj.m.all() 16 # girl_list = obj.m.filter(nick="苍老师") 17 18 19 # obj.m.clear() 20 21 obj = models.Girl.objects.filter(nick="苍老师").first() 22 v = obj.boy_set.all() 23 24 SQL 演示
方式三:通过 外键 和 ManyToManyField 创建
1 class Boy(models.Model): 2 name = models.CharField(max_length=32) 3 m = models.ManyToManyField("Girl",through="Love",through_fields=("b","g",)) 4 5 class Girl(models.Model): 6 nick = models.CharField(max_length=32) 7 8 class Love(models.Model): 9 b = models.ForeignKey("Boy") 10 g = models.ForeignKey("Girl") 11 12 class Meta: 13 unique_together = [ 14 ("b","g"), 15 ]
1 obj = models.Boy.objects.filter(name="方少伟").first() 2 3 #只可以查或清空 4 obj.m.clear() 5 6 obj.m.all() 7 8 SQL 操作
d. 一对多
1 正向: 2 filter() values,values_list() -> 跨表 fk__xxx 3 objs = all() 4 for obj in objs: 5 obj.fk. 6 反向: 7 filter() values,values_list() -> 跨表 表名称__xxx 8 objs = all() 9 for obj in objs: 10 obj.表名称_set.all()
1.连表操作演示
1 urlpatterns = [ 2 3 url(r'^test/', views.test), 4 5 ]
1 class User_type(models.Model): 2 uid = models.BigAutoField(primary_key=True) 3 title = models.CharField(max_length=32) 4 5 class User_info(models.Model): 6 name = models.CharField(max_length=32) 7 age = models.CharField(max_length=32) 8 ut = models.ForeignKey("User_type") 9 10 models.py
1 def test(request): 2 models.User_type.objects.create(title="普通用户") 3 models.User_type.objects.create(title="白金用户") 4 models.User_type.objects.create(title="黄金用户") 5 6 7 models.User_info.objects.create(name="小鸡",age=18,ut_id=1) 8 models.User_info.objects.create(name="小狗",age=18,ut_id=2) 9 models.User_info.objects.create(name="小猫",age=18,ut_id=2) 10 models.User_info.objects.create(name="小雨",age=18,ut_id=3) 11 models.User_info.objects.create(name="大雨",age=18,ut_id=1) 12 13 for i in range(300): 14 name = "root" + str(i) 15 models.User_info.objects.create(name=name, age=18, ut_id=1) 16 17 #正向操作 18 obj = models.User_info.objects.all().first() 19 print(obj.name,obj.age,obj.ut.title) 20 21 #反向操作 obj.表名小写_set.all() 22 obj = models.User_type.objects.all().first() 23 for row in obj.user_info_set.all(): 24 print(row.name,row.age) 25 26 result = models.User_type.objects.all() 27 for item in result: 28 print(item.title,item.user_info_set.all()) 29 print(item.user_info_set.filter(name="小雨")) 30 31 32 #字典格式 33 result = models.User_info.objects.all().values("id","name") 34 for row in result: 35 print(row) 36 37 #字典格式查的时候跨表 38 result = models.User_info.objects.all().values("id","name","ut__title") 39 for row in result: 40 print(row["id"],row["name"],row["ut__title"]) 41 42 43 44 45 46 # 元组格式 47 # result = models.User_info.objects.all().values_list("id","name") 48 # for row in result: 49 # print(row) 50 51 return HttpResponse(".....") 52 53 views.py
十二、ORM操作
1 操作数据行:---------(在views中操作) 2 增 3 models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs 4 obj = models.Tb1(c1='xx', c2='oo') 5 obj.save() 6 7 删 8 models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 9 10 改 11 models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs 12 obj = models.Tb1.objects.get(id=1) 13 obj.c1 = '111' 14 obj.save() # 修改单条数据 15 16 查 17 models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) 18 models.Tb1.objects.all() # 获取全部 19 models.Tb1.objects.filter(name='seven') # 获取指定条件的数据
1 # 获取个数 2 # 3 # models.Tb1.objects.filter(name='seven').count() 4 5 # 大于,小于 6 # 7 # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 8 # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值 9 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 10 # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值 11 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 12 13 # in 14 # 15 # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 16 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 17 18 # isnull 19 # Entry.objects.filter(pub_date__isnull=True) 20 21 # contains 22 # 23 # models.Tb1.objects.filter(name__contains="ven") 24 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 25 # models.Tb1.objects.exclude(name__icontains="ven") 26 27 # range 28 # 29 # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and 30 31 # 其他类似 32 # 33 # startswith,istartswith, endswith, iendswith, 34 35 # order by 36 # 37 # models.Tb1.objects.filter(name='seven').order_by('id') # asc 38 # models.Tb1.objects.filter(name='seven').order_by('-id') # desc 39 40 # group by 41 # 42 # from django.db.models import Count, Min, Max, Sum 43 # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) 44 # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" 45 46 # limit 、offset 47 # 48 # models.Tb1.objects.all()[10:20] 49 50 # regex正则匹配,iregex 不区分大小写 51 # 52 # Entry.objects.get(title__regex=r'^(An?|The) +') 53 # Entry.objects.get(title__iregex=r'^(an?|the) +') 54 55 # date 56 # 57 # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) 58 # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) 59 60 # year 61 # 62 # Entry.objects.filter(pub_date__year=2005) 63 # Entry.objects.filter(pub_date__year__gte=2005) 64 65 # month 66 # 67 # Entry.objects.filter(pub_date__month=12) 68 # Entry.objects.filter(pub_date__month__gte=6) 69 70 # day 71 # 72 # Entry.objects.filter(pub_date__day=3) 73 # Entry.objects.filter(pub_date__day__gte=3) 74 75 # week_day 76 # 77 # Entry.objects.filter(pub_date__week_day=2) 78 # Entry.objects.filter(pub_date__week_day__gte=2) 79 80 # hour 81 # 82 # Event.objects.filter(timestamp__hour=23) 83 # Event.objects.filter(time__hour=5) 84 # Event.objects.filter(timestamp__hour__gte=12) 85 86 # minute 87 # 88 # Event.objects.filter(timestamp__minute=29) 89 # Event.objects.filter(time__minute=46) 90 # Event.objects.filter(timestamp__minute__gte=29) 91 92 # second 93 # 94 # Event.objects.filter(timestamp__second=31) 95 # Event.objects.filter(time__second=2) 96 # Event.objects.filter(timestamp__second__gte=31)
1 # extra #额外查询条件以及相关表,排序 2 # 3 # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) 4 # a. 映射 5 # select 6 # select_params=None 7 # select 此处 from 表 8 9 # b. 条件 10 # where=None 11 # params=None, 12 # select * from 表 where 此处 13 14 # c. 表 15 # tables 16 # select * from 表,此处 17 18 # c. 排序 19 # order_by=None 20 # select * from 表 order by 此处 21 22 # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) 23 # Entry.objects.extra(where=['headline=%s'], params=['Lennon']) 24 # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) 25 # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 26 27 # F #更新时用于获取原来的值 28 29 from django.db.models import F 30 models.Tb1.objects.update(num=F('num')+1) 31 32 33 # Q #用于构造复杂查询条件 34 35 # 应用一: 36 models.UserInfo.objects.filter(Q(id__gt=1)) 37 models.UserInfo.objects.filter(Q(id=8) | Q(id=2)) 38 models.UserInfo.objects.filter(Q(id=8) & Q(id=2)) 39 40 # 应用二: 41 # con = Q() 42 # q1 = Q() 43 # q1.connector = 'OR' 44 # q1.children.append(('id', 1)) 45 # q1.children.append(('id', 10)) 46 # q1.children.append(('id', 9)) 47 # q2 = Q() 48 # q2.connector = 'OR' 49 # q2.children.append(('c1', 1)) 50 # q2.children.append(('c1', 10)) 51 # q2.children.append(('c1', 9)) 52 # con.add(q1, 'AND') 53 # con.add(q2, 'AND') 54 # 55 # models.Tb1.objects.filter(con) 56 57 58 # 执行原生SQL 59 # 60 # from django.db import connection, connections 61 # cursor = connection.cursor() # cursor = connections['default'].cursor() 62 # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) 63 # row = cursor.fetchone()
1 ################################################################## 2 # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET # 3 ################################################################## 4 5 def all(self) 6 # 获取所有的数据对象 7 8 def filter(self, *args, **kwargs) 9 # 条件查询 10 # 条件可以是:参数,字典,Q 11 12 def exclude(self, *args, **kwargs) 13 # 条件查询 14 # 条件可以是:参数,字典,Q 15 16 def select_related(self, *fields) 17 性能相关:表之间进行join连表操作,一次性获取关联的数据。 18 model.tb.objects.all().select_related() 19 model.tb.objects.all().select_related('外键字段') 20 model.tb.objects.all().select_related('外键字段__外键字段') 21 22 def prefetch_related(self, *lookups) 23 性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。 24 # 获取所有用户表 25 # 获取用户类型表where id in (用户表中的查到的所有用户ID) 26 models.UserInfo.objects.prefetch_related('外键字段') 27 28 29 30 from django.db.models import Count, Case, When, IntegerField 31 Article.objects.annotate( 32 numviews=Count(Case( 33 When(readership__what_time__lt=treshold, then=1), 34 output_field=CharField(), 35 )) 36 ) 37 38 students = Student.objects.all().annotate(num_excused_absences=models.Sum( 39 models.Case( 40 models.When(absence__type='Excused', then=1), 41 default=0, 42 output_field=models.IntegerField() 43 ))) 44 45 def annotate(self, *args, **kwargs) 46 # 用于实现聚合group by查询 47 48 from django.db.models import Count, Avg, Max, Min, Sum 49 50 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')) 51 # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id 52 53 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1) 54 # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 55 56 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1) 57 # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 58 59 def distinct(self, *field_names) 60 # 用于distinct去重 61 models.UserInfo.objects.values('nid').distinct() 62 # select distinct nid from userinfo 63 64 注:只有在PostgreSQL中才能使用distinct进行去重 65 66 def order_by(self, *field_names) 67 # 用于排序 68 models.UserInfo.objects.all().order_by('-id','age') 69 70 def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) 71 # 构造额外的查询条件或者映射,如:子查询 72 73 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) 74 Entry.objects.extra(where=['headline=%s'], params=['Lennon']) 75 Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) 76 Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 77 78 def reverse(self): 79 # 倒序 80 models.UserInfo.objects.all().order_by('-nid').reverse() 81 # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序 82 83 84 def defer(self, *fields): 85 models.UserInfo.objects.defer('username','id') 86 或 87 models.UserInfo.objects.filter(...).defer('username','id') 88 #映射中排除某列数据 89 90 def only(self, *fields): 91 #仅取某个表中的数据 92 models.UserInfo.objects.only('username','id') 93 或 94 models.UserInfo.objects.filter(...).only('username','id') 95 96 def using(self, alias): 97 指定使用的数据库,参数为别名(setting中的设置) 98 99 100 ################################################## 101 # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # 102 ################################################## 103 104 def raw(self, raw_query, params=None, translations=None, using=None): 105 # 执行原生SQL 106 models.UserInfo.objects.raw('select * from userinfo') 107 108 # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名 109 models.UserInfo.objects.raw('select id as nid from 其他表') 110 111 # 为原生SQL设置参数 112 models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) 113 114 # 将获取的到列名转换为指定列名 115 name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} 116 Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) 117 118 # 指定数据库 119 models.UserInfo.objects.raw('select * from userinfo', using="default") 120 121 ################### 原生SQL ################### 122 from django.db import connection, connections 123 cursor = connection.cursor() # cursor = connections['default'].cursor() 124 cursor.execute("""SELECT * from auth_user where id = %s""", [1]) 125 row = cursor.fetchone() # fetchall()/fetchmany(..) 126 127 128 def values(self, *fields): 129 # 获取每行数据为字典格式 130 131 def values_list(self, *fields, **kwargs): 132 # 获取每行数据为元祖 133 134 def dates(self, field_name, kind, order='ASC'): 135 # 根据时间进行某一部分进行去重查找并截取指定内容 136 # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日) 137 # order只能是:"ASC" "DESC" 138 # 并获取转换后的时间 139 - year : 年-01-01 140 - month: 年-月-01 141 - day : 年-月-日 142 143 models.DatePlus.objects.dates('ctime','day','DESC') 144 145 def datetimes(self, field_name, kind, order='ASC', tzinfo=None): 146 # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间 147 # kind只能是 "year", "month", "day", "hour", "minute", "second" 148 # order只能是:"ASC" "DESC" 149 # tzinfo时区对象 150 models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC) 151 models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) 152 153 """ 154 pip3 install pytz 155 import pytz 156 pytz.all_timezones 157 pytz.timezone(‘Asia/Shanghai’) 158 """ 159 160 def none(self): 161 # 空QuerySet对象 162 163 164 #################################### 165 # METHODS THAT DO DATABASE QUERIES # 166 #################################### 167 168 def aggregate(self, *args, **kwargs): 169 # 聚合函数,获取字典类型聚合结果 170 from django.db.models import Count, Avg, Max, Min, Sum 171 result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid')) 172 ===> {'k': 3, 'n': 4} 173 174 def count(self): 175 # 获取个数 176 177 def get(self, *args, **kwargs): 178 # 获取单个对象 179 180 def create(self, **kwargs): 181 # 创建对象 182 183 def bulk_create(self, objs, batch_size=None): 184 # 批量插入 185 # batch_size表示一次插入的个数 186 objs = [ 187 models.DDD(name='r11'), 188 models.DDD(name='r22') 189 ] 190 models.DDD.objects.bulk_create(objs, 10) 191 192 def get_or_create(self, defaults=None, **kwargs): 193 # 如果存在,则获取,否则,创建 194 # defaults 指定创建时,其他字段的值 195 obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2}) 196 197 def update_or_create(self, defaults=None, **kwargs): 198 # 如果存在,则更新,否则,创建 199 # defaults 指定创建时或更新时的其他字段 200 obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1}) 201 202 def first(self): 203 # 获取第一个 204 205 def last(self): 206 # 获取最后一个 207 208 def in_bulk(self, id_list=None): 209 # 根据主键ID进行查找 210 id_list = [11,21,31] 211 models.DDD.objects.in_bulk(id_list) 212 213 def delete(self): 214 # 删除 215 216 def update(self, **kwargs): 217 # 更新 218 219 def exists(self): 220 # 是否有结果 221 222 其他操作
十三、多表关系以及参数
1 ForeignKey(ForeignObject) # ForeignObject(RelatedField) 2 to, # 要进行关联的表名 3 to_field=None, # 要关联的表中的字段名称 4 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 5 - models.CASCADE,删除关联数据,与之关联也删除 6 - models.DO_NOTHING,删除关联数据,引发错误IntegrityError 7 - models.PROTECT,删除关联数据,引发错误ProtectedError 8 - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空) 9 - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值) 10 - models.SET,删除关联数据, 11 a. 与之关联的值设置为指定值,设置:models.SET(值) 12 b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象) 13 14 def func(): 15 return 10 16 17 class MyModel(models.Model): 18 user = models.ForeignKey( 19 to="User", 20 to_field="id" 21 on_delete=models.SET(func),) 22 related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() 23 related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 24 limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: 25 # 如: 26 - limit_choices_to={'nid__gt': 5} 27 - limit_choices_to=lambda : {'nid__gt': 5} 28 29 from django.db.models import Q 30 - limit_choices_to=Q(nid__gt=10) 31 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 32 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 33 db_constraint=True # 是否在数据库中创建外键约束 34 parent_link=False # 在Admin中是否显示关联数据 35 36 37 OneToOneField(ForeignKey) 38 to, # 要进行关联的表名 39 to_field=None # 要关联的表中的字段名称 40 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 41 42 ###### 对于一对一 ###### 43 # 1. 一对一其实就是 一对多 + 唯一索引 44 # 2.当两个类之间有继承关系时,默认会创建一个一对一字段 45 # 如下会在A表中额外增加一个c_ptr_id列且唯一: 46 class C(models.Model): 47 nid = models.AutoField(primary_key=True) 48 part = models.CharField(max_length=12) 49 50 class A(C): 51 id = models.AutoField(primary_key=True) 52 code = models.CharField(max_length=1) 53 54 ManyToManyField(RelatedField) 55 to, # 要进行关联的表名 56 related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() 57 related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 58 limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: 59 # 如: 60 - limit_choices_to={'nid__gt': 5} 61 - limit_choices_to=lambda : {'nid__gt': 5} 62 63 from django.db.models import Q 64 - limit_choices_to=Q(nid__gt=10) 65 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 66 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 67 symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段 68 # 做如下操作时,不同的symmetrical会有不同的可选字段 69 models.BB.objects.filter(...) 70 71 # 可选字段有:code, id, m1 72 class BB(models.Model): 73 74 code = models.CharField(max_length=12) 75 m1 = models.ManyToManyField('self',symmetrical=True) 76 77 # 可选字段有: bb, code, id, m1 78 class BB(models.Model): 79 80 code = models.CharField(max_length=12) 81 m1 = models.ManyToManyField('self',symmetrical=False) 82 83 through=None, # 自定义第三张表时,使用字段用于指定关系表 84 through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表 85 from django.db import models 86 87 class Person(models.Model): 88 name = models.CharField(max_length=50) 89 90 class Group(models.Model): 91 name = models.CharField(max_length=128) 92 members = models.ManyToManyField( 93 Person, 94 through='Membership', 95 through_fields=('group', 'person'), 96 ) 97 98 class Membership(models.Model): 99 group = models.ForeignKey(Group, on_delete=models.CASCADE) 100 person = models.ForeignKey(Person, on_delete=models.CASCADE) 101 inviter = models.ForeignKey( 102 Person, 103 on_delete=models.CASCADE, 104 related_name="membership_invites", 105 ) 106 invite_reason = models.CharField(max_length=64) 107 db_constraint=True, # 是否在数据库中创建外键约束 108 db_table=None, # 默认创建第三张表时,数据库中表的名称
十四、MVC,MTV
1 models(数据库,模型) views(html模板) controllers(业务逻辑处理) --> MVC 2 3 4 models(数据库,模型) templates(html模板) views(业务逻辑处理) --> MTV 5 6 7 Django -----基于-----> MTV
十五、事务
示例一:
1 try: 2 from django.db import transaction 3 with transaction.atomic(): 4 models.UpDown.objects.create(user_id=user_id,article_id=article_id,up=False) 5 models.Article.objects.filter(nid=article_id).update(down_count=F('down_count')+1) 6 except Exception as e: 7 response['status'] = False 8 response['msg'] = str(e)
示例二:
1 #函数里面有数据库操作,加在函数上 2 from django.db.transaction import atomic 3 4 @atomic 5 def cmd(self): 6 model..... 7 model.....
十六、随机生成验证码
1 # import random 2 # print(random.random()) #0-1的小数 3 # print(random.randint(1,3)) #包括1和3 4 # print("--",random.randrange(1,3)) #不包括1和3 5 6 #随机生成四位验证码 7 import random 8 checkcode = '' 9 for i in range(4): 10 current = random.randrange(0,4) 11 if current != i: 12 temp = chr(random.randint(65,90)) 13 else: 14 temp = random.randint(0,9) 15 checkcode += str(temp) 16 print(checkcode) 17 #KS3G 18 19 20 #随机生成8位验证码 21 import string 22 23 print(string.ascii_lowercase) 24 #abcdefghijklmnopqrstuvwxyz 25 print(string.digits) 26 #0123456789 27 28 obj = random.sample(string.ascii_lowercase+string.digits,8) 29 print(obj) 30 #['i', 'm', 'o', '9', '6', 'p', 'g', '0'] 31 row = "".join(random.sample(string.ascii_lowercase+string.digits,8)) 32 print(row) 33 #417x6kyt
十七、AEC(高级加密)
1 #3.6安装 pip3 install pycryptodome 2 #mac pip3 install pycrypto
示例:
1 ############################### 加密 ############################## 2 3 from Crypto.Cipher import AES 4 def encrypt(message): 5 key = b'dfdsdfsasdfdsdfs' #key必须是16的整数倍 6 cipher = AES.new(key, AES.MODE_CBC, key) #创建对象 7 ---------------------------------------------- 8 #先转成字节,把数据拼够16字节的整数倍 9 ba_data = bytearray(message,encoding='utf-8') #把数据转成bytearray(byte的数组),bytearray只能追加数字,默认把数字转成字节 10 v1 = len(ba_data) 11 v2 = v1 % 16 12 if v2 == 0: 13 v3 = 16 14 else: 15 v3 = 16 - v2 #v3是追加的长度 16 for i in range(v3): 17 ba_data.append(v3) #bytearray只能追加数字,默认把数字转成字节 18 final_data = ba_data.decode('utf-8') 19 ---------------------------------------------- 20 msg = cipher.encrypt(final_data) #要加密的字符串,必须是16个字节或16个字节的倍数,加密后是byte格式 21 return msg 22 23 ############################### 解密 ############################## 24 def decrypt(msg): 25 key = b'dfdsdfsasdfdsdfs' 26 cipher = AES.new(key, AES.MODE_CBC, key) 27 result = cipher.decrypt(msg) #把加密后的字节解密成不加密的字节 28 data = result[0:-result[-1]] 29 return str(data,encoding='utf-8')
十八、前端Format方法
为字符串创建Format方法,用于字符串格式化
1 String.prototype.Format=function (arg) { 2 //console.log(this,arg); //this,当前调用方法的字符串,arg为Format方法传入的参数 3 //return '666'; //return,格式化之后获取的新内容,return啥就替换为啥 4 var temp = this.replace(/{(w+)}/g,function (k,kk) { 5 // k相当于{(w+)},kk相当于(w+)要替换的东西,arg一般是一个字典 6 return arg[kk]; 7 }); 8 return temp; 9 }; 10 11 #调用 12 a = {nid} 13 b = {"nid":"123"} 14 a.Format(b)
十九、高级使用----反射
1 反射: 2 getattr(obj,'xxx') 3 4 导入模块: 5 import re 6 'django.middleware.clickjacking.XFrameOptionsMiddleware' 7 m = importlib.import_module('django.middleware.clickjacking') 8 cls = getattr(m,'XFrameOptionsMiddleware') 9 cls() 10 11 面向对象: 12 13 #示例一: 之后爬虫使用 14 class Foo: 15 def __init__(self): 16 pass 17 18 @classmethod 19 def instance(cls): 20 return cls() 21 22 def process(self): 23 pass 24 25 if hasattr(Foo,'instance'): 26 obj = Foo.instance() 27 else: 28 obj = Foo() 29 obj.process() 30 31 32 #示例二: 33 class A: 34 def f1(self): 35 self.f2() 36 37 def f2(self): 38 print('A.f2') 39 40 class B(A): 41 def f2(self): 42 print("B.f2") 43 44 obj = B() 45 obj.f1()
二十、request
1 客户端向服务端发送多层字典的值
1 obj = { 2 'data':{ 3 "k1":"v1", 4 "k2":"v2" 5 }, 6 'status': True 7 } 8 9 #json发送 10 requests.post("http://www.baidu.com",json=obj) 11 12 #发送数据内部默认处理(会在内部把字典obj json.dumps序列成字符串,发送给服务端) 13 14 #body: json.dumps(obj) 15 #headers= {'content-type':'application/json'} #默认加入 16 17 #只有设置如下请求头request.post才能接受,但不能接受多层字典的数据,接受第二层字典只能接受key,不能接受value 18 #headers= {'content-type':"application/x-www-form-urlencoded"} 19 20 21 #接受上面格式发送的数据 22 if request.method == 'POST': 23 obj = json.loads(request.body.decode('utf-8'))
2 request.post 和request.body
1 #接受 2 requests.boby 3 - 请求体原生的值 4 5 requests.POST 6 - 根据特殊的请求头从requests.boby获取数据,不能接受多层字典的数据
3 三者相等
1 #方式一: 2 3 requests.post("http://www.baidu.com",json=obj) 4 5 #方式二: 6 7 requests.post( 8 url="http://www.baidu.com", 9 headers={'content-type':'application/json'}, 10 data=json.dumps(obj) 11 ) 12 13 #方式三(): 14 15 requests.post( 16 url="http://www.baidu.com", 17 headers={'content-type':'application/json'}, 18 data=bytes(json.dumps(obj),encoding="utf-8") 19 )
二十一、hashlib加密(md5)
md5加密
1 m = hashlib.md5() 2 m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据 3 md5_key = m.hexdigest() #返回值是字符窜类型
二十二、命令行执行Django脚本
1 - #效仿manage.py加入的环境变量在脚本的文件加入 2 - #手动注册django所有的APP
1 import sys,os 2 -----------------------举例 3 from audit.backend import user_interactive 4 5 6 if __name__ == "__main__": 7 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "LuffyAudit.settings") 8 import django 9 django.setup() #手动注册django所有的APP 10 -----------------------举例 11 obj = user_interactive.UserShell(sys.argv) 12 obj.start()
二十三、API验证
1 API验证: 2 a. 发令牌: 静态 3 PS: 隐患 key被别人获取 4 b. 动态令牌 5 PS: (问题越严重)用户生成的每个令牌被黑客获取到,都会破解 6 c. 高级版本 7 PS: 黑客网速快,会窃取, so要对数据加密 8 d. 终极版本 9 10 11 特点: 12 为什么要用API ? 13 - 数据在传输过程中,保证数据安全 14 你是如何设计的 ? 15 - Tornado 中的加密Cookie类似 16 - 创建动态key md5(key + time)|time (Tornado中也是这么做) 17 - 限制 18 - 第一关: 时间 19 - 第二关: 算法规则 20 - 第三关: 已访问的记录 21 PS: 黑客网速快,会窃取, so要对数据加密
1 客户端和服务端都有一个相同的key
1 客户端把key发给服务端,服务端拿着自己的key和客户端的key做比较 2 3 ###客户端 4 5 import time 6 import requests 7 8 key = "asdfasdfasdfasdf098712sdfs" 9 10 response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':key}) 11 print(response.text) 12 13 14 ###服务端 15 16 #print(request.META) 17 key = request.META.get("HTTP_OPENKEY") 18 if key != settings.AUTH_KEY: 19 return HttpResponse("验证失败")
2 key和时间
1 #客户端和服务端都有一个相同的key 2 #客户端把加密key和当前时间发给服务端,服务端收到后把客户端发来的时间和自己的key加密 3 #然后把加密后的字串和客户端的字串比较 4 5 #客户端 6 7 import time 8 import requests 9 import hashlib 10 11 ctime = time.time() 12 key = "asdfasdfasdfasdf098712sdfs" 13 new_key = "%s|%s" %(key,ctime,) 14 15 m = hashlib.md5() 16 m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据 17 md5_key = m.hexdigest() #返回值是字符串类型 18 19 md5_time_key = "%s|%s" %(md5_key,ctime) 20 21 22 response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':md5_time_key}) 23 print(response.text) 24 25 #服务端 26 client_md5_time_key = request.META.get("HTTP_OPENKEY") 27 28 client_md5_key,client_ctime = client_md5_time_key.split("|") 29 30 temp = "%s|%s"%(settings.AUTH_KEY,client_ctime) 31 m = hashlib.md5() 32 m.update(bytes(temp, encoding='utf-8')) 33 server_md5_key = m.hexdigest() 34 35 36 if server_md5_key != client_md5_key: 37 return HttpResponse("验证失败")
3 高级版本
1 #客户端和服务端都有一个相同的key 2 #客户端把加密key和当前时间发给服务端 3 #服务端验证: 4 #1)服务端判断服务器当前的时间是否比客户端时间快10s,如果在10s内通过,有效的杜绝了案例二成千上万的key 5 #2)服务器获取客户端时间和自己key加密然后和 客户端获取到的key比较 6 #3)删除与现在时间相差10s的数据(之后用memcache,redis) 7 #3)在字典里判断是否有这个key,如果有不通过,没有加入字典(之后用memcache,redis) 8 9 10 11 #客户端 12 import time 13 import requests 14 import hashlib 15 16 ctime = time.time() 17 key = "asdfasdfasdfasdf098712sdfs" 18 new_key = "%s|%s" %(key,ctime,) 19 20 m = hashlib.md5() 21 m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据 22 md5_key = m.hexdigest() #返回值是字符串类型 23 24 md5_time_key = "%s|%s" %(md5_key,ctime) 25 26 print(md5_time_key) 27 response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':md5_time_key}) 28 29 #黑客获取调用 30 #response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':"f610077a7001c53b5a74868c5544b388|1501514254.455578"}) 31 print(response.text) 32 33 34 #服务端 35 api_key_record ={ 36 "76942d662d98ebe3b920a7b791bf5040|1501510243.92804":1501510243.92804, 37 } 38 39 40 def asset(request): 41 42 43 client_md5_time_key = request.META.get("HTTP_OPENKEY") 44 45 client_md5_key,client_ctime = client_md5_time_key.split("|") 46 client_ctime = float(client_ctime) 47 server_ctime = time.time() 48 49 #第一关 时间关 50 if server_ctime - client_ctime > 10: 51 return HttpResponse("第一关 小伙子,别虎我,太长了") 52 53 #第二关 客户端时间和服务端key加密和 客户端的密钥对比 54 temp = "%s|%s"%(settings.AUTH_KEY,client_ctime) 55 m = hashlib.md5() 56 m.update(bytes(temp, encoding='utf-8')) 57 server_md5_key = m.hexdigest() 58 if server_md5_key != client_md5_key: 59 return HttpResponse("第二关 规则正确") 60 61 62 #以后基于memcache,目前先写入内存删除超过10s的值 63 for k in list(api_key_record.keys()): 64 v = api_key_record[k] 65 if server_ctime > v: 66 del api_key_record[k] 67 68 69 #第三关 判断字典里是否有之前访问的key,如果有不通过,没有加入字典 70 if client_md5_time_key in api_key_record: 71 return HttpResponse("第三关 已经有人来过了") 72 else: 73 api_key_record[client_md5_time_key] = client_ctime + 10
4 终极版本
1 注意: key 是从配置文件获取的 2 3 装饰器要返回Httpresponse对象
1 __author__ = 'Administrator' 2 from Crypto.Cipher import AES 3 from lib.conf.config import settings 4 def encrypt(message): 5 """ 6 数据加密 7 :param message: 8 :return: 9 """ 10 key = settings.DATA_KEY 11 cipher = AES.new(key, AES.MODE_CBC, key) 12 ba_data = bytearray(message,encoding='utf-8') 13 v1 = len(ba_data) 14 v2 = v1 % 16 15 if v2 == 0: 16 v3 = 16 17 else: 18 v3 = 16 - v2 19 for i in range(v3): 20 ba_data.append(v3) 21 final_data = ba_data.decode('utf-8') 22 msg = cipher.encrypt(final_data) # 要加密的字符串,必须是16个字节或16个字节的倍数 23 return msg 24 25 def decrypt(msg): 26 """ 27 数据解密 28 :param message: 29 :return: 30 """ 31 from Crypto.Cipher import AES 32 key = settings.DATA_KEY 33 cipher = AES.new(key, AES.MODE_CBC, key) 34 result = cipher.decrypt(msg) # result = b'xe8xa6x81xe5x8axa0xe5xafx86xe5x8axa0xe5xafx86xe5x8axa0sdfsd ' 35 data = result[0:-result[-1]] 36 return str(data,encoding='utf-8') 37 38 39 def auth(): 40 """ 41 API验证 42 :return: 43 """ 44 import time 45 import requests 46 import hashlib 47 48 ctime = time.time() 49 key = "asdfasdfasdfasdf098712sdfs" 50 new_key = "%s|%s" %(key,ctime,) 51 52 m = hashlib.md5() 53 m.update(bytes(new_key,encoding='utf-8')) #里面是字节数据 54 md5_key = m.hexdigest() #返回值是字符窜类型 55 56 md5_time_key = "%s|%s" %(md5_key,ctime) 57 58 return md5_time_key
1 from Crypto.Cipher import AES 2 import requests 3 import json 4 from lib.utils import encrypt 5 from lib.utils import auth 6 7 #对数据加密字典 8 v1 = encrypt(json.dumps({"k1":"v1"})) #获取的是加密后的字节 9 print(v1) 10 11 response = requests.post( 12 url="http://127.0.0.1:8000/api/asset.html", 13 headers={'OpenKey':auth(),'content-type':'application/json'}, 14 data=v1 15 ) 16 17 18 print(response.text)
1 import json 2 import hashlib 3 from django.shortcuts import render,HttpResponse 4 from repository import models 5 from django.conf import settings 6 from api.service import PluginManager 7 import time 8 import json 9 from Crypto.Cipher import AES 10 11 12 api_key_record ={ 13 "76942d662d98ebe3b920a7b791bf5040|1501510243.92804":1501510243.92804, 14 } 15 16 17 def decrypt(msg): 18 key = b'dfdsdfsasdfdsdfs' 19 cipher = AES.new(key, AES.MODE_CBC, key) 20 result = cipher.decrypt(msg) # 把加密后的字节解密成不加密的字节 21 data = result[0:-result[-1]] 22 return str(data, encoding='utf-8') 23 24 25 def outer(func): 26 def wrapper(request): 27 client_md5_time_key = request.META.get("HTTP_OPENKEY") 28 29 client_md5_key, client_ctime = client_md5_time_key.split("|") 30 client_ctime = float(client_ctime) 31 server_ctime = time.time() 32 33 # 第一关 时间关 34 if server_ctime - client_ctime > 30: 35 return HttpResponse("第一关 小伙子,别虎我,太长了") 36 37 # 第二关 客户端时间和服务端key加密和 客户端的密钥对比 38 temp = "%s|%s" % (settings.AUTH_KEY, client_ctime) 39 m = hashlib.md5() 40 m.update(bytes(temp, encoding='utf-8')) 41 server_md5_key = m.hexdigest() 42 if server_md5_key != client_md5_key: 43 return HttpResponse("第二关 规则正确") 44 45 # 以后基于memcache,目前先写入内存删除超过10s的值 46 for k in list(api_key_record.keys()): 47 v = api_key_record[k] 48 if server_ctime > v: 49 del api_key_record[k] 50 51 # 第三关 判断字典里是否有之前访问的key,如果有不通过,没有加入字典 52 if client_md5_time_key in api_key_record: 53 return HttpResponse("第三关 已经有人来过了") 54 else: 55 api_key_record[client_md5_time_key] = client_ctime + 10 56 obj = func(request) 57 return obj 58 59 return wrapper 60 61 62 63 @outer 64 def asset(request): 65 66 67 if request.method == 'GET': 68 ys = '重要的不能被闲杂人等看的数据' 69 return HttpResponse(ys) 70 71 elif request.method == 'POST': 72 73 server_info = decrypt(request.body) 74 server_info = json.loads(server_info) 75 76 77 78 # # 新资产信息 79 # server_info = json.loads(request.body.decode('utf-8')) 80 hostname = server_info['basic']['data']['hostname'] 81 # 老资产信息 82 server_obj = models.Server.objects.filter(hostname=hostname).first() 83 if not server_obj: 84 return HttpResponse('当前主机名在资产中未录入') 85 86 87 PluginManager(server_info,server_obj,hostname).exec_plugin() 88 89 return HttpResponse("...")
二十四、KindEditor
1 进入官网
2 下载
官网下载:http://kindeditor.net/down.php
3 文件夹说明
1 ├── asp asp示例 2 ├── asp.net asp.net示例 3 ├── attached 空文件夹,放置关联文件attached 4 ├── examples HTML示例 5 ├── jsp java示例 6 ├── kindeditor-all-min.js 全部JS(压缩) 7 ├── kindeditor-all.js 全部JS(未压缩) 8 ├── kindeditor-min.js 仅KindEditor JS(压缩) 9 ├── kindeditor.js 仅KindEditor JS(未压缩) 10 ├── lang 支持语言 11 ├── license.txt License 12 ├── php PHP示例 13 ├── plugins KindEditor内部使用的插件 14 └── themes KindEditor主题
4 基本使用
1 <textarea name="content" id="content"></textarea> 2 3 <script src="/static/jquery-1.12.4.js"></script> 4 <script src="/static/plugins/kind-editor/kindeditor-all.js"></script> 5 <script> 6 $(function () { 7 initKindEditor(); 8 }); 9 10 function initKindEditor() { 11 var kind = KindEditor.create('#content', { 12 '100%', // 文本框宽度(可以百分比或像素) 13 height: '300px', // 文本框高度(只能像素) 14 minWidth: 200, // 最小宽度(数字) 15 minHeight: 400 // 最小高度(数字) 16 }); 17 } 18 </script>
5 详细参数
http://kindeditor.net/docs/option.html
6 上传文件示例
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 9 <div> 10 <h1>文章内容</h1> 11 {{ request.POST.content|safe }} 12 </div> 13 14 15 <form method="POST"> 16 <h1>请输入内容:</h1> 17 {% csrf_token %} 18 <div style=" 500px; margin: 0 auto;"> 19 <textarea name="content" id="content"></textarea> 20 </div> 21 <input type="submit" value="提交"/> 22 </form> 23 24 <script src="/static/jquery-1.12.4.js"></script> 25 <script src="/static/plugins/kind-editor/kindeditor-all.js"></script> 26 <script> 27 $(function () { 28 initKindEditor(); 29 }); 30 31 function initKindEditor() { 32 var a = 'kind'; 33 var kind = KindEditor.create('#content', { 34 '100%', // 文本框宽度(可以百分比或像素) 35 height: '300px', // 文本框高度(只能像素) 36 minWidth: 200, // 最小宽度(数字) 37 minHeight: 400, // 最小高度(数字) 38 uploadJson: '/kind/upload_img/', 39 extraFileUploadParams: { 40 'csrfmiddlewaretoken': '{{ csrf_token }}' 41 }, 42 fileManagerJson: '/kind/file_manager/', 43 allowPreviewEmoticons: true, 44 allowImageUpload: true 45 }); 46 } 47 </script> 48 </body> 49 </html>
1 import os 2 import json 3 import time 4 5 from django.shortcuts import render 6 from django.shortcuts import HttpResponse 7 8 9 def index(request): 10 """ 11 首页 12 :param request: 13 :return: 14 """ 15 return render(request, 'index.html') 16 17 18 def upload_img(request): 19 """ 20 文件上传 21 :param request: 22 :return: 23 """ 24 dic = { 25 'error': 0, 26 'url': '/static/imgs/20130809170025.png', 27 'message': '错误了...' 28 } 29 30 return HttpResponse(json.dumps(dic)) 31 32 33 def file_manager(request): 34 """ 35 文件管理 36 :param request: 37 :return: 38 """ 39 dic = {} 40 root_path = '/Users/wupeiqi/PycharmProjects/editors/static/' 41 static_root_path = '/static/' 42 request_path = request.GET.get('path') 43 if request_path: 44 abs_current_dir_path = os.path.join(root_path, request_path) 45 move_up_dir_path = os.path.dirname(request_path.rstrip('/')) 46 dic['moveup_dir_path'] = move_up_dir_path + '/' if move_up_dir_path else move_up_dir_path 47 48 else: 49 abs_current_dir_path = root_path 50 dic['moveup_dir_path'] = '' 51 52 dic['current_dir_path'] = request_path 53 dic['current_url'] = os.path.join(static_root_path, request_path) 54 55 file_list = [] 56 for item in os.listdir(abs_current_dir_path): 57 abs_item_path = os.path.join(abs_current_dir_path, item) 58 a, exts = os.path.splitext(item) 59 is_dir = os.path.isdir(abs_item_path) 60 if is_dir: 61 temp = { 62 'is_dir': True, 63 'has_file': True, 64 'filesize': 0, 65 'dir_path': '', 66 'is_photo': False, 67 'filetype': '', 68 'filename': item, 69 'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path))) 70 } 71 else: 72 temp = { 73 'is_dir': False, 74 'has_file': False, 75 'filesize': os.stat(abs_item_path).st_size, 76 'dir_path': '', 77 'is_photo': True if exts.lower() in ['.jpg', '.png', '.jpeg'] else False, 78 'filetype': exts.lower().strip('.'), 79 'filename': item, 80 'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path))) 81 } 82 83 file_list.append(temp) 84 dic['file_list'] = file_list 85 return HttpResponse(json.dumps(dic))
7 XSS过滤特殊标签
处理依赖
pip3 install beautifulsoup4
1 from bs4 import BeautifulSoup 2 3 4 class XSSFilter(object): 5 __instance = None 6 7 def __init__(self): 8 # XSS白名单 9 self.valid_tags = { 10 "font": ['color', 'size', 'face', 'style'], 11 'b': [], 12 'div': [], 13 "span": [], 14 "table": [ 15 'border', 'cellspacing', 'cellpadding' 16 ], 17 'th': [ 18 'colspan', 'rowspan' 19 ], 20 'td': [ 21 'colspan', 'rowspan' 22 ], 23 "a": ['href', 'target', 'name'], 24 "img": ['src', 'alt', 'title'], 25 'p': [ 26 'align' 27 ], 28 "pre": ['class'], 29 "hr": ['class'], 30 'strong': [] 31 } 32 33 @classmethod 34 def instance(cls): 35 if not cls.__instance: 36 obj = cls() 37 cls.__instance = obj 38 return cls.__instance 39 40 def process(self, content): 41 soup = BeautifulSoup(content, 'lxml') 42 # 遍历所有HTML标签 43 for tag in soup.find_all(recursive=True): 44 # 判断标签名是否在白名单中 45 if tag.name not in self.valid_tags: 46 tag.hidden = True 47 if tag.name not in ['html', 'body']: 48 tag.hidden = True 49 tag.clear() 50 continue 51 # 当前标签的所有属性白名单 52 attr_rules = self.valid_tags[tag.name] 53 keys = list(tag.attrs.keys()) 54 for key in keys: 55 if key not in attr_rules: 56 del tag[key] 57 58 return soup.renderContents() 59 60 61 if __name__ == '__main__': 62 html = """<p class="title"> 63 <b>The Dormouse's story</b> 64 </p> 65 <p class="story"> 66 <div name='root'> 67 Once upon a time there were three little sisters; and their names were 68 <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' id="link1"><!-- Elsie --></a> 69 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and 70 <a href="http://example.com/tillie" class="sister" id="link3">Tilffffffffffffflie</a>; 71 and they lived at the bottom of a well. 72 <script>alert(123)</script> 73 </div> 74 </p> 75 <p class="story">...</p>""" 76 77 v = XSSFilter.instance().process(html) 78 print(v)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 from bs4 import BeautifulSoup 4 5 6 class XSSFilter(object): 7 __instance = None 8 9 def __init__(self): 10 # XSS白名单 11 self.valid_tags = { 12 "font": ['color', 'size', 'face', 'style'], 13 'b': [], 14 'div': [], 15 "span": [], 16 "table": [ 17 'border', 'cellspacing', 'cellpadding' 18 ], 19 'th': [ 20 'colspan', 'rowspan' 21 ], 22 'td': [ 23 'colspan', 'rowspan' 24 ], 25 "a": ['href', 'target', 'name'], 26 "img": ['src', 'alt', 'title'], 27 'p': [ 28 'align' 29 ], 30 "pre": ['class'], 31 "hr": ['class'], 32 'strong': [] 33 } 34 35 def __new__(cls, *args, **kwargs): 36 """ 37 单例模式 38 :param cls: 39 :param args: 40 :param kwargs: 41 :return: 42 """ 43 if not cls.__instance: 44 obj = object.__new__(cls, *args, **kwargs) 45 cls.__instance = obj 46 return cls.__instance 47 48 def process(self, content): 49 soup = BeautifulSoup(content, 'lxml') 50 # 遍历所有HTML标签 51 for tag in soup.find_all(recursive=True): 52 # 判断标签名是否在白名单中 53 if tag.name not in self.valid_tags: 54 tag.hidden = True 55 if tag.name not in ['html', 'body']: 56 tag.hidden = True 57 tag.clear() 58 continue 59 # 当前标签的所有属性白名单 60 attr_rules = self.valid_tags[tag.name] 61 keys = list(tag.attrs.keys()) 62 for key in keys: 63 if key not in attr_rules: 64 del tag[key] 65 66 return soup.renderContents() 67 68 69 if __name__ == '__main__': 70 html = """<p class="title"> 71 <b>The Dormouse's story</b> 72 </p> 73 <p class="story"> 74 <div name='root'> 75 Once upon a time there were three little sisters; and their names were 76 <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' id="link1"><!-- Elsie --></a> 77 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and 78 <a href="http://example.com/tillie" class="sister" id="link3">Tilffffffffffffflie</a>; 79 and they lived at the bottom of a well. 80 <script>alert(123)</script> 81 </div> 82 </p> 83 <p class="story">...</p>""" 84 85 obj = XSSFilter() 86 v = obj.process(html) 87 print(v)
8 示例图
二十五、Django多级评论
1 原理
1 #多级评论原理简单原理,弄完之后发现基础白学了 2 msg_list = [ 3 {'id':1,'content':'xxx','parent_id':None}, 4 {'id':2,'content':'xxx','parent_id':None}, 5 {'id':3,'content':'xxx','parent_id':None}, 6 {'id':4,'content':'xxx','parent_id':1}, 7 {'id':5,'content':'xxx','parent_id':4}, 8 {'id':6,'content':'xxx','parent_id':2}, 9 {'id':7,'content':'xxx','parent_id':5}, 10 {'id':8,'content':'xxx','parent_id':3}, 11 ] 12 #python里面的apend之类的东西都是引用的原来数据的内从地址,对原数据进行操作的话 13 #我们引用的数据也会发生一样的变化(字典列表之类的) 14 15 #骗子的方法 16 # for i in msg_list: 17 # i['child']=[] 18 # for i in range(len(msg_list)-1,-1,-1): 19 # if msg_list[i]['parent_id']: 20 # msg_list[msg_list[i]['parent_id'] - 1]['child'].append(msg_list[i]) 21 # new_msg_list = [i for i in msg_list if i['parent_id'] is None] 22 # print(new_msg_list) 23 24 #老师讲的方法 25 # v=[row.setdefault('child',[]) for row in msg_list] #这和地下的第一个for循环的作用是一样的,给每一个元素加一个'child':[] 26 # print(msg_list) 27 #如果我们想加快索引(快点找到数据的话)就建一个字典的数据结构 28 msg_list_dict={} #加快索引,节省时间 29 for item in msg_list: 30 item['child']=[] 31 msg_list_dict[item['id']]=item #字典中key为item['id'],value为item 32 #把字典数据结构填上数据,能够加快索引,而且我们数据还是占得原来的内从空间 33 #我们只是引用了数据的内容空间,所以不存在新的数据结构浪费空间一说 34 result=[] 35 for item in msg_list: 36 pid=item['parent_id'] 37 if pid: #如果parent_id不为空,说明它是子级,要把自己加入对应的父级 38 msg_list_dict[pid]['child'].append(item) 39 else: #如果为空,说明他是父级,要把它单独领出来用 40 result.append(item) 41 #result就是我们最终要的结果,因为这里面全是引用,所有数据的内存地址都没有变 42 #只不过被多个数据结构引用了而已 43 print(result)
2 精简版
1 def comments(request,nid): 2 res={'status':True,'data':None,'msg':None} 3 try: 4 comment_list = models.Comment.objects.filter(article_id=nid).values() 5 com_list = list(comment_list) # 所有的评论,列表套字典 6 com_list_dict = {} # 建立一个方便查找的数据结构字典 7 for item in com_list: # 循环评论列表,给每一条评论加一个child:[]就是让他装对他回复的内容 8 item['create_time'] = str(item['create_time']) 9 item['child'] = [] 10 com_list_dict[item['nid']] = item 11 result = [] 12 for item in com_list: 13 rid = item['reply_id'] 14 if rid: # 如果reply_id不为空的话,那么就是说明他是子评论,我们要把他加入对应的评论后面 15 com_list_dict[rid]['child'].append(item) 16 else: 17 result.append(item) 18 print(result) 19 # comment_str = comment_tree(result) 20 # 这是在服务器上递归完之后,然后在传到前端,但是这样会增加服务器压力 21 #所以这种方式我们直接就不用了 22 res['data']=result 23 except Exception as e: 24 res['status']=False 25 res['mag']=str(e) 26 return HttpResponse(json.dumps(res))
1 <style> 2 .comment{ 3 margin-left:20px; 4 } 5 </style> 6 7 <body> 8 <div id="commentArea"> 9 10 </div> 11 </body> 12 <script src="/static/jquery-3.2.1.js"></script> 13 <script> 14 //自定义JS中字符串格式化方法 15 String.prototype.Format=function (arg) { 16 //console.log(this,arg); //this,当前调用方法的字符串,arg为Format方法传入的参数 17 //return '666'; //return,格式化之后获取的新内容,return啥就替换为啥 18 var temp = this.replace(/{(w+)}/g,function (k,kk) { 19 // k相当于{(w+)},kk相当于(w+)要替换的东西,arg一般是一个字典 20 return arg[kk]; 21 }); 22 return temp; 23 }; 24 25 $(function () { 26 //发送Ajax请求,获取所有评论的信息 27 //列表 28 //JS生成结构 29 var token=$.cookie('csrftoken'); 30 $.ajax({ 31 url:"/comments-{{ article_obj.nid }}.html", 32 type:"GET", 33 dataType:"JSON", 34 success:function (arg) { 35 if (arg.status){ 36 var comment=commentTree(arg.data); 37 $('#commentArea').append(comment); 38 }else{ 39 alert(arg.msg); 40 } 41 } 42 }) 43 }); 44 45 //多级评论递归函数,js函数里面也有return,自己写js字符串格式化 46 //pyhton中字符串的方法都是str下的,js中是String.prototype下找的 47 function commentTree(commentList) { 48 var comment_str="<div class='comment'>"; 49 $.each(commentList,function (k,row) { 50 var temp="<div class='content'>{content}</div>".Format({content:row.content}); 51 comment_str += temp; 52 if (row.child.length>0){ 53 comment_str += commentTree(row.child); 54 } 55 }); 56 comment_str += '</div>'; 57 return comment_str 58 } 59 </script>
二十六、REST framework
1. 什么是REST
- REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
- REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
- REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
- 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
- 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)
设计参考:http://www.ruanyifeng.com/blog/2014/05/restful_api.html
2. 目前如何实现 REST API ?
按照规则,根据不同的请求方式做出不同的处理,并且返回内容以及相应状态码
3. 什么是 Django REST framework?
Django REST framework是一个基于Django开发的app,用于快速搭建REST API。
安装:
1 pip3 install djangorestframework
a. 快速使用
INSTALLED_APPS = [ ... 'rest_framework', ]
1 from rest_framework import routers 2 from . import views 3 4 5 router = routers.DefaultRouter() 6 router.register(r'users', views.UserInfoViewSet) 7 8 urlpatterns = [ 9 url(r'^', include(router.urls)), 10 ]
1 from rest_framework import viewsets 2 from . import models 3 from . import serializers 4 5 # ########### 1. 基本处理方式 ########### 6 7 class UserInfoViewSet(viewsets.ModelViewSet): 8 """ 9 API endpoint that allows users to be viewed or edited. 10 """ 11 queryset = models.UserInfo.objects.all().order_by('-id') 12 serializer_class = serializers.UserInfoSerializer
1 from rest_framework import serializers 2 from . import models 3 4 class UserInfoSerializer(serializers.HyperlinkedModelSerializer): 5 class Meta: 6 model = models.UserInfo 7 # fields = ('id', 'username', 'pwd','ug') # fields = '__all__' 8 exclude = ('ug',) 9 depth = 1 # 0<=depth<=10
PS:最终访问路径
1 [GET] http://127.0.0.1:8000/api/users/ 2 [POST] http://127.0.0.1:8000/api/users/ 3 [GET] http://127.0.0.1:8000/api/users/7/ 4 [PUT] http://127.0.0.1:8000/api/users/7/ 5 [DELETE] http://127.0.0.1:8000/api/users/7/
b. 基于CBV
1 from django.conf.urls import url,include 2 from django.contrib import admin 3 from . import views 4 5 urlpatterns = [ 6 url(r'^users/$', views.UserList.as_view()), 7 url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()), 8 ]
1 from rest_framework.views import APIView 2 from rest_framework.response import Response 3 from rest_framework.request import Request 4 from rest_framework.parsers import JSONParser 5 from . import models 6 from . import serializers 7 8 9 class UserList(APIView): 10 def get(self, request, *args, **kwargs): 11 user_list = models.UserInfo.objects.all() 12 serializer = serializers.MySerializer(instance=user_list, many=True) 13 return Response(serializer.data) 14 15 def post(self, request, *args, **kwargs): 16 data = JSONParser().parse(request) 17 serializer = serializers.MySerializer(data=data) 18 if serializer.is_valid(): 19 # print(serializer.data) 20 # print(serializer.errors) 21 # print(serializer.validated_data) 22 # 如果有instance,则执行update方法;否则,执行create 23 serializer.save() 24 return Response(serializer.data, status=201) 25 return Response(serializer.errors, status=400) 26 27 28 class UserDetail(APIView): 29 def get(self, request, *args, **kwargs): 30 obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first() 31 serializer = serializers.MySerializer(obj) 32 return Response(serializer.data) 33 34 def delete(self, request, *args, **kwargs): 35 obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first() 36 obj.delete() 37 return Response(status=204) 38 39 def put(self, request, *args, **kwargs): 40 data = JSONParser().parse(request) 41 obj = models.UserInfo.objects.filter(pk=kwargs.get('pk')).first() 42 serializer = serializers.MySerializer(obj, data=data) 43 if serializer.is_valid(): 44 serializer.save() 45 return Response(serializer.data) 46 return Response(serializer.errors, status=400)
1 from rest_framework import serializers 2 from rest_framework.exceptions import ValidationError 3 from . import models 4 5 6 class MySerializer(serializers.Serializer): 7 id = serializers.IntegerField(read_only=True) 8 username = serializers.CharField(required=False, allow_blank=True, max_length=100) 9 pwd = serializers.CharField() 10 11 def validate_username(self, value): 12 if value == '中国': 13 raise ValidationError('用户名中存在敏感字符') 14 return value 15 16 def validate_pwd(self, value): 17 print(value) 18 return value 19 20 def validate(self, attrs): 21 print(attrs) 22 return attrs 23 24 def create(self, validated_data): 25 """ 26 当执行save方法时,自动调用。instance未传值 27 :param validated_data: 28 :return: 29 """ 30 print(validated_data) 31 return models.UserInfo.objects.create(**validated_data) 32 33 def update(self, instance, validated_data): 34 """ 35 当执行save方法时,自动调用。instance传值 36 :param instance: 37 :param validated_data: 38 :return: 39 """ 40 instance.username = validated_data.get('username', instance.username) 41 instance.save() 42 return instance
c. 基于CBV
1 from django.conf.urls import url,include 2 from django.contrib import admin 3 from . import views 4 5 urlpatterns = [ 6 url(r'^users/$', views.user_list), 7 url(r'^users/(?P<pk>[0-9]+)/$', views.user_detail), 8 ]
1 from django.http import JsonResponse,HttpResponse 2 from rest_framework.response import Response 3 from rest_framework.parsers import JSONParser 4 from rest_framework.decorators import api_view 5 from .serializers import MySerializer 6 from . import models 7 8 @api_view(['GET',"POST"]) 9 def user_list(request): 10 """ 11 List all code snippets, or create a new snippet. 12 """ 13 if request.method == 'GET': 14 user_list = models.UserInfo.objects.all() 15 serializer = MySerializer(user_list,many=True) 16 return Response(serializer.data) 17 18 elif request.method == 'POST': 19 data = JSONParser().parse(request) 20 serializer = MySerializer(data=data) 21 if serializer.is_valid(): 22 print(serializer.data) 23 print(serializer.errors) 24 print(serializer.validated_data) 25 # 如果有instance,则执行update方法;否则,执行create 26 serializer.save() 27 return Response(serializer.data, status=201) 28 return Response(serializer.errors, status=400) 29 30 @api_view(['GET',"POST","PUT"]) 31 def user_detail(request, pk): 32 """ 33 Retrieve, update or delete a code snippet. 34 """ 35 36 obj = models.UserInfo.objects.filter(pk=pk).first() 37 if not obj: 38 return HttpResponse(status=404) 39 40 if request.method == 'GET': 41 serializer = MySerializer(obj) 42 # return JsonResponse(serializer.data,json_dumps_params={'ensure_ascii':False},content_type='application/json;charset=utf-8') 43 return Response(serializer.data) 44 45 elif request.method == 'PUT': 46 data = JSONParser().parse(request) 47 serializer = MySerializer(obj, data=data) 48 if serializer.is_valid(): 49 serializer.save() 50 return Response(serializer.data) 51 return Response(serializer.errors, status=400) 52 53 elif request.method == 'DELETE': 54 obj.delete() 55 return Response(status=204)
1 from rest_framework import serializers 2 from rest_framework.exceptions import ValidationError 3 from . import models 4 5 6 class MySerializer(serializers.Serializer): 7 id = serializers.IntegerField(read_only=True) 8 username = serializers.CharField(required=False, allow_blank=True, max_length=100) 9 pwd = serializers.CharField() 10 11 def validate_username(self, value): 12 if value == '中国': 13 raise ValidationError('用户名中存在敏感字符') 14 return value 15 16 def validate_pwd(self, value): 17 print(value) 18 return value 19 20 def validate(self, attrs): 21 print(attrs) 22 return attrs 23 24 def create(self, validated_data): 25 """ 26 当执行save方法时,自动调用。instance未传值 27 :param validated_data: 28 :return: 29 """ 30 print(validated_data) 31 return models.UserInfo.objects.create(**validated_data) 32 33 def update(self, instance, validated_data): 34 """ 35 当执行save方法时,自动调用。instance传值 36 :param instance: 37 :param validated_data: 38 :return: 39 """ 40 instance.username = validated_data.get('username', instance.username) 41 instance.save() 42 return instance
d. 权限控制
1 REST_FRAMEWORK = { 2 'DEFAULT_PERMISSION_CLASSES': [ 3 'permissi.MyPermission', 4 ] 5 }
1 class MyPermission(object): 2 """ 3 A base class from which all permission classes should inherit. 4 """ 5 6 def has_permission(self, request, view): 7 """ 8 Return `True` if permission is granted, `False` otherwise. 9 """ 10 11 return True 12 13 def has_object_permission(self, request, view, obj): 14 return True
1 - 全局配置 2 Highcharts.setOptions({ 3 global: { 4 useUTC: false 5 } 6 }); 7 8 - 主配置 9 var chart = new Highcharts.Chart('id1', { 10 title: { 11 text: '不同城市的月平均气温', 12 x: 0 13 }, 14 subtitle: { 15 text: '数据来源: WorldClimate.com', 16 x: 0 17 }, 18 chart: { 19 events: { 20 load: function (e) { 21 // 图标加载时,执行的函数 22 } 23 } 24 }, 25 credits: { 26 enable: true, 27 position: { 28 align: 'right', 29 verticalAlign: 'bottom' 30 }, 31 text: '老男孩', 32 href: 'http://www.oldboyedu.com' 33 }, 34 legend: { 35 layout: 'vertical', 36 align: 'right', 37 verticalAlign: 'middle', 38 borderWidth: 1 39 }, 40 41 xAxis: { 42 // categories: ['1.1', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], 43 type: 'datetime', 44 labels: { 45 formatter: function () { 46 return Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.value); 47 }, 48 rotation: 30 49 } 50 51 }, 52 yAxis: { 53 title: { 54 text: '数值' 55 } 56 }, 57 tooltip: { 58 valueSuffix: '个', 59 xDateFormat: "%Y-%m-%d %H:%M:%S", 60 pointFormatter: function (e) { 61 var tpl = '<span style="color:' + this.series.color + '">●</span> ' + this.series.name + ': <b>' + this.y + '</b><br/>'; 62 return tpl; 63 }, 64 valueDecimals: 1, 65 useHTML: true 66 }, 67 plotOptions: { 68 series: { 69 cursor: 'pointer', 70 events: { 71 click: function (event) { 72 // 点击某个指定点时,执行的事件 73 console.log(this.name, event.point.x, event.point.y); 74 } 75 } 76 } 77 }, 78 series: [{ 79 name: '东京', 80 // data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6] 81 data: [ 82 [1501689804077.358, 8.0], 83 [1501689814177.358, 6.9], 84 [1501689824277.358, 16.9], 85 [1501689834377.358, 11.9] 86 ] 87 }, 88 { 89 name: '洛杉矶', 90 // data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6] 91 data: [ 92 [1501689804077.358, 18.0], 93 [1501689814177.358, 16.9], 94 [1501689824277.358, 26.9], 95 [1501689834377.358, 9.9] 96 ] 97 }] 98 }); 99 100 // chart.addSeries({name:'北京',data: [216.4, 194.1, 95.6, 54.4, 29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5]}); 101 // 参数:数值;是否重绘; isShift; 是否动画 102 // chart.series[0].addPoint(18); 103 // chart.series[0].addPoint([12]); 104 // chart.series[0].addPoint([v.x, v.y]); 105 // 参数:是否重绘 106 // chart.series[0].remove(false); 107 // 更新饼图 108 // $('#id1').highcharts().series[0].data[0].update({x: 0, y: 100})