当前位置:   article > 正文

Django_相亲对象是问题学生

相亲对象是问题学生

'GET / HTTP/1.1 <-- 请求行
Host: 127.0.0.1:8001 <-- 请求头部
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.1.522660093.1520652325; csrftoken=gYuOvvynQQLeetX7Bxj6naEyQbOgH9pLBphdWvMTmK5nos3b8QZRhTA5y4DnQG3M

’ <-- 没有请求数据
day60 2018-04-27

  1. 今日内容

    1. 概括

      1. 98%的时间都是在写例子 帮你理解Django --> 由我们写的例子对比理解Django框架
      2. 安装Django
    2. 写例子

      用户的浏览器(socket客户端)
      3. 客户端往服务端发消息

       6. 客户端接收消息
       
       7. 关闭
      
      • 1
      • 2
      • 3

      JD的服务器(socket服务端)
      1. 启动,监听
      2. 等待客户端连接

       4. 服务端收消息
       5. 服务端回消息
       
       7. 关闭
      
      • 1
      • 2
      • 3
      • 4

      FTP作业:

       FTP客户端:  PUT,1024.avi,2048
       
       FTP服务端:  .split("|")
      
      • 1
      • 2
      • 3

      浏览器和服务端通信都要遵循一个HTTP协议(消息的格式要求).

      关于HTTP协议:
      1. 浏览器往服务端发的叫 请求(request)
      请求的消息格式:
      请求方法 路径 HTTP/1.1\r\n
      k1:v1\r\n
      k2:v2\r\n
      \r\n
      请求数据

       2. 服务端往浏览器发的叫 响应(response)
       	响应的消息格式:
       		HTTP/1.1 状态码 状态描述符\r\n
       		k1:v1\r\n
       		k2:v2\r\n
       		\r\n
       		响应正文   <-- html的内容
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    动态的网页:
    本质上都是字符串的替换
    字符串替换发生在什么地方:
    在服务端替换完再返回给浏览器!!!

    总结一下:
    1. web框架的本质:
    socket服务端 与 浏览器的通信
    2. socket服务端功能划分:
    a. 负责与浏览器收发消息(socket通信) --> wsgiref/uWsgi/gunicorn…

     	b. 根据用户访问不同的路径执行不同的函数
     	
     	c. 从HTML读取出内容,并且完成字符串的替换  --> jinja2(模板语言)
     	
     3. Python中 Web框架的分类:
     	
     	1. 按上面三个功能划分:
     		1. 框架自带a,b,c                 --> Tornado
     		2. 框架自带b和c,使用第三方的a    --> Django
     		3. 框架自带b,使用第三方的a和c    --> Flask
     	2. 按另一个维度来划分:
     		1. Django   --> 大而全(你做一个网站能用到的它都有)
     		2. 其他     --> Flask 轻量级
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 新建Django项目
      命令行创建:
      django-admin startproject mysite
      pycharm创建:
      1. File --> New project --> 左侧选Django --> 右侧填项目路径,并且勾选python.exe

    2. 设置Django项目:

      1. settings.py
        1. 配置HTML文件存放的位置
        2. 配置静态文件存放的位置
  2. 作业

    1. 用Django框架把我们之前写过登录的页面返回给浏览器
      day61 2018-04-28
  3. 内容回顾

    1. HTTP协议消息的格式:

      1. 请求(request)
        请求方法 路径 HTTP/1.1\r\n
        k1:v1\r\n
        …\r\n
        \r\n
        请求体 <-- 可以有,可以没有

      2. 响应(response)
        HTTP/1.1 状态码 状态描述符\r\n
        k1:v1\r\n
        Content-Type: text/html; charset=utf8\r\n
        \r\n
        响应正文 <-- HTML内容

    2. Python web框架的本质:
      a. 收发socket消息 --> 按照HTTP协议消息格式去解析消息

      b. 路径和要执行的函数的对应关系 --> 主要的业务逻辑

      c. 字符串替换 --> 模板(特殊符号 --> 数据)

    3. 一个完整得请求流程:

      1. 启动服务端,等待客户端(用户的浏览器)来连接
      2. 在浏览器地址栏输入URL,与服务端建立连接,浏览器发送请求
      3. 服务端收到请求消息,解析请求消息,根据路径和函数的对应关系,找到将要执行的函数
      4. 执行函数,打开HTML文件,进行字符串替换,得到一个最终要返回的HTML内容
      5. 按照HTTP协议的消息格式要求,把HTML内容回复给用户浏览器(发送响应)
      6. 浏览器收到响应的消息之后,按照HTML的规则渲染页面.
      7. 关闭连接
  4. Django昨日内容梳理:

    1. Django安装
      pip3 install django==1.11.11

      pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple/ django==1.11.11

      PyCharm安装的时候:
      注意不要勾选那个选项 (你们懂得)

    2. Django项目的启动:

      1. 命令行启动
        在项目的根目录下(也就是有manage.py的那个目录),运行:
        python3 manage.py runserver IP:端口–> 在指定的IP和端口启动
        python3 manage.py runserver 端口 --> 在指定的端口启动
        python3 manage.py runserver --> 默认在本机的8000端口启动

      2. PyCharm启动
        点绿色的小三角,直接可以启动Django项目(前提是小三角左边是你的Django项目名)

    3. 配置相关 项目名/settings.py文件

      1. Templates(存放HTML文件的配置) <-- 告诉Django去哪儿找我的HTML文件

      2. 静态文件(css/js/图片)

        静态文件保存目录的别名

        STATIC_URL = ‘/static/’

        所有静态文件(css/js/图片)都放在我下面你配置的文件夹中

        STATICFILES_DIRS = [
        os.path.join(BASE_DIR, “static”),
        ]

      3. 注释掉setting.py中 带有 csrf 的那一行(大概45~47行)

  5. 今日内容

    1. 登录的完整示例

    复习:
    form表单往后端提交数据需要注意哪三点: 五一回来默写 <-- 谁写错成from谁就请大家吃雪糕
    1. form不是from,所有获取用户输入的标签都应该放在form里面, 并且必须要有name属性
    2. action属性控制往哪儿提交,method一般都设置成post
    3. 提交按钮必须是type=submit,不能是别的类型

    1. GET请求和POST请求
      GET请求:
      1. 浏览器请求一个页面
      2. 搜索引擎检索关键字的时候

      POST请求:
      1. 浏览器向服务端提交数据,比如登录/注册等

    2. Django中的APP:
      什么是APP?以及为什么要用APP?

      project --> 项目 (老男孩教育大学校)

      APP --> 应用 (Linux学院/Python学院/大数据学院/Java学院)

      方便我们在一个大的Django项目中,管理实现不同的业务功能.

      1. 创建APP的命令
        1. 命令行,在Django项目的根目录输入:
          python3 manage.py startapp app名字
    3. ORM

    import pymysql
    pymysql.connect(


    )

    1. 不同的程序员写的SQL水平参差不齐
    2. 执行效率也参差不齐

    python语法 --自动翻译–> SQL语句

    jQuery DOM
    $("#d1") --自动翻译–> document.getElementById(“d1”)

    ORM:
    优点:
    1. 简单,不用自己写SQL语句
    2. 开发效率高
    缺点:
    1. 记忆你这个特殊的语法
    2. 相对于大神些的SQL语句,肯定执行效率有差距

    ORM的对应关系:
    类 —> 数据表
    对象 —> 数据行
    属性 —> 字段

    ORM能做的事儿:
    1. 操作数据表 --> 创建表/删除表/修改表
    操作models.py里面的类

     2. 操作数据行    --> 数据的增删改查
     	
     
     不能创建数据库,自己动手创建数据库
    
    • 1
    • 2
    • 3
    • 4

    使用Django的ORM详细步骤:
    1. 自己动手创建数据库
    create database 数据库名;
    2. 在Django项目中设置连接数据库的相关配置(告诉Django连接哪一个数据库)
    # 数据库相关的配置
    DATABASES = {
    ‘default’: {
    ‘ENGINE’: ‘django.db.backends.mysql’, # 连接的数据库类型
    ‘HOST’: ‘127.0.0.1’, # 连接数据库的地址
    ‘PORT’: 3306, # 端口
    ‘NAME’: “day61”, # 数据库名称
    ‘USER’: ‘root’, # 用户
    ‘PASSWORD’: ‘123456’ # 密码
    }
    }
    3. 告诉Django用pymysql代替默认的MySQLDB 连接MySQL数据库
    在项目/init.py文件中,写下面两句:
    import pymysql
    # 告诉Django用pymysql来代替默认的MySQLdb
    pymysql.install_as_MySQLdb()
    4. 在app下面的models.py文件中定义一个类,这个类必须继承models.Model
    class 类名(models.Model):

    5. 执行两个命令
    1. python3 manage.py makemigrations
    2. python3 manage.py migrate

    ORM单表的增加和查询:
    1. 查询
    models.UserInfo.objects.all()

     2. 增加
     	models.UserInfo.objects.create(name="张三")
    
    
     	day62 2018-05-02
    
    • 1
    • 2
    • 3
    • 4
    • 5
  6. 内容回顾
    Django
    1. 安装
    1. Django版本 1.11.xx
    2. 安装方式
    1. 命令行 --> Python环境(双版本,pip的使用)
    2. PyCharm安装
    2. 创建Django项目
    1. 创建方式
    1. 命令行创建方式
    1. cd到你要保存Django项目的目录
    2. Django-admin startproject 项目名 --> 会在当前目录创建Django项目
    2. PyCharm创建方式
    1. File --> new project --> …
    2. 创建完之后一定要选在新窗口打开!!!
    3. 配置Django项目
    1. settings.py文件
    1. templates文件夹的位置
    2. 静态文件
    1. STATIC_URL --> 静态文件夹的别名(在HTML文件中用的)
    2. STATICFILES_DIRS --> 静态文件夹的真正路径
    3. 注释掉 csrf 相关的中间件
    4. Django项目连接的数据库信息
    4. Django WEB请求流程(简版)
    1. 启动Django项目,等待用户连接
    2. 浏览器在地址栏输入URL,来连接我的Django项目
    3. 在urls.py中 找 路径和函数的 对应关系
    4. 执行对应的函数
    5. 返回响应
    5. views.py
    1. 专门用来定义处理请求的函数
    1. 基本必备三件套
    from django.shortcuts import HttpResponse, render, redirect
    1. HttpResponse(“要返回的内容”) --> 通常用于直接返回数据
    2. render(request, “html文件”, {“k1”: v1}) --> 返回一个HTML文件或者打开文件进行字符串替换
    3. redirect(“URL”) --> 告诉用户的浏览器去访问其他的URL

     		2. request相关
     			1. request.method     --> 查看请求的方法
     			2. request.POST       --> 获取POST请求的数据
     			
     6. ORM使用
     	1. 什么是ORM? 
     		是一种编程的方法论(模型), 和语言无关.(其他的语言也有类似的实现.)
     		
     	2. ORM的本质:
     		类    --->    数据表
     		对象  --->    数据行
     		属性  --->    字段
     		
     		按照规定的语法写,自动翻译成对应的SQL语句.
     		
     	3. ORM的功能:	
     		ORM操作数据表
     		ORM操作数据行
     		
     	4. Django里ORM的使用:
     		1. 手动创建数据库
     		2. 在settings.py里面,配置数据库的连接信息
     			DATABASES = {
     				'default': {
     					'ENGINE': 'django.db.backends.mysql',
     					'NAME': 'day62',
     					'HOST': '127.0.0.1',
     					'PORT': 3306,
     					'USER': 'root',
     					'PASSWORD': '123456',
     				}
     			}
     		3. 在项目/__init__.py告诉Django用pymysql模块代替MySQLdb来连接MySQL数据库
     			import pymysql
     			pymysql.install_as_MySQLdb()
     		4. 在app/models.py里面定义类
     			# 出版社
     			class Publisher(models.Model):
     				id = models.AutoField(primary_key=True)  # 自增的ID主键
     				# 创建一个varchar(64)的唯一的不为空的字段
     				name = models.CharField(max_length=64, null=False, unique=True)
     		5. 执行两个命令
     			1. python3 manage.py makemigrations   --> 把models.py里面的更改记录到小本本上
     			2. python3 manage.py migrate  --> 把更改翻译成SQL语句,去数据库执行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
  7. 今日内容

    1. GET请求和POST请求
      都属于HTTP协议规定的请求方法

    2. 什么时候用GET请求?

      1. 浏览器想要得到一个HTML页面的时候
      2. 搜索引擎查询关键字的时候 www.sogo.com/web/?query=迪丽热巴
    3. 什么时候用POST?

      1. 向后端提交数据
        1. 大段的数据
        2. 包含隐私的数据
        3. 上传文件
    4. 实际中GET和POST的应用场景

      1. GET:
        1. 直接在浏览器地址栏输入URL访问网站
        2. a标签
      2. POST:
        1. 登录注册
        2. 修改(新增)大段的数据
        3. 上传文件
  8. 今日作业

    1. 上课的删除和编辑功能自己独立写出来

    2. 组内讨论:

      1. 每个组员依次说一下Django的请求怎么走的?
    3. 用Bootstrap把课上的页面写一下

       		day63 2018-05-03
      
      • 1
  9. 内容回顾

    1. 单表的增删改查
      1. 删和改

        1. GET请求 URL传值

          1. 格式
            127.0.0.1:8000/delete_publisher/?name=alex&id=7
          2. Django后端取值
            request.GET --> 大字典
            request.GET[“name”]/request.GET[“id”] --> key不存在就报错了
            request.GET.get(“name”, “sb”) --> 推荐用这个方法取值
        2. 复习一下POST方法提交的数据怎么取:
          request.POST.get(“key”)

        3. ORM操作

          1. 删除

            1. 先找到对象,调用对象的.delete()方法
              publisher_obj = models.Publisher.objects.get(id=7)
              publisher_obj.delete()
              或者
              models.Publisher.objects.get(id=7).delete()
          2. 修改

            1. 找到对象,通过修改对象的属性来修改数据库中指定字段的值,要保存
              publisher_obj = models.Publisher.objects.get(id=7)
              publisher_obj.name = “新的出版社名字”
              publisher_obj.save() --> 把修改提交到数据库
      2. GET和POST

        1. GET请求:

          1. GET请求携带的数据都拼在了URL上
          2. GET请求携带的数据有长度限制 40k
        2. POST请求

          1. form表单提交数据
          2. 上传文件
        3. 几个GET请求具体的应用场景:

          1. 浏览器地址栏直接输入URL
          2. 点击a标签
          3. 搜索引擎检索
      3. request相关的知识点

        1. request.method
          1. GET
          2. POST
        2. request.POST --> 所有和post请求相关的数据
        3. request.GET --> 所有和GET请求相关的数据
  10. 今日内容

    1. 图书管理系统表结构设计
      图书管理系统的三种角色
      1. 出版社
      2. 书
      3. 作者
      总结关系:
      1. 一本书 只能 有一个出版社
      2. 一本书 能有 多个作者
      3. 一个作者 能写 多本书

       出版社和书: 一对多    --> 外键
       书和作者:   多对多    --> 用第三张表做关联
      
      • 1
      • 2

      表结构图在excel中:

    2. 查看书籍列表

    3. 添加书籍
      将所有的出版社在页面上以select标签的形式展示出来

    4. 删除书籍
      如何在后端获取要删除的是那一个书籍?
      通过URL传参数的形式

    5. 编辑书籍
      将所有的出版社在页面上以select标签的形式展示出来
      将当前编辑的书籍对象的书名和出版社在页面上展示出来

