• 框架----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'xe8xa6x81xe5x8axa0xe5xafx86xe5x8axa0xe5xafx86xe5x8axa0sdfsd									'
    35     data = result[0:-result[-1]]
    36     return str(data,encoding='utf-8')
    37 
    38 
    39 def auth():
    40     """
    41     API验证
    42     :return:
    43     """
    44     import time
    45     import requests
    46     import hashlib
    47 
    48     ctime = time.time()
    49     key = "asdfasdfasdfasdf098712sdfs"
    50     new_key = "%s|%s" %(key,ctime,)
    51 
    52     m = hashlib.md5()
    53     m.update(bytes(new_key,encoding='utf-8'))  #里面是字节数据
    54     md5_key = m.hexdigest()                    #返回值是字符窜类型
    55 
    56     md5_time_key = "%s|%s" %(md5_key,ctime)
    57 
    58     return md5_time_key
    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              '100%',       // 文本框宽度(可以百分比或像素)
    13             height: '300px',     // 文本框高度(只能像素)
    14             minWidth: 200,       // 最小宽度(数字)
    15             minHeight: 400      // 最小高度(数字)
    16         });
    17     }
    18 </script>

    5 详细参数

        http://kindeditor.net/docs/option.html

    6 上传文件示例

     1 <!DOCTYPE html>
     2 <html>
     3 <head lang="en">
     4     <meta charset="UTF-8">
     5     <title></title>
     6 </head>
     7 <body>
     8 
     9 <div>
    10     <h1>文章内容</h1>
    11     {{ request.POST.content|safe }}
    12 </div>
    13 
    14 
    15 <form method="POST">
    16     <h1>请输入内容:</h1>
    17     {% csrf_token %}
    18     <div style=" 500px; margin: 0 auto;">
    19         <textarea name="content" id="content"></textarea>
    20     </div>
    21     <input type="submit" value="提交"/>
    22 </form>
    23 
    24 <script src="/static/jquery-1.12.4.js"></script>
    25 <script src="/static/plugins/kind-editor/kindeditor-all.js"></script>
    26 <script>
    27     $(function () {
    28         initKindEditor();
    29     });
    30 
    31     function initKindEditor() {
    32         var a = 'kind';
    33         var kind = KindEditor.create('#content', {
    34              '100%',       // 文本框宽度(可以百分比或像素)
    35             height: '300px',     // 文本框高度(只能像素)
    36             minWidth: 200,       // 最小宽度(数字)
    37             minHeight: 400,      // 最小高度(数字)
    38             uploadJson: '/kind/upload_img/',
    39             extraFileUploadParams: {
    40                 'csrfmiddlewaretoken': '{{ csrf_token }}'
    41             },
    42             fileManagerJson: '/kind/file_manager/',
    43             allowPreviewEmoticons: true,
    44             allowImageUpload: true
    45         });
    46     }
    47 </script>
    48 </body>
    49 </html>
    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})
    临时放一下
  • 相关阅读:
    [HTTP2] HTTP1 probs and HTTP2 saves
    [HTTPS] MAN IN THE MIDDLE (MITM)
    [HTTP] HTTP Verb
    [Node.js] Creating JWTs (JSON Web Tokens) in Node
    [RxJS] Drag and Drop example
    [Webpack 2] Ensure all source files are included in test coverage reports with Webpack
    [Webpack 2] Add Code Coverage to tests in a Webpack project
    android简单的答题游戏
    Java Web----EL(表达式语言)详解
    使用ant构建报错,编码GBK的不可映射字符解决方法
  • 原文地址:https://www.cnblogs.com/wangyongsong/p/7095170.html
Copyright © 2020-2023  润新知