框架----Django框架知识点整理

一、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 ]
urls.py
 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
views.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 ]
urls
 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
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
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 ]
urls
 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
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
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
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
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)
View Code

四、数据获取多个数据时(注意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])     # 跨表取值时用的是下标    
View Code

五、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应用装饰器
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应用其它装饰器
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
csrf1.html
1 urlpatterns = [
2 
3     url(r'^csrf1.html', views.csrf1),
4 ]
urls.py
1 def csrf1(request):
2 
3     if request.method == 'GET':
4         return render(request,'csrf1.html')
5     else:
6         return HttpResponse('ok')
views.py

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
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中返回
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/")
View Code

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. 配置文件中:
            - 存储位置
            - 超时时间、每次刷新更新时间
session是什么

a. 简单示例

用户访问http://127.0.0.1:8000/login/
urlpatterns = [

    url(r'^index/', views.index),
    url(r'^login/', views.login),
]
urls
 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
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
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
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/')
views

十、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示例 演示
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
View Code

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 演示
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演示
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 演示
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 操作
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 ]
urls
 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
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
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'\xe8\xa6\x81\xe5\x8a\xa0\xe5\xaf\x86\xe5\x8a\xa0\xe5\xaf\x86\xe5\x8a\xa0sdfsd\t\t\t\t\t\t\t\t\t'
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
lib/utils.py
 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             width: '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="width: 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             width: '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>
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))
views

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)
XSS示例
 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)
基于__new__实现单例模式示例

 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)
View Code

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))
views
 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>
html

二十六、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.注册APP
 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 ]
2.注册路由
 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
3.编写ViewSet,视图函数
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
4.编写serializers,form验证以及数据库操作

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.URL
 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)
2.编写视图函数
 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
3.编写serializers

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.URL
 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)
2.视图函数
 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
3.编写serializers

d. 权限控制

1 REST_FRAMEWORK = {
2     'DEFAULT_PERMISSION_CLASSES': [
3         'permissi.MyPermission',
4     ]
5 }
1.settings配置文件
 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
2.权限控制

 

 

  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})
临时放一下

 

posted @ 2017-07-03 08:45  ForeverPine  阅读(469)  评论(0编辑  收藏  举报
TOP