Queryset:

1 切片操作 Book.objects.all()[0:8]
2 迭代操作
for obj in Book.objects.all():
print(obj.属性)

3 惰性查询
ret=Book.objects.all()

	# for i in ret:
	#     print(i)
	#
	# Book.objects.create(title="java",publishDate="2012-12-12",price=12,publish_id=1)
	#
	# for i in ret:
	#     print(i)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4 缓存机制

    # ret=Book.objects.all().exists()
	# if ret:
	#     print("OK")


	# ret=Book.objects.all().iterator()
	# print(type(ret))
	# for i in ret:
	#     print(i)
	# Book.objects.create(title="hello2",publishDate="2012-12-12",price=12,publish_id=1)
	#
	# for i in ret:
	#     print(i)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

modle:
model_name=Book._meta.model_name
app_label=Book._meta.app_label
title=Book._meta.get_field(“title”)

print(title)
print(type(title))

print(title.max_length)

price=Book._meta.get_field("price")
print(price)
print(type(price))

print(price.max_digits)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

自定义分页

查看页面

分页
search
action

filter

pop

stark

分页
分页组件
保存搜索条件

search

action

filter:

        print("filter_field",filter_field) # "publish"
        filter_field_obj=self.config.model._meta.get_field(filter_field)
        print("filter_field_obj",filter_field_obj)
        print(type(filter_field_obj))
        from django.db.models.fields.related import ForeignKey
        from django.db.models.fields.related import ManyToManyField
        print("rel...",filter_field_obj.rel.to.objects.all())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

pop功能:

1 如何在一对多和多对多字段后渲染 +

2 +对应的跳转路径

3 保存添加记录同时,将原页面的对应的下拉菜单中添加该记录

11 crm
12 linux
13
14 crm
15 crm
16 crm
17 rest
18 rest
19 linux
20 rest

21 vue

25 vue

stark

1 注册模型表
2 设计URL
3 增删改 ----ModelForm
      ------pop
4 查看
      ------表头
	  ------表单数据
	  ------分页
	  ------search
	  ------action
	  ------filter
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

知识点:
django查找templates,先找本项目下的django查找templates,再找每一个注册app的django查找templates

CRM–

权限
stark
crm逻辑
  • 1
  • 2
  • 3

model:

class classList():

teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',related_name="abc")
tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes',)
  • 1
  • 2

form:

class classListForm():

teachers = models.ModelMutipleChoiceFiled(verbose_name='任课老师', to='UserInfo',related_name="abc")
tutor = models.ModelChoiceFiled(verbose_name='班主任', to='UserInfo', related_name='classes',)



渲染字段:
    teachers:  select
	            option: UserInfo.objects.all()
	            option: UserInfo.objects.filter(depart__in=[1002,1003])

   	tutor		select	
                option: UserInfo.objects.all()		
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

if

class Customer():
name=models.Charfield(max…)
gender = models.IntegerField(verbose_name=‘性别’, choices=[(1,“男”),(2,“女”)])

obj=Customer.objects.create(name=“alex”,gender=1)

print(obj.gender)
print(obj.get_gender_display()) # “男”

day70 2018-05-14

  1. 内容回顾

    1. ORM
      1. ORM常用字段和属性

        1. AutoField(primary_key=True)

        2. CharField(max_length=32)

        3. IntgerField()

        4. DateField()

        5. DateTimeField()

          1. auto_now_add --> 创建的时候自动填充当前时间
          2. auto_now --> 每次修改的时候自动把当前时间更新
      2. 关系字段

        1. ForeignKey(to=“类名”,related_name=“xx”) --> 1对多 ,外键通常设置在多的那一边、
        2. ManyToMany(to=“类名”,related_name=“xx”) --> 多对多,通常设置在正向查询多的那一边
      3. ORM一般操作

        1. 必知必会13条

          1. 返回QuerySet对象的
            1. all()
            2. filter()
            3. values()
            4. values_list()
            5. exclude()
            6. order_by()
            7. reverse()
            8. distinct()
          2. 返回具体对象的
            1. get()
            2. first()
            3. last()
          3. 返回布尔值的
            1. exists()
          4. 返回具体数值的
            1. count()
        2. 单表查询的双下划线

          1. models.Book.objects.filter(id__gt=1)
          2. models.Book.objects.filter(id__in=[1,2,3])
          3. models.Book.objects.filter(id__range=[1,5])
          4. models.Book.objects.filter(title__contains=“沙河”)
          5. models.Book.objects.filter(title__icontains=“沙河”)
          6. models.Book.objects.filter(title__startswith=“沙河”)
          7. models.Book.objects.filter(title__endswith=“沙河”)
          8. models.Book.objects.filter(publish_date__year=2017)
          9. models.Book.objects.filter(publish_date__month=2)
        3. 外键的跨表查询

          1. 正向查找

            1. 基于对象
              book_obj = models.Book.object.get(id=1)
              book_obj.publisher.name

            2. 基于双下划线的
              models.Book.object.filter(id=1).values(“publisher__name”)

          2. 反向查找(由出版社查书)

            1. 基于对象
              publisher_obj = models.Publisher.objects.get(id=1)
              默认反向查找的时候是表名加_set
              publisher_obj.book_set.all()
              如果在外键中设置了related_name=“books”
              publisher_obj.books.all()

            2. 基于双下划线
              models.Publisher.objects.filter(id=1).values(“book__title”)
              如果配置了related_query_name=“books”
              models.Publisher.objects.filter(id=1).values(“books__title”)

        4. 分组和聚合

          1. 聚合
            from django.db.models import Avg, Sum, Max, Min, Count
            models.Book.objects.all().aggregate(Avg(“price”))
          2. 分组
            book_list = models.Book.objects.all().annotate(author_num=Count(“author”))
        5. F和Q

          1. 当需要字段和字段作比较的时候用F查询
          2. 当查询条件是 或 的时候 用Q查询,因为默认的filter参数都是且的关系
        6. 事务

          1. 保证数据的原子性操作!!!
        7. 执行原生的SQL语句(了解即可)

  2. ORM 一对一

    1. 什么时候用一对一?
      当 一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁
      把不怎么常用的字段 单独拿出来做成一张表 然后用过一对一关联起来

    2. 优势
      既保证数据都完整的保存下来,又能保证大部分的检索更快

    3. ORM中的用法
      OneToOneField(to="")

  3. ORM 多对多的三种方式
    多对多的方式:
    1. ORM自动帮我创建第三张表

     2. 自己创建第三张表, 利用外键分别关联作者和书
     	关联查询比较麻烦,因为没办法使用ORM提供的便利方法
     	
     3. 自己创建第三张表,使用ORM 的ManyToManyFiled()
     	 使用此种方式创建多对多表的时候,没有 add() remove() 等方法
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我们应该用哪种?
    看情况:
    1. 如果你第三张表没有额外的字段,就用第一种
    2. 如果你第三张表有额外的字段,就用第三种或第一种

     相亲网站:
     	Boy
     		girls = ManyToManyField(to=“Girl")
     	
     	Girl
     	
     	约会记录:多对多
     		id  boy_id girl_id  date
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  4. ORM查询的练习题

    1. 跨表查询
    2. 跨多张表查询
  5. csrf简单用法

    什么是CSRF ?
    跨站请求伪造,

    问题:
    1. 钓鱼网站的页面和正经网站的页面对浏览器来说有什么区别? (页面是怎么来的?)
    钓鱼网站的页面是由 钓鱼网站的服务端给你返回的

     	正经网站的网页是由 正经网站的服务端给你返回的
     	
     	
     2. Django中内置了一个专门处理csrf问题的中间件
     	django.middleware.csrf.CsrfViewMiddleware
     	
     	这个中间件做的事情:
     		1. 在render返回页面的时候,在页面中塞了一个隐藏的input标签
     		
     		用法:
     			我们在页面上 form表单 里面 写上 {% csrf_token %}
     			
     		<input type="hidden" name="csrfmiddlewaretoken" value="8gthvLKulM7pqulNl2q3u46v1oEbKG7BSwg6qsHBv4zf0zj0UcbQmpbAdijqyhfE">
     		
     		2. 当你提交POST数据的时候,它帮你做校验,如果校验不通过就拒绝这次请求
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

作业:
1. 多对多的三种情况 自己整理下笔记
2. ORM查询练习
1. 正向查
2. 反向查
3. 跨表查
3. 预习

预习:
http://www.cnblogs.com/liwenzhou/p/8343243.html

day72 2018-05-16

  1. 内容回顾

    1. Cookie是什么
      保存在浏览器端的键值对

      为什么要有Cookie?
      因为HTTP请求是无状态的

      Cookie的原理?
      服务端可以在返回响应的时候 做手脚
      在浏览器上写入键值对(Cookie)

       浏览器发送请求的时候会自动携带该网站保存在我浏览器的键值对(Cookie)
      
      • 1

      Django 从请求携带的Cookie中取值:
      request.COOKIES.get(“is_login”)
      request.get_signed_cookie(key, default=None, salt=“xxx”)
      Django中设置Cookie:(针对的是响应对象)
      rep = HttpResponse()/render(request, "test.html)/redirect()
      rep.set_signed_cookie(key, value, salt=“xxx”, max_age=7)
      Django中删除Cookie:(注销)
      rep.delete_cookie(key)

    2. Session是什么
      Session保存在服务端的键值对

      Session依赖于Cookie

      dsadasdsadsafsjkndf: {“is_login”: 1, “name”: “xiaohei”, “age”:18}
      dsaasdaknfgreryywdf: {“is_login”: 1, “name”: “xiaobai”, “age”:20}
      wqrqrteknfgzddasqfg: {“is_login”: 0, “name”: “xiaohui”, “age”:48}

      给浏览器写入Cookie:
      sessionid:wqrqrteknfgzddasqfg

      1. 从用户发来的请求的Cookie中 根据 sessionid 取值, 取到 wqrqrteknfgzddasqfg
      2. 根据特殊字符串找到对应的 Session 数据 --> {“is_login”: 0, “name”: “xiaohui”, “age”:48}
      3. request.session.get(“is_login”) --> 从Session取值

      Django中设置Session:
      request.session[“is_login”] = 1
      request.session.set_expiry(7) # 设置超时时间 (Cookie和Session数据的)

       在settings.py中设置,每次请求都刷新Session超时时间
       SESSION_SAVE_EVERY_REQUEST = True 
      
      • 1
      • 2

      Django中删除Session:
      request.session.flush() 清除Cookie和Session数据

       request.session.clear_expired()  将所有Session失效日期小于当前日期的数据删除
      
      • 1
  2. 今日内容
    AJAX

    1. 预备知识 JSON

    2. 我们之前已经学过的发请求的方式:

      1. 直接在地址栏输入URL回车 GET请求
      2. a标签 GET请求
      3. form表单 GET/POST请求
      4. AJAX GET/POST请求
    3. AJAX 特点:

      1. 异步
      2. 局部刷新浏览器(偷偷发请求)
  3. 今日作业
    绝知此事要躬行!!!

  4. 检测用户名是否已经存在!

  5. 把Sweetalet插件

  6. 复习jQuery的内容

     day73 2018-05-17
    
    • 1
  7. 内容回顾

    1. 回顾了一下json数据格式
      1. JS对象 和 json数据格式的互相转换
      2. Python中数据 和 json数据格式的互相转换
    2. AJAX
      1. 我们前端往后端发请求的方式:

        1. 直接在地址栏输入URL
        2. a标签
        3. form表单
        4. AJAX

        HTTP请求的类型:
        GET
        POST

      2. AJAX特点:

        1. 异步
        2. 局部刷新(偷偷发请求)
      3. AJAX缺点:
        请求零碎,滥用对服务端压力大

      4. jQuery封装的AJAX方法:
        先导入 jquery.js

        $.ajax({
        url: “/test/”,
        type: “post”,
        data: {“key”: “value”, “key2”:[[1, 2, 3], [4, 5, 6]]},
        success: function(arg){
        // 请求得到响应的时候,自动执行这个回调函数
        console.log(arg);
        }
        })

  8. 今日内容

    1. form组件的介绍

    之前web开发的模式,以注册为例:
    1. 要有一个注册的页面,页面里面要有form表单 --> 生成HTML代码
    2. form表单要能提交数据到后端,后端要做有效性校验 --> 数据有效性校验
    3. 要把校验的提示信息展示在页面上 --> 校验信息返回并展示,保存原来填写的内容

     关于校验:
     	1. 前端通过JS代码做校验    --> 最好有
     	2. 后端做校验              --> 必须要有(因为前端的校验可以被跳过)
    
    • 1
    • 2
    • 3
    1. form组件的用法

      1. from django import forms
        2, 定义一个form类
        class RegForm(forms.Form):
        user = forms.CharField()
        pwd = forms.CharField()
        email = forms.EmailField()

      生成HTML:
      3. 实例化一个form对象, 传递到模板语言中
      4. 在目标语言中调用form对象的响应方法和属性

       三种方式:
       	1. {{ form_obj.as_p }}
       	2. 单独写
       		{{ form_obj.pwd.label }}
       		{{ form_obj.pwd }}
      
      • 1
      • 2
      • 3
      • 4
      • 5

      做校验:
      1. form_obj = RegForm(request.POST)
      2. form_obj.is_valid()

      内置的正则校验器的使用
      mobile = forms.CharField(
      label=“手机”,
      # 自己定制校验规则
      validators=[
      RegexValidator(r’1+ ′ , ′ 手 机 号 必 须 是 数 字 ′ ) , R e g e x V a l i d a t o r ( r ′ 1 [ 3 − 9 ] [ 0 − 9 ] 9 ', '手机号必须是数字'), RegexValidator(r'^1[3-9][0-9]{9} ,),RegexValidator(r1[39][09]9’, ‘手机格式有误’)
      ],
      widget=widgets.TextInput(attrs={“class”: “form-control”}),
      error_messages={
      “required”: “该字段不能为空”,
      }
      )

    看源码:

     form_obj.is_valid()都干了什么?
     
     
     self._errors = ErrorDict()  --> {}
     self.cleaned_data = {}     
    
     self.fields.items()
     	字段名  字段对象
     
     
     如果有错误:
     	self._errors["name"] = ""
     
     没有报错:
     	self.cleaned_data["name"] = value(用户填写的值)
     	
     注意:
     钩子函数(hook)的使用
     
     def clean_xx():
     	"""具体字段的自定义校验方法"""
     	pass
     
     def clean():
         """全局的自定义校验方法"""
     	pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

errors:

  • name
    • 不符合社会主义核心价值观!
  • __all__
    • 两次密码不一致
day74 2018-05-21

课程安排
周一:
中间件
auth模块+分析BBS项目需求(小组讨论把表结构设计出来)

  1. 今日内容
    中间件:http://www.cnblogs.com/liwenzhou/p/8761803.html

     1. URL的白名单 url = ["/xx/", "/oo/", "/haha/"]
     2. 登陆之后才能访问某些URL    之前使用装饰器
    
    • 1
    • 2

    中间件的定义:
    wsgi之后 urls.py之前 在全局 操作Django请求和响应的模块!

    中间件的使用:
    5个固定的方法
    process_request(self, request)
    执行顺序:
    按照注册的顺序(在settings.py里面设置中 从上到下的顺序)
    何时执行:
    请求从wsgi拿到之后
    返回值:
    返回None,继续执行后续的中间件的process_request方法
    返回response , 不执行后续的中间件的process_request方法

     	process_response
     		执行顺序:
     			按照注册顺序的倒序(在settings.py里面设置中 从下到上的顺序)
     		何时执行:
     			请求有响应的时候
     		返回值:
     			必须返回一个response对象
     			
     	process_view(self, request, view_func, view_args, view_kwargs):
     		执行顺序:
     			按照注册的顺序(在settings.py里面设置中 从上到下的顺序)
     		何时执行:
     			在urls.py中找到对应关系之后 在执行真正的视图函数之前
     		返回值:
     			返回None,继续执行后续的中间件的process_view方法
     			返回response,
     			
     			
     	process_exception(self, request, exception)
     		执行顺序:
     			按照注册顺序的倒序(在settings.py里面设置中 从下到上的顺序)
     		何时执行:
     			视图函数中抛出异常的时候才执行
     		返回值:
     			返回None,继续执行后续中间件的process_exception
     			返回response,
     			
     			
     			
     	process_template_response(self, request, response)
     		执行顺序:
     			按照注册顺序的倒序(在settings.py里面设置中 从下到上的顺序)
     		何时执行:
     			视图函数执行完,在执行视图函数返回的响应对象的render方法之前 
     		返回值:
     			返回None,继续执行后续中间件的process_exception
     			返回response,
    
    
     Django调用 注册的中间件里面五个方法的顺序:
     	1. process_request
     		urls.py
     	2. process_view
     		view
     	3. 有异常就执行 process_exception
     	4. 如果视图函数返回的响应对象有render方法,就执行process_template_response
     	5. process_response
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

Django已经学过的知识点:
1. Urls.py 路由系统:

	正则
		分组匹配     --> 位置参数
		分组命名匹配 --> 关键字参数
	
	分级路由
		include
	
	给路由起别名
		name="xx"
		
	反向解析url
		view
			from django.urls import reverse
			
			reverse("xx", args=[1, 2, 3])
			reverse("xx", kwargs={”k": "v"})
			
	自取其辱
	
2. 视图 views.py
	request
		request.method
		request.GET     --> URL里面的参数
		request.POST    --> post请求的数据
		
		request.path_info        --> 路径
		request.get_full_path()  --> 路径加路径的参数
	
	
	response
		新手必备3件套
		render(request, "xx.html", {“k”: "v", ...})
		HttpResponse("响应")
		redirect("/index/")
		redirect("http://www.luffycity.com")
		
		from django.http import JsonResponse
		JsonResponse()
		
		FBV和CBV
		
		函数装饰器和方法装饰器的区别
		
3. 模板
	
	filter
		内置的filter方法
		自定义的filter方法
		
	tag
		内置的tag
		自定义的simpleTag
		自定义的inclusionTag
		
	母版和继承
	
	{% extends ‘base.html’ %}
	
	{% block page-main %}
		{% block small %}
		{% endblock small %}
	{% endblock page-main %}
	
	
	组件 {% include nav %}
	
	
	静态文件相关的tag
	
	在模板语言里面反向解析url
	
		{% url 'url的别名' xx %}

	
4. ORM
	
	对应关系
		类   --> 数据表
		对象 --> 数据行
		属性 --> 字段
		
	
	Django连接MySQL数据库的步骤:
		1. 手动创建库
		2. 配置settings.py中数据库的连接信息
		3. 修改settings.py同目录下的__init__.py文件,添加两句
			import pymysql
			pymysql.install_as_MySQLdb()
		4. 在app下面的models.py中定义类,类一定要继承mdoels.Model
		5. 执行两句命令
			1. python manage.py makemigrations
			2. python manage.py migrate

	操作数据表
	
	操作数据行(增删改查)
		单表
		外键
		多对多
		一对一
		
	
	ORM高级:
		常用字段和方法
		必知必会13条
		神奇的双下划线
		跨表的正向查询反向查询
		
		F和Q
		
		聚合和分组
		
		事务
		
		执行原生的SQL语句

5. Cookie和Session,分页


6. AJAX
	
	$.ajax({
		url: “”,
		type: "post",
		data: {"k1": JSON.stringify([1,2,3])},
		success:function(data){
			
		}
	})
7. form表单

8. 中间件

	
		
		
		
day99
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138

1 CBV

2 APIView
class BookView(APIView):pass
url(r’^books/ ′ , v i e w s . B o o k V i e w . a s v i e w ( ) , n a m e = " b o o k s " ) , u r l ( r ′ b o o k s / ', views.BookView.as_view(),name="books"), url(r'^books/ ,views.BookView.asview(),name="books"),url(rbooks/’, View类下的view,name=“books”),
一旦访问books/: view(request)======APIView类下的dispatch()====请求方式对应的示例方法()

3 def dispatch():
#一 初始化操作
# (1) 构建新的request:
self.request=self.initial_request()
# self.request._request
# self.request.GET
# self.request.data
# (2) 执行组件
# 认证,权限,频率
# 认证:request.user
self.initial(request, *args, **kwargs)
==== # 认证组件
self.perform_authentication(request)
==== request.user
=====
for authenticator in self.authenticators: # [TokenAuth(),]
try:
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise

												if user_auth_tuple is not None:
													self._authenticator = authenticator
													self.user, self.auth = user_auth_tuple
													return
					
					
					# 权限组件
					self.check_permissions(request)
					   ===========
							 for permission in self.get_permissions():
									if not permission.has_permission(request, self):
										self.permission_denied(
											request, message=getattr(permission, 'message', None)
										)
					
					
					# 频率组件
					self.check_throttles(request)
					
					  =============
						for throttle in self.get_throttles():  # [VisitRateThrottle(),]
								if not throttle.allow_request(request, self):
									self.throttled(request, throttle.wait()) # 受限制
				   
					
   # 分发
	    if request.method.lower() in self.http_method_names:
			handler = getattr(self,request.method.lower(),
							  self.http_method_not_allowed)
	
		response = handler(request, *args, **kwargs)
		
		return response
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

4 序列化组件

class PublishSerializers(serializers.Serializer):
		name = serializers.CharField()
		email = serializers.CharField()
        		
class PublishModelSerializers(serializers.ModelSerializer):
		class Meta:
			model=Publish
			fields="__all__"

# queryset或者model对象-------------》json数据
ps=PublishSerializers(queryset,many=True)
ps.data # [{},{},{}]

ps=PublishSerializers(model_obj,many=False)
ps.data # {}


# json数据-------》记录
# 添加操作
ps=PublishSerializers(data=request.data)
if ps.is_valid():
   ps.save()  # create
   
# 更新操作

ps=PublishSerializers(model_obj,data=request.data)
if ps.is_valid():
   ps.save()  # update
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

5 视图组件
# 版本1:
# Book表
class BookView(APIView):

			def get(self,request):
				book_list=Book.objects.all()
				bs=BookModelSerializers(book_list,many=True,context={'request': request})
				return Response(bs.data)		
			def post(self,request):
				# post请求的数据
				bs=BookModelSerializers(data=request.data)
				if bs.is_valid():
					print(bs.validated_data)
					bs.save()# create方法
					return Response(bs.data)
				else:
					return Response(bs.errors)


		class BookDetailView(APIView):

			def get(self,request,id):

				book=Book.objects.filter(pk=id).first()
				bs=BookModelSerializers(book,context={'request': request})
				return Response(bs.data)

			def put(self,request,id):
				book=Book.objects.filter(pk=id).first()
				bs=BookModelSerializers(book,data=request.data)
				if bs.is_valid():
					bs.save()
					return Response(bs.data)
				else:
					return Response(bs.errors)

			def delete(self,request,id):
				Book.objects.filter(pk=id).delete()

				return Response()


# 版本2:mixIn

    from rest_framework import mixins
	from rest_framework import generics

	class AuthorView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
		queryset=Author.objects.all()
		serializer_class =AuthorModelSerializers

		def get(self,request, *args, **kwargs):
			return self.list(request, *args, **kwargs)
		def post(self,request, *args, **kwargs):
			return self.create(request, *args, **kwargs)


	class AuthorDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView):
		queryset = Author.objects.all()
		serializer_class = AuthorModelSerializers

		def get(self,request,*args, **kwargs):
			return self.retrieve(request,*args, **kwargs)

		def delete(self,request,*args, **kwargs):
			return self.destroy(request,*args, **kwargs)

		def put(self,request,*args, **kwargs):
			return self.retrieve(request,*args, **kwargs)
		
		
# 版本3:基于通用类
    from rest_framework import mixins
	from rest_framework import generics


	class AuthorView(generics.ListCreateAPIView):
		queryset=Author.objects.all()
		serializer_class =AuthorModelSerializers

	class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView):
		queryset = Author.objects.all()
		serializer_class = AuthorModelSerializers
        
# 版本4
 class AuthorModelView(viewsets.ModelViewSet):
		queryset = Author.objects.all()
		serializer_class = AuthorModelSerializers
		
 url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"),
 url(r'^authors/(?P<pk>\d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put"

 流程:
     url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"),
     url(r'^authors/$', ViewSetMixin.as_view({"get":"list","post":"create"}),name="author"),
     url(r'^authors/$', ViewSetMixin类下的view),
	 一旦访问 /authors/:
 		 ViewSetMixin
		 def  view():
            for method, action in actions.items(): # {"get":"list","post":"create"}
				handler = getattr(self, action)    # self.list  self.create
				setattr(self, method, handler)			
		             
            self.dispatch(request, *args, **kwargs)
        
		APIView类下的self.dispatch
	          # 分发
				if request.method.lower() in self.http_method_names:
					handler = getattr(self,request.method.lower(),
									  self.http_method_not_allowed)
			

				response = handler(request, *args, **kwargs) # self.list()
				
				return response
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

6 认证权限频率 组件

request.META:
    {'ALLUSERSPROFILE': 'C:\\ProgramData', 
	'APPDATA': 'C:\\Users\\Administrator\\AppData\\Roaming', 
	'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files', 
	'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files',
	'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 
	'COMPUTERNAME': 'PC201712041709',
	'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 
	'DJANGO_SETTINGS_MODULE': 'restdemo.settings', 
	'FP_NO_HOST_CHECK': 'NO', 'HOMEDRIVE': 'C:', 
	'HOMEPATH': '\\Users\\Administrator',
	'LOCALAPPDATA': 'C:\\Users\\Administrator\\AppData\\Local', 
	'LOGONSERVER': '\\\\PC201712041709', 
	'NUMBER_OF_PROCESSORS': '4', 'OS': 'Windows_NT',
	'PATH': 'C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\Scripts;C:\\Python27;E:\\MySQL Server 5.6\\bin;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\Scripts\\;C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\;C:\\Users\\Administrator\\AppData\\Local\\atom\\bin', 
	'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 
	'PROCESSOR_ARCHITECTURE': 'AMD64', 
	'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 60 Stepping 3, GenuineIntel',
	'PROCESSOR_LEVEL': '6', 'PROCESSOR_REVISION': '3c03', 
	'PROGRAMDATA': 'C:\\ProgramData',
	'PROGRAMFILES': 'C:\\Program Files',
	'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 
	'PROGRAMW6432': 'C:\\Program Files', 
	'PSMODULEPATH': 'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\', 
	'PUBLIC': 'C:\\Users\\Public', 'PYCHARM_HOSTED': '1', 'PYTHONIOENCODING': 'UTF-8', 
	'PYTHONPATH': 'C:\\Users\\Administrator\\PycharmProjects\\s9\\restdemo', 'PYTHONUNBUFFERED': '1', 
	'SESSIONNAME': 'Console', 'SYSTEMDRIVE': 'C:', 'SYSTEMROOT': 'C:\\Windows', 
	'TEMP': 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp', 'TMP': 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp',
	'USERDOMAIN': 'PC201712041709', 
	'USERNAME': 'Administrator', 
	'USERPROFILE': 'C:\\Users\\Administrator', 
	'WINDIR': 'C:\\Windows', 'WINDOWS_TRACING_FLAGS': '3', 
	'WINDOWS_TRACING_LOGFILE': 'C:\\BVTBin\\Tests\\installpackage\\csilogfile.log',
	'RUN_MAIN': 'true', 'SERVER_NAME': 'PC201712041709', 
	'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8000', 
	'REMOTE_HOST': '', 
	'CONTENT_LENGTH': '', 
	'SCRIPT_NAME': '', 
	'SERVER_PROTOCOL': 'HTTP/1.1', 
	'SERVER_SOFTWARE': 'WSGIServer/0.2', 
	'REQUEST_METHOD': 'GET', 
	'PATH_INFO': '/authors/', 
	'QUERY_STRING': 'token=8204b8e3ac40bf59ae480d17c146b51a', 
	'REMOTE_ADDR': '127.0.0.1', 
	'CONTENT_TYPE': 'text/plain', 
	'HTTP_HOST': '127.0.0.1:8000', 
	'HTTP_CONNECTION': 'keep-alive', 
	'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 
	'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 
	'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
	'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'HTTP_COOKIE': 'csrftoken=jtus3l4GJEc9TFXWYCWxkBIZprcOv7C1vFMIyOHs7Zkxt015FwVZ2KEEeDV6LOyN', 'wsgi.input': <_io.BufferedReader name=832>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

7 解析器-----数据解析器
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser
parser_classes = [JSONParser,FormParser]

8 路由控制
针对:
url(r’^authors/KaTeX parse error: Undefined control sequence: \d at position 113: …authors/(?P<pk>\̲d̲+)/’, views.AuthorModelView.as_view({“get”:“retrieve”,“put”:“update”,“delete”:“destroy”}),name=“detailauthor”),

     class AuthorModelView(viewsets.ModelViewSet):

			queryset = Author.objects.all()
			serializer_class = AuthorModelSerializers
			
			
			
     url(r'^books/$', views.BookModelView.as_view({"get":"list","post":"create"}),name="author"),
     url(r'^books/(?P<pk>\d+)/$', views.BookModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailbook"),
     
	 
   
     class AuthorModelView(viewsets.ModelViewSet):

			queryset = Author.objects.all()
			serializer_class = AuthorModelSerializers
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

9 分页

10 响应器 Response

day66 2018-05-08

  1. 内容回顾

    1. 模板系统(字符串替换)
      1. 语法

        1. 变量相关: {{ name }},{{name|length}},{{name|default:“默认值”}}
        2. 逻辑相关:
          1. if判断
            {% if a > b %}
            {% endif %}

            {% if a > b %}
            {% else %}
            {% endif %}

            {% if a > b %}
            {% elif %}
            {% else %}
            {% endif %}

          2. for循环

            1. for循环的基本用法:
              {% for i in name_list %}
              {{ i }}
              {% endfor %}

              {% for i in name_list %}
              {{ i }}
              {% empty %}
              空空如也
              {% endfor %}

            2. for循环可用的属性:
              forloop.counter
              forloop.counter0
              forloop.revcounter
              forloop.revcounter0

              forloop.first
              forloop.last

              forloop.parentloop --> 两层for循环,内层循环引用外层循环

      2. filter

        1. 常用的内置filter

          1. length
          2. filesizeformat --> 格式化文件大小的
          3. date:‘Y-m-d H:i:s’ --> 格式化时间的
          4. slice
          5. safe --> XSS攻击(跨站脚本攻击)
          6. truncatechars:20 --> 截取字符,超过的用…表示
          7. default
        2. 自定义的filter
          示例:
          1. addsb
          2. addstr
          具体的实现方式:
          1. 定义阶段
          1. 在app下面新建一个python的包:templatetags
          2. 在上面的Python包中新建一个Python文件,名字随意
          3. 在上述python文件中:
          from django import template

           		# 生成一个注册用的实例
           		register = template.Library()
           		# 定义并注册一个自定义的filter函数
           		@register.filter(name='addsb')
           		def add_sb(arg):
           			return "{} sb".format(arg)
           2. 调用阶段:
           	1. 在Django的模板文件中,导入刚才新建的python文件
           		{% load py文件名 %}
           	2. 按照filter的语法调用
           		{{ name|addsb }}
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
  2. 今日内容

    1. 母版和继承

      1. 为什么要有模板和继承:
        把多个页面公用的部分提取出来,放在一个 母版 里面。
        其他的页面只需要 继承 母版就可以了。

      2. 具体使用的步骤:

        1. 把公用的HTML部分提取出来,放到base.html文件中
        2. 在base.html中,通过定义block,把每个页面不同的部分区分出来
        3. 在具体的页面中,先继承母版
        4. 然后block名去指定替换母版中相应的位置
      3. 使用母版和继承的注意事项:

        1. {% extends ‘base.html’ %} --> 母版文件:base.html要加引号
        2. {% extends ‘base.html’ %}必须放在子页面的第一行!!!
        3. 可以在base.html中定义很多block,通常我们会额外定义page-css和page-js两个块
        4. view.py相应的函数中返回的是对应的子页面文件 不是不是不是 base.html
    2. 组件
      {% include ‘xxx.html’%}

    3. 静态文件的灵活写法

      1. {% load static %}
        {% static ‘jQuery-3.3.1.js’ %}
      2. {% get_static_prefix %}jQuery-3.3.1.js
    4. 自定义simple_tag和inclusion_tag

       		day67 2018-05-09
      
      • 1
  3. 内容回顾

    1. 模板语言(字符串替换)
      1. 母版和继承

        1. 什么时候用母版?
          html页面有重复的代码,把它们提取出来放到一个单独的html文件。
          (比如:导航条和左侧菜单)

        2. 子页面如何使用母版?
          {% extends ‘base.html’ %} --> 必须要放在子页面的第一行

          母版里面定义block(块),子页面使用block(块)去替换母版中同名的块

      2. 组件

        1. 什么时候用组件?
          重复的代码,包装成一个独立的小html文件。
        2. 如何使用?
          {% include ‘nav.html’ %}
      3. Django模板语言中关于静态文件路径的灵活写法

        1. 利用Django模板语言内置的static方法帮我拼接静态文件的路径
          {% load static %}
        2. 利用内置的get_static_prefix获取静态文件路径的别名,我们自行拼接路径
          {% load static %}
        3. as语法(一个路径多次用到,可以使用as保存到一个变量,后面就直接使用变量代替具体路径)
      4. 自定义的simple_tag
        比filter高级一点点
        它可以接受的参数个数大于2

      5. 自定义的inclusion_tag
        用来返回一段html代码(示例:返回ul标签)

        1. 定义阶段
          在app下面新建templatetags 文件夹(注意是Python包)
          新建一个py文件

          from django import template

          生成注册示例,名字必须是register

          register = template.Library()
          @register.inclusion_tag(“ul.html”)
          def show_ul(num):
          num = 1 if num < 1 else int(num)
          data = [“第{:0>3}号技师”.format(i) for i in range(1, num+1)]
          return {“data”: data}

        2. 调用阶段
          {% load xx %}
          {% show_ul 10 %}

  4. 今日内容

    1. 视图(接收请求返回响应那部分)

      1. CBV(class base view)和FBV(function base view)

      2. request对象

        1. 之前学过的
          1. request.method --> 获取请求的方法(GET、POST等)
          2. request.GET --> 通常用来获取URL里面的参数
            127.0.0.1:8000/edit_book/?id=1&name=yimi
            request.GET --> {“id”:1, “name”:“yimi”}
            request.GET.get(“id”)
          3. request.POST --> 用来获取POST提交过来的数据
            request.POST.get(“book_name”)
        2. 补充其他常用的:
          1. request.path_info --> 获取用户请求的路径(不包含IP和端口和URL参数)
          2. request.body
      3. response
        基础必备三件套(求学要严谨)

        1. HttpResponse --> 返回字符串内容

        2. render --> 返回一个html页面

        3. redirect --> 返回一个重定向(告诉浏览器再去访问另外的网址)

        4. JsonResponse

    2. 路由系统(urls.py) http://www.cnblogs.com/liwenzhou/p/8271147.html

      1. 正则表达式的模糊匹配
      2. 分组匹配 --> 相当于给视图函数传递位置参数
      3. 分组命名匹配 --> 相当于给视图函数传递关键字参数
        (两个不要混合使用)

---------------------------- 这里是坎 ------------------------------------

	4. 反向解析URL
		本质上就是给url匹配模式起别名,然后用过别名拿到具体的URL路径
		
		1. 怎么起别名?
			在url匹配模式中,定义name="别名"
		2. 如何使用?
			1. 在模板语言里面使用:
				{% url "别名" %}  --> 得到具体的URL路径
			2. 在视图中如何使用:
				from django.urls import reverse
				
				reverse("别名")  --> 得到具体的URL路径
		3. 如何传参数?
			1. 模板语言中:
				{% url "别名" 2018 "nb" %}
			2. 视图函数中
				传位置参数:
					reverse("别名", args=(2018, "nb"))
			
				传关键字参数:
					reverse("别名" kwargs={"year": 2018, "title": "nb"})
		4. namespace
			为了防止不同的app下面的url匹配模式有重复的别名
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  1. 今日作业

    1. 把之前图书管理系统的编辑和删除功能用url分组匹配的形式修改一下!

    2. 把编辑按钮的链接改成反向解析URL的形式

       	day68 2018-05-10
      
      • 1

来老男孩教育学习必经的四个阶段:
第一个阶段:信心满满(我一定能学会,我为啥学不会)
第二个阶段:自我怀疑(卧槽!还真不好学!)
第三个阶段:极其浮躁(卧槽!怎么还不毕业!这讲师连Django都讲不明白!)
第四个阶段:极其焦虑(卧槽!怎么要毕业了?我什么都不会,怎么找工作?)

永远不要高估自己!

  1. 内容回顾(赵导专场)

    1. ORM已经的学过的内容:
      1. Django项目如何使用ORM连接MySQL

        1. 手动创建数据库
        2. 在settings.py里面配置一下数据库的连接信息(告诉Django连接哪一个数据库)
          DATABASES = {
          ‘default’: {
          ‘ENGINE’: ‘django.db.backends.mysql’, # 连接数据库的类型
          ‘NAME’: ‘day62xiawu’, # 数据库名字
          ‘HOST’: ‘127.0.0.1’, # IP
          ‘PORT’: 3306, # 端口
          ‘USER’: ‘root’, # 用户名
          ‘PASSWORD’: ‘123456’, # 密码
          }
          }
        3. 在和settings.py同目录下的__init__.py文件中,告诉Django用pymysql代替MySQLdb来连接数据库
          import pymysql
          pymysql.install_as_MySQLdb()
        4. 在app/models.py中,定义类,类一定要继承models.Model
          class Book(models.Model):
          id = models.AutoField(primary_key=True)
          title = models.CharField(max_length=32)
        5. 执行两条命令
          1. 在哪儿执行?
            在项目的根目录(有manage.py文件的那个目录)

          2. 命令
            python manage.py makemigrations --> 将models.py文件中的改动记录在小本本(app/migrations/00xx_****.py)上

            python manage.py migrate --> 将改动翻译成SQL语句,去数据库中执行

      2. 表和表之间的关系

        1. 一对多(出版社和书)
          publisher = models.ForeignKey(to=“Publisher”)

          在数据库中:
          有没有publisher这个字段?
          数据库中实际 生成的是一个 publisher_id 字段

        2. 多对多(作者和书)
          books = models.ManyToManyField(to=“Book”)

          在数据库中:
          是通过第三张表建立的关系

      3. 增删改查操作

        1. 单表增删改查
          增:
          models.Publisher.objects.create(name=“沙河出版社”)
          查:
          models.Publisher.objects.get(id=1)
          models.Publisher.objects.get(name=“沙河出版社”)
          删:
          models.Publisher.objects.get(id=1).delete()
          改:
          obj = models.Publisher.objects.get(id=1)
          obj.name = “沙河第二出版社”
          obj.save()

        2. 外键的增删改查
          增、删、查同上

          book_obj = models.Book.objects.get(id=1)

          book_obj.publisher 是什么? *****
          和我这本书关联的出版社对象

           book_obj.publisher.id    和我这本书关联的出版社的id值
           book_obj.publisher.name  和我这本书关联的出版社的名称
          
          • 1
          • 2

          book_obj.publisher_id 是什么?
          和我这本书关联的出版社的id值

        3. 多对多操作

          1. 查id为1的作者都写过的书?
            author_obj = models.Author.objects.get(id=1)
            author_obj.books.all() --> 和我这个作者关联的所有书对象
          2. 想给作者绑定多本书?
            author_obj = models.Author.objects.get(id=1)
            author_obj.books.set([1,2,3]) --> 把id是1、2、3的书和我这个作者关联上
  2. 今日内容

     1. Django ORM常用字段:
     	1. AutoField       --> 自增
     	2. CharField       --> varchar(xx)
     	3. ForeignKey      --> 外键
     	4. ManyToManyField --> 多对多关联
     	
     	5. DateField
     	6. DateTimeField
     	
     	7. IntegerField
     	
     	
     2. 自定义char字段
     	class FixedCharField(models.Field):
     		"""
     		自定义的char类型的字段类
     		"""
     		def __init__(self, max_length, *args, **kwargs):
     			self.max_length = max_length
     			super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs)
    
     		def db_type(self, connection):
     			"""
     			限定生成数据库表的字段类型为char,长度为max_length指定的值
     			"""
     			return 'char(%s)' % self.max_length
    
     	
     	
     3. 常用的字段参数
     	1. null
     	2. default
     	3. unique
     	4. db_index
     	
     	5. DateField和DateTimeField才有的参数:
     		auto_now_add=True     --> 创建数据的时候自动把当前时间赋值
     		auto_add=True         --> 每次更新数据的时候更新当前时间
     		
     		上述两个不能同时设置!!!
     	
     	5. class Meta:
     		 db_table = "表名"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    day69 2018-05-11

  3. ORM增删改查操作
    http://www.cnblogs.com/liwenzhou/p/8660826.html

    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!
    见 : 课上代码 orm1.py文件!!!

    1. 单表增删改查

    2. 单表的双下划线操作

    3. 外键的跨表查询

      1. 正向查询

      2. 反向查询

    4. 多对多的跨表查询

      1. 正向查询

      2. 反向查询

    5. 分组和聚合

    6. F和Q

    7. 事务

    8. 执行原生SQL语句

饲养员 还让 老母猪 笑话着了。

作业:
把ORM查询操作多写几个例子!!!

后面的项目:
1. BBS 仿博客园 练手的
2. CRM --> 权限系统、Django admin、 Startk组件
3. 路飞学城 --> Django REST Framework(API) --> Vue(MVVM框架)
4. Flask --> 发布系统
5. 爬虫
6. 算法+金融那些
7. Linux
day94:

知识点1:

limit_choice_to={}

ModelForm
model:
teachers = models.ManyToManyField(verbose_name=‘任课老师’, to=‘UserInfo’,related_name=“abc”,limit_choices_to={“depart__in”:[1002,1005]})
form:
data=UserInfo.objects.filter(depart__in=[1002,1005]).valueslist(“pk”,“title”)
teachers = forms.ModelMultiChoiceField(choices=data)

知识点2:
if     

	class Customer(): 
		name=models.Charfield(max...)
		gender = models.IntegerField(verbose_name='性别', choices=[(1,"男"),(2,"女")])
		   
	obj=Customer.objects.create(name="alex",gender=1)	
		
	print(obj.gender)
	print(obj.get_gender_display())  # "男"

知识点3:
扩展URL:
      

            temp.extend(self.extra_url())
	 
	 
	 
	        def cancel_course(self,request,customer_id,course_id):
				print(customer_id,course_id)

				obj=Customer.objects.filter(pk=customer_id).first()
				obj.course.remove(course_id)
				return redirect(self.get_list_url())

			def extra_url(self):

				temp=[]

				temp.append(url(r"cancel_course/(\d+)/(\d+)",self.cancel_course))

				return temp
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

crm:

讲师与学生
    1 初始化  course_record,studyrecord,
	2 考勤
	3 录入成绩
	4 显示成绩 ajax 查询  




销售与客户

	day95
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

crm:

讲师与学生
    1 初始化  course_record,studyrecord,
	2 考勤
	3 录入成绩
	4 显示成绩 ajax 查询  
	
	5 上传作业(os模块)
	6 下载作业
	

销售与客户(销售)


---公共客户(公共资源)
   1 没有报名
   2 3天没有跟进
   3 15天没有成单
	

		mycustomer:
			
			 龙泰    男   yuan 2018-5-1     3天未跟进
		
		
		mycustomer:
			
			 龙泰    男   三江 2018-5-5      15天未成单
			 
			 
		mycustomer:
			
			 龙泰    男   暴雨 2018-5-21      正在跟进	 
		
		
		客户分布表
			龙泰    男   yuan 2018-5-1       3天未跟进
			龙泰    男   三江 2018-5-5       15天未成单
			龙泰    男   暴雨 2018-5-21      正在跟进	 
		
---我的客户
    crontab:

		2018-5-15 12:00 龙泰    男   三江 2018-5-5        正在跟进
		
		2018-5-16 0:0
		2018-5-17 0:0
		2018-5-18 0:0
		2018-5-19 0:0    龙泰    男   三江 2018-5-5       3天未跟进

   
key: CustomerDistrbute为什么创建 ,为什么不能直接用Customer













权限组件
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

day 96

CBV与FBV

restful协议

 ----  一切皆是资源,操作只是请求方式
 
 ----book表增删改查
     /books/                 books
	 /books/add/             addbook
	 /books/(\d+)/change/    changebook
	 /books/(\d+)/delete/    delbook
	 
----book表增删改查
     /books/     -----get            books      -----  返回当前所有数据
	 /books/     -----post           books      -----  返回提交数据 
	 
	 /books/(\d+)-----get            bookdetail -----  返回当前查看的单条数据 
	 /books/(\d+)-----put            bookdetail -----  返回更新数据 
	 /books/(\d+)-----delete         bookdetail -----  返回空
	 
	 	 
	 class  Books(View):
	      def get(self,request):
		      pass  # 查看所有书籍
			  
		  def post(self,request):
		      pass  # 添加书籍
			  
			  
	 class  BooksDetail(View):
	      def get(self,request,id):
		      pass  # 查看具体书籍
	 
	      def put(self,request,id):
		      pass  # 更新某本书籍
			  
		  def delete(self,request,id):
		      pass  # 删除某本书籍	  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

restframework(Django)

----针对数据:json


(1)Django的原生request:

	  浏览器   -------------  服务器
	  
	  "GET url?a=1&b=2 http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\n"
	  "POST url http/1.1\r\user_agent:Google\r\ncontentType:urlencoded\r\n\r\na=1&b=2"

	  request.body: a=1&b=2
	  request.POST:
				   if contentType:urlencoded:
						 a=1&b=2----->{"a":1,"b":2}

(2)restframework 下的APIView:

    


(3)
class PublishSerializers(serializers.Serializer):
		name=serializers.CharField()
		email=serializers.CharField()
		
		
	PublishSerializers(queryset,many=true)
	PublishSerializers(model_obj)
	
	
	
总结:
    1 reuqest类----源码
	
	2 restframework 下的APIView--源码
	
	  url(r'^books/$', views.BookView.as_view(),name="books")#  View下的view

	  books/一旦被访问: view(request) ------APIView: dispatch()
	
	3 def dispatch():
	
		  构建request对象
		  self.request=Request(request)
		  self.request._request
		  self.request.GET  # get
		  self.request.data # POST  PUT
	  
		  分发----if get请求:
				if request.method.lower() in self.http_method_names:
					handler = getattr(self, request.method.lower(),
									 self.http_method_not_allowed)
				else:
					handler = self.http_method_not_allowed   

				response = handler(request, *args, **kwargs) # self.get(request, *args, **kwargs)
				
				return response				
		
	4 序列化类
	    # from django.core import serializers
        # ret=serializers.serialize("json",publish_list)
	
	    restframework下的序列类  BookModelSerializers
		    将queryset或者model对象序列成一json数据
				bs=BookModelSerializers(book_list,many=True,context={'request': request})
				bs=BookModelSerializers(book,context={'request': request})
	   
	        还可以做校验数据,json-------》queryset/model-->记录
			
				bs=BookModelSerializers(data=request.data)
				if bs.is_valid():
					print(bs.validated_data)
					bs.save() # 重写create方法
	5 操作数据:
	
	    以Book表为例
		    class BookView(APIView):
			    # 查看所有书籍
				def get(self,request):
					book_list=Book.objects.all()
					bs=BookModelSerializers(book_list,many=True,context={'request': request})
					return Response(bs.data)
					
				# 添加一本书籍	
				def post(self,request):
					# post请求的数据
					bs=BookModelSerializers(data=request.data)
					if bs.is_valid():
						print(bs.validated_data)
						bs.save()# create方法
						return Response(bs.data)
					else:
						return Response(bs.errors)

			class BookDetailView(APIView):
                # 查看一本书籍
				def get(self,request,id):

					book=Book.objects.filter(pk=id).first()
					bs=BookModelSerializers(book,context={'request': request})
					return Response(bs.data)
                # 更新一本书籍
				def put(self,request,id):
					book=Book.objects.filter(pk=id).first()
					bs=BookModelSerializers(book,data=request.data)
					if bs.is_valid():
						bs.save()
						return Response(bs.data)
					else:
						return Response(bs.errors)
                # 删除某一本书籍
				def delete(self,request,id):
					Book.objects.filter(pk=id).delete()

					return Response()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116

restframework

1 APIView
2 序列组件
3 视图、
4 组件(认证权限频率)
5 数据解析器
6 分页和Response


					

	权限组件
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

1 项目与应用

2 什么是权限?

 一个包含正则表达式url就是一个权限


 who   what    how   ---------->True  or  Flase
 
 UserInfor
 
	 name       
	 pwd
	 permission=models.manytomany(Permission)
    
	
	name   pwd    
	egon   123            
	alex   456    
	A      111
	B      222
	C      333
	D      444
	
	
 Permission
 
    url=.....
  	title=....
	
id       url            title
1	 "/users/"         "查看用户"
2	 "/users/add/"     "添加用户"
3    "/customer/add"	"添加客户"
	 
 UserInfor_permission

    id
    user_id
    permission_id		
	 
	 
	id    user_id   permission_id
     1       1           1		
	 2       1           2
	 3       2           2
	 
	 4       3           1
	 5       3           2
	 6       3           3
	 
	 4       4           1
	 5       4           2
	 6       4          3
	 
	 
	 4       5           1
	 5       5           2
	 6       5           3
	 
	 
	 4       6           1
	 5       6           2
	 6       6           3
	 
	 
	 4       7           1
	 5       7           2
	 6       7           3
	 
	 
	 
	 
	 
示例:登录人:egon
      访问url:http://127.0.0.1:8000/users/	
	 
	  
	  def users(request):
         
		 user_id=request.session.get("user_id")
		 
		 
		 obj=UserInfor.objects.filter(pk=user_id).first()
		 obj.permission.all().valuelist("url")
		 
		 
		 
         return HttpResponse("users.....")
	 
	 
# 版本2:



UserInfor
 
	 name       
	 pwd
	 roles
	
    
	
	name   pwd    
	egon   123            
	alex   456    
	alex   456    
	alex   456    
	alex   456    
	alex   456    
	alex   456    
	alex   456    
	alex   456    
	
		
Role
   
   title=.......	   
   permissions=......
   
	 id   title
	 1   销售员
   

UserInfor2Role

   id     user_id    role_id	
    1        1          1

	
Permission
 
    url=.....
  	title=....
	
id       url            title
1	 "/users/"         "查看用户"
2	 "/users/add/"     "添加用户"
3    "/customer/add"	"添加客户"
	 

	 
	 
Role2Permission

id  role_id   permission_id	
 1      1	       1
 2      1	       2
 3      1	       3
	 
	 
	 
3  rbac(role-based access control) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149

关于rbac:

(1) 创建表关系:
    class User(models.Model):
		name=models.CharField(max_length=32)
		pwd=models.CharField(max_length=32)
		roles=models.ManyToManyField(to="Role")

		def __str__(self): return self.name

	class Role(models.Model):
		title=models.CharField(max_length=32)
		permissions=models.ManyToManyField(to="Permission")

		def __str__(self): return self.title

	class Permission(models.Model):
		title=models.CharField(max_length=32)
		url=models.CharField(max_length=32)

		def __str__(self):return self.title

(2) 基于admin录入数据


(3) 登录校验:
    
	if 登录成功:
	   
        查询当前登录用户的权限列表注册到session中

(4) 校验权限(中间件的应用)
    class ValidPermission(MiddlewareMixin):

		def process_request(self,request):

			# 当前访问路径
			current_path = request.path_info

			# 检查是否属于白名单
			valid_url_list=["/login/","/reg/","/admin/.*"]

			for valid_url in valid_url_list:
				ret=re.match(valid_url,current_path)
				if ret:
					return None


			# 校验是否登录

			user_id=request.session.get("user_id")

			if not user_id:
				return redirect("/login/")


			# 校验权限
			permission_list = request.session.get("permission_list",[])  # ['/users/', '/users/add', '/users/delete/(\\d+)', 'users/edit/(\\d+)']


			flag = False
			for permission in permission_list:

				permission = "^%s$" % permission

				ret = re.match(permission, current_path)
				if ret:
					flag = True
					break
			if not flag:
				return HttpResponse("没有访问权限!")

			return None
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

day83:

权限粒度控制

简单控制:
    {% if "users/add" in permissions_list%}


摆脱表控制


更改数据库结构
    class Permission(models.Model):
		title=models.CharField(max_length=32)
		url=models.CharField(max_length=32)

		action=models.CharField(max_length=32,default="")
		group=models.ForeignKey("PermissionGroup",default=1)
		def __str__(self):return self.title



	class PermissionGroup(models.Model):
		title = models.CharField(max_length=32)

		def __str__(self): return self.title


登录验证:
    permissions = user.roles.all().values("permissions__url","permissions__group_id","permissions__action").distinct()
    
    构建permission_dict

        permissions:
			[

			 {'permissions__url': '/users/add/', 
			 'permissions__group_id': 1, 
			 'permissions__action': 'add'}, 
			 
			 {'permissions__url': '/roles/', 
			 'permissions__group_id': 2, 
			 'permissions__action': 'list'}, 
			 
			 {'permissions__url': '/users/delete/(\\d+)', 
			 'permissions__group_id': 1, 
			 'permissions__action': 'delete'}, 
			 
			 {'permissions__url': 'users/edit/(\\d+)', 
			 'permissions__group_id': 1, 
			 'permissions__action': 'edit'}
			 ]
			 
        permission_dict


			 {
			 
			 1: {
			 'urls': ['/users/', '/users/add/', '/users/delete/(\\d+)', 'users/edit/(\\d+)'], 
			 'actions': ['list', 'add', 'delete', 'edit']}, 
			 
			 2: {
			 'urls': ['/roles/'],
			 'actions': ['list']}
			 
			 }



中间价校验权限:
    permission_dict=request.session.get("permission_dict")

    for item in permission_dict.values():
          urls=item['urls']
          for reg in urls:
              reg="^%s$"%reg
              ret=re.match(reg,current_path)
              if ret:
                  print("actions",item['actions'])
                  request.actions=item['actions']
                  return None

    return HttpResponse("没有访问权限!")
	
	
思考:
    菜单权限显示	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

原生form

forms组件

ChoiceField(Field)

ModelChoiceField(ChoiceField)

ModelMultipleChoiceField(ModelChoiceField)



1 针对form表单设计form组件
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

modelform

 class Book(models.Model):

	title=models.CharField(max_length=32)
	price=models.DecimalField(max_digits=8,decimal_places=2)  # 999999.99
	date=models.DateField()
	publish=models.ForeignKey("Publish")
	authors=models.ManyToManyField("Author")


class BookForm(forms.Form):
	title = forms.CharField(max_length=32,label="书籍名称")
	price = forms.DecimalField(max_digits=8, decimal_places=2,label="价格")  # 999999.99
	date = forms.DateField(label="日期",
		widget=widgets.TextInput(attrs={"type":"date"})
	)

	#gender=forms.ChoiceField(choices=((1,"男"),(2,"女"),(3,"其他")))
	#publish=forms.ChoiceField(choices=Publish.objects.all().values_list("pk","title"))
	publish=forms.ModelChoiceField(queryset=Publish.objects.all())
	authors=forms.ModelMultipleChoiceField(queryset=Author.objects.all())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

day85

上节回顾:

class BookForm(forms.Form):
   
    title=forms.CharField()
    price=forms.FloatField()
	

def add():
    if request.method=="POST":
	    form=BookForm(request.POST)
        if form.is_valid():
            pass

        else: 
            pass			
    #form=BookForm()
	return render(request,"add.html")


add.html:
    # 方案1
    <form action="">
		<p>名称<input type="text"name="title"></p>
		<p>价格<input type="text"name="price"></p>
		<input type="submit">
	</form>
	
	 # 方案2
	<form action="" method="post">
		  {% csrf_token %}
		  {% for field in form %}
			<div>
			 {{ field.label }}
			 {{ field }}
			</div>
		  {% endfor %}
		<input type="submit">
	</form>
	


######################################################
	
	
forms.ChoiceField(Field)      ----select
forms.ModelChoiceField(ChoiceField)  ----select
forms.ModelMultipleChoiceField(ModelChoiceField)  ----select multiple
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

跨域
jsonp
同源是指,协议,域名,端口相同。

cors
  • 1

admin配置

会议室预定

POST:

浏览器-------------------->server
“请求首行\r\nContent-Type:url_encode\r\n\r\na=1&b=2”
“请求首行\r\nContent-Type:application/json\r\n\r\n’{“a”:1,“b”:2}’”

在django的wsgi的request中:
request.body:元数据’{“a”:1,“b”:2}’

if 请求头中的Content-Type==url_encode:
    request.POST=解码a=1&b=2 
  • 1
  • 2

Q:

方式1:
q=Q()
q.connection="or"
q.children.append("pk",1)
q.children.append("user_id",1)
q.children.append("room_id",1)

Book.objects.filter(q)	


方式2:
Book.objects.filter(Q(pk=1)|Q(user_id=1)|Q(room_id=1))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

day74 下午 2018-05-21

  1. auth认证模块: http://www.cnblogs.com/liwenzhou/p/9030211.html

auth模块的知识点:
1. 创建超级用户
python manage.py createsuperuser

from django.contrib import auth

2. auth.authenticate(username=username, password=pwd)

	验证用户名和密码
	如果验证成功,得到的是一个用户对象
	如果验证失败,得到的是匿名用户
	
3. auth.login(request, user)
	将验证过的用户 赋值给 request.user属性
	
4. auth.logout(request)

	request.session.flush() 
		将session数据都删除,并且Cookie也失效
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  1. 如何扩展自带的auth_user表

    1. 新建一个表, 一对一关联上面的auth_user表

    2. 继承的方式

      from django.contrib.auth.models import AbstractUser

      class UserInfo(AbstractUser):
      phone = models.CharField(max_length=11)
      addr = models.CharField(max_length=128)
      相当于对默认的auth_user表做了扩展, 并且代替auth_user

      注意:
      在settings.py中一定要加
      AUTH_USER_MODEL = ‘app名.类名’

  2. BBS项目需求分析:

    1. 需要哪些表
      1. UserInfo

        1. username
        2. password
        3. avatar
      2. 文章表:
        title
        publish_date
        desc
        author
        详细内容 一对一关联 文章详情表

      3. 文章详情表
        info

      4. 评论表

        1. user
        2. 时间
        3. 内容
        4. 关联的文章
        5. 是谁的子评论
      5. 标签
        标签名
        和文章 多对多

      6. 分类
        分类名
        和文章的关联关系 多对多/一对多

      7. 点赞
        是赞还是踩
        文章
        谁点的 关联user

    day76 2018-05-23

  3. 滑动验证码补充说一下

极验科技

  1. 复习下form组件和文件上传

  2. BBS的注册功能

    day77 2018-05-24

  3. form组件梳理

    注册功能:
    1. 利用form组件生成HTML代码
    2. 使用AJAX提交数据,并且在页面显示错误信息
    3. 后端还是使用form做校验

    额外补充:
    滑动验证码
    前端预览头像

  4. 站点主页

    • Django admin简单使用

      1. 告诉admin 我有哪一些表

        1. 在app/admin.py文件中,把表注册一下
      2. 只有超级用户才能登陆admin管理后台

      3. blank=True 控制django admin 可以不填

      auth模块再讲解
      详见今天auth_demo示例代码

    • Bootstrap布局

      • 2 8 2布局

      • media的配置

    • ORM查询操作

      • 基于对象的查询
      • 基于QuerySet的查询

      当查询比写入操作多的时候,我们尽量减少跨表查询,节省时间。
      文章表的评论数据和点赞踩灭数据 是通过额外字段写在文章表里的

--------------------------------明天内容 ----------------------------

  1. 个人主页
    • 分组、聚合
    • extra() --> 执行SQL语句

day78 2018-05-25

  1. 复习下分组和聚合 https://www.cnblogs.com/liwenzhou/p/8660826.html

    1. 分组
      ORM中values或者values_list 里面写什么字段,就相当于select 什么字段

      ret = models.Employee.objects.all().values(“dept”, “age”)
      相当于:
      SELECT employee.dept, employee.age FROM employee LIMIT 21; args=()

    2. ORM中 annotate 前面是什么就按照什么分组!
      from django.db.models import Avg
      ret = models.Employee.objects.values(“province”).annotate(a=Avg(“salary”)).values(“province”, “a”)
      相当于:
      SELECT employee.province, AVG(employee.salary) AS a FROM employee GROUP BY employee.province ORDER BY NULL LIMIT 21; args=()

    3. extra --> 在执行ORM查询的时候执行额外的SQL语句

      查询person表,判断每个人的工资是否大于2000

      ret = models.Person.objects.all().extra(
      select={“gt”: “salary > 2000”}
      )
      相当于:
      SELECT (salary > 2000) AS gt, person.id, person.name, person.salary, person.dept_id FROM person LIMIT 21; args=()

    4. 直接执行原生的SQL语句,类似pymysql的用法
      from django.db import connection
      cursor = connection.cursor() # 获取光标,等待执行SQL语句
      cursor.execute(""“SELECT * from person where id = %s”"", [1])
      row = cursor.fetchone()
      print(row)

  2. 个人站点首页

    • 分组和聚合查询
      1. 文章分类

      2. 标签分类

      3. 日期归档

        1. MySQL内置的方法:date_format(字段名, “%Y-%m”)
        2. extra() --> 执行额外的原生SQL语句
          ret = models.Article.objects.filter(user=user).extra(
          select={“archive_ym”: “date_format(create_time,’%%Y-%%m’)”}
          ).values(“archive_ym”).annotate(c=Count(“nid”)).values(“archive_ym”, “c”)

sql:

子查询
join查询
分组查询(单表分组,多表分组)
  • 1
  • 2
  • 3

ORM:
跨表查询
翻译sql
Queryset.annotate() #
Publish.objects.all().annotate()

博客系统

个人站点(ORM查询------跨表查询与分组查询)

文章详细页

1 一次请求的完整流程

----response
----伴随着其他请求
  • 1
  • 2

2 render()到底渲染的什么?

作业1 一旦js文件变为静态文件,点赞的js代码如何重构
  • 1

3 json

4 点赞
作业2: 点赞流程

博客(2) ******

Xadmin(4)******
crm(3) ******

restframework (3) ******
vue(3) ******
路飞(5)******

(1 月)
flask
爬虫
linux

点赞

点赞或者评论者就是当前登录人

1 绑定事件
2 携带data={article_id,is_up}发送Ajax请求
3 对应的视图函数要生成一个赞或者灭记录
4 响应结果给ajax
5 Ajax的success处理

知识点:

什么是json?

+-------------------+---------------+
| Python            | JSON          |
+===================+===============+
| dict              |objects'{"":""}'|
+-------------------+---------------+
| list, tuple       | array[]        |
+-------------------+---------------+
| str               | string  '""'   |
+-------------------+---------------+
| int, float        | 'number'        |
+-------------------+---------------+
| True              | 'true '         |
+-------------------+---------------+
| False             | 'false'         |
+-------------------+---------------+
| None              | 'null'          |
+-------------------+---------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

user article_id is_up
1 1 True
1 1 False


  1. 0-9 ↩︎

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/619236
推荐阅读
相关标签
  

闽ICP备14008679号