赞
踩
'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
今日内容
概括
写例子
用户的浏览器(socket客户端)
3. 客户端往服务端发消息
6. 客户端接收消息
7. 关闭
JD的服务器(socket服务端)
1. 启动,监听
2. 等待客户端连接
4. 服务端收消息
5. 服务端回消息
7. 关闭
FTP作业:
FTP客户端: PUT,1024.avi,2048
FTP服务端: .split("|")
浏览器和服务端通信都要遵循一个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. 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 轻量级
新建Django项目
命令行创建:
django-admin startproject mysite
pycharm创建:
1. File --> New project --> 左侧选Django --> 右侧填项目路径,并且勾选python.exe
设置Django项目:
作业
内容回顾
HTTP协议消息的格式:
请求(request)
请求方法 路径 HTTP/1.1\r\n
k1:v1\r\n
…\r\n
\r\n
请求体 <-- 可以有,可以没有
响应(response)
HTTP/1.1 状态码 状态描述符\r\n
k1:v1\r\n
Content-Type: text/html; charset=utf8\r\n
\r\n
响应正文 <-- HTML内容
Python web框架的本质:
a. 收发socket消息 --> 按照HTTP协议消息格式去解析消息
b. 路径和要执行的函数的对应关系 --> 主要的业务逻辑
c. 字符串替换 --> 模板(特殊符号 --> 数据)
一个完整得请求流程:
Django昨日内容梳理:
Django安装
pip3 install django==1.11.11
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple/ django==1.11.11
PyCharm安装的时候:
注意不要勾选那个选项 (你们懂得)
Django项目的启动:
命令行启动
在项目的根目录下(也就是有manage.py的那个目录),运行:
python3 manage.py runserver IP:端口–> 在指定的IP和端口启动
python3 manage.py runserver 端口 --> 在指定的端口启动
python3 manage.py runserver --> 默认在本机的8000端口启动
PyCharm启动
点绿色的小三角,直接可以启动Django项目(前提是小三角左边是你的Django项目名)
配置相关 项目名/settings.py文件
今日内容
复习:
form表单往后端提交数据需要注意哪三点: 五一回来默写 <-- 谁写错成from谁就请大家吃雪糕
1. form不是from,所有获取用户输入的标签都应该放在form里面, 并且必须要有name属性
2. action属性控制往哪儿提交,method一般都设置成post
3. 提交按钮必须是type=submit,不能是别的类型
GET请求和POST请求
GET请求:
1. 浏览器请求一个页面
2. 搜索引擎检索关键字的时候
POST请求:
1. 浏览器向服务端提交数据,比如登录/注册等
Django中的APP:
什么是APP?以及为什么要用APP?
project --> 项目 (老男孩教育大学校)
APP --> 应用 (Linux学院/Python学院/大数据学院/Java学院)
方便我们在一个大的Django项目中,管理实现不同的业务功能.
ORM
import pymysql
pymysql.connect(
…
…
)
python语法 --自动翻译–> SQL语句
jQuery DOM
$("#d1") --自动翻译–> document.getElementById(“d1”)
ORM:
优点:
1. 简单,不用自己写SQL语句
2. 开发效率高
缺点:
1. 记忆你这个特殊的语法
2. 相对于大神些的SQL语句,肯定执行效率有差距
ORM的对应关系:
类 —> 数据表
对象 —> 数据行
属性 —> 字段
ORM能做的事儿:
1. 操作数据表 --> 创建表/删除表/修改表
操作models.py里面的类
2. 操作数据行 --> 数据的增删改查
不能创建数据库,自己动手创建数据库
使用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
内容回顾
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语句,去数据库执行
今日内容
GET请求和POST请求
都属于HTTP协议规定的请求方法
什么时候用GET请求?
什么时候用POST?
实际中GET和POST的应用场景
今日作业
上课的删除和编辑功能自己独立写出来
组内讨论:
用Bootstrap把课上的页面写一下
day63 2018-05-03
内容回顾
删和改
GET请求 URL传值
复习一下POST方法提交的数据怎么取:
request.POST.get(“key”)
ORM操作
删除
修改
GET和POST
GET请求:
POST请求
几个GET请求具体的应用场景:
request相关的知识点
今日内容
图书管理系统表结构设计
图书管理系统的三种角色
1. 出版社
2. 书
3. 作者
总结关系:
1. 一本书 只能 有一个出版社
2. 一本书 能有 多个作者
3. 一个作者 能写 多本书
出版社和书: 一对多 --> 外键
书和作者: 多对多 --> 用第三张表做关联
表结构图在excel中:
查看书籍列表
添加书籍
将所有的出版社在页面上以select标签的形式展示出来
删除书籍
如何在后端获取要删除的是那一个书籍?
通过URL传参数的形式
编辑书籍
将所有的出版社在页面上以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)
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)
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)
自定义分页
查看页面
分页
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())
pop功能:
1 如何在一对多和多对多字段后渲染 +
2 +对应的跳转路径
3 保存添加记录同时,将原页面的对应的下拉菜单中添加该记录
11 crm
12 linux
13
14 crm
15 crm
16 crm
17 rest
18 rest
19 linux
20 rest
25 vue
stark
1 注册模型表
2 设计URL
3 增删改 ----ModelForm
------pop
4 查看
------表头
------表单数据
------分页
------search
------action
------filter
知识点:
django查找templates,先找本项目下的django查找templates,再找每一个注册app的django查找templates
CRM–
权限
stark
crm逻辑
model:
class classList():
teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',related_name="abc")
tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes',)
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()
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
内容回顾
ORM常用字段和属性
AutoField(primary_key=True)
CharField(max_length=32)
IntgerField()
DateField()
DateTimeField()
关系字段
ORM一般操作
必知必会13条
单表查询的双下划线
外键的跨表查询
正向查找
基于对象
book_obj = models.Book.object.get(id=1)
book_obj.publisher.name
基于双下划线的
models.Book.object.filter(id=1).values(“publisher__name”)
反向查找(由出版社查书)
基于对象
publisher_obj = models.Publisher.objects.get(id=1)
默认反向查找的时候是表名加_set
publisher_obj.book_set.all()
如果在外键中设置了related_name=“books”
publisher_obj.books.all()
基于双下划线
models.Publisher.objects.filter(id=1).values(“book__title”)
如果配置了related_query_name=“books”
models.Publisher.objects.filter(id=1).values(“books__title”)
分组和聚合
F和Q
事务
执行原生的SQL语句(了解即可)
ORM 一对一
什么时候用一对一?
当 一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁
把不怎么常用的字段 单独拿出来做成一张表 然后用过一对一关联起来
优势
既保证数据都完整的保存下来,又能保证大部分的检索更快
ORM中的用法
OneToOneField(to="")
ORM 多对多的三种方式
多对多的方式:
1. ORM自动帮我创建第三张表
2. 自己创建第三张表, 利用外键分别关联作者和书
关联查询比较麻烦,因为没办法使用ORM提供的便利方法
3. 自己创建第三张表,使用ORM 的ManyToManyFiled()
使用此种方式创建多对多表的时候,没有 add() remove() 等方法
我们应该用哪种?
看情况:
1. 如果你第三张表没有额外的字段,就用第一种
2. 如果你第三张表有额外的字段,就用第三种或第一种
相亲网站:
Boy
girls = ManyToManyField(to=“Girl")
Girl
约会记录:多对多
id boy_id girl_id date
ORM查询的练习题
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. ORM查询练习
1. 正向查
2. 反向查
3. 跨表查
3. 预习
预习:
http://www.cnblogs.com/liwenzhou/p/8343243.html
day72 2018-05-16
内容回顾
Cookie是什么
保存在浏览器端的键值对
为什么要有Cookie?
因为HTTP请求是无状态的
Cookie的原理?
服务端可以在返回响应的时候 做手脚
在浏览器上写入键值对(Cookie)
浏览器发送请求的时候会自动携带该网站保存在我浏览器的键值对(Cookie)
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)
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
Django中设置Session:
request.session[“is_login”] = 1
request.session.set_expiry(7) # 设置超时时间 (Cookie和Session数据的)
在settings.py中设置,每次请求都刷新Session超时时间
SESSION_SAVE_EVERY_REQUEST = True
Django中删除Session:
request.session.flush() 清除Cookie和Session数据
request.session.clear_expired() 将所有Session失效日期小于当前日期的数据删除
今日内容
AJAX
预备知识 JSON
我们之前已经学过的发请求的方式:
AJAX 特点:
今日作业
绝知此事要躬行!!!
检测用户名是否已经存在!
把Sweetalet插件
复习jQuery的内容
day73 2018-05-17
内容回顾
我们前端往后端发请求的方式:
HTTP请求的类型:
GET
POST
AJAX特点:
AJAX缺点:
请求零碎,滥用对服务端压力大
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);
}
})
今日内容
之前web开发的模式,以注册为例:
1. 要有一个注册的页面,页面里面要有form表单 --> 生成HTML代码
2. form表单要能提交数据到后端,后端要做有效性校验 --> 数据有效性校验
3. 要把校验的提示信息展示在页面上 --> 校验信息返回并展示,保存原来填写的内容
关于校验:
1. 前端通过JS代码做校验 --> 最好有
2. 后端做校验 --> 必须要有(因为前端的校验可以被跳过)
form组件的用法
生成HTML:
3. 实例化一个form对象, 传递到模板语言中
4. 在目标语言中调用form对象的响应方法和属性
三种方式:
1. {{ form_obj.as_p }}
2. 单独写
{{ form_obj.pwd.label }}
{{ form_obj.pwd }}
做校验:
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(r′1[3−9][0−9]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
errors:
课程安排
周一:
中间件
auth模块+分析BBS项目需求(小组讨论把表结构设计出来)
今日内容
中间件:http://www.cnblogs.com/liwenzhou/p/8761803.html
1. URL的白名单 url = ["/xx/", "/oo/", "/haha/"]
2. 登陆之后才能访问某些URL 之前使用装饰器
中间件的定义:
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
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 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(r′books/’, 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
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
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
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'>}
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
9 分页
10 响应器 Response
day66 2018-05-08
内容回顾
语法
if判断
{% if a > b %}
{% endif %}
{% if a > b %}
{% else %}
{% endif %}
{% if a > b %}
{% elif %}
{% else %}
{% endif %}
for循环
for循环的基本用法:
{% for i in name_list %}
{{ i }}
{% endfor %}
{% for i in name_list %}
{{ i }}
{% empty %}
空空如也
{% endfor %}
for循环可用的属性:
forloop.counter
forloop.counter0
forloop.revcounter
forloop.revcounter0
forloop.first
forloop.last
forloop.parentloop --> 两层for循环,内层循环引用外层循环
filter
常用的内置filter
自定义的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 }}
今日内容
母版和继承
为什么要有模板和继承:
把多个页面公用的部分提取出来,放在一个 母版 里面。
其他的页面只需要 继承 母版就可以了。
具体使用的步骤:
使用母版和继承的注意事项:
组件
{% include ‘xxx.html’%}
静态文件的灵活写法
自定义simple_tag和inclusion_tag
day67 2018-05-09
内容回顾
母版和继承
什么时候用母版?
html页面有重复的代码,把它们提取出来放到一个单独的html文件。
(比如:导航条和左侧菜单)
子页面如何使用母版?
{% extends ‘base.html’ %} --> 必须要放在子页面的第一行
母版里面定义block(块),子页面使用block(块)去替换母版中同名的块
组件
Django模板语言中关于静态文件路径的灵活写法
自定义的simple_tag
比filter高级一点点
它可以接受的参数个数大于2
自定义的inclusion_tag
用来返回一段html代码(示例:返回ul标签)
定义阶段
在app下面新建templatetags 文件夹(注意是Python包)
新建一个py文件
from django import template
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}
调用阶段
{% load xx %}
{% show_ul 10 %}
今日内容
视图(接收请求返回响应那部分)
CBV(class base view)和FBV(function base view)
request对象
response
基础必备三件套(求学要严谨)
HttpResponse --> 返回字符串内容
render --> 返回一个html页面
redirect --> 返回一个重定向(告诉浏览器再去访问另外的网址)
JsonResponse
路由系统(urls.py) http://www.cnblogs.com/liwenzhou/p/8271147.html
---------------------------- 这里是坎 ------------------------------------
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匹配模式有重复的别名
今日作业
把之前图书管理系统的编辑和删除功能用url分组匹配的形式修改一下!
把编辑按钮的链接改成反向解析URL的形式
day68 2018-05-10
来老男孩教育学习必经的四个阶段:
第一个阶段:信心满满(我一定能学会,我为啥学不会)
第二个阶段:自我怀疑(卧槽!还真不好学!)
第三个阶段:极其浮躁(卧槽!怎么还不毕业!这讲师连Django都讲不明白!)
第四个阶段:极其焦虑(卧槽!怎么要毕业了?我什么都不会,怎么找工作?)
永远不要高估自己!
内容回顾(赵导专场)
Django项目如何使用ORM连接MySQL
在哪儿执行?
在项目的根目录(有manage.py文件的那个目录)
命令
python manage.py makemigrations --> 将models.py文件中的改动记录在小本本(app/migrations/00xx_****.py)上
python manage.py migrate --> 将改动翻译成SQL语句,去数据库中执行
表和表之间的关系
一对多(出版社和书)
publisher = models.ForeignKey(to=“Publisher”)
在数据库中:
有没有publisher这个字段?
数据库中实际 生成的是一个 publisher_id 字段
多对多(作者和书)
books = models.ManyToManyField(to=“Book”)
在数据库中:
是通过第三张表建立的关系
增删改查操作
单表增删改查
增:
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()
外键的增删改查
增、删、查同上
book_obj = models.Book.objects.get(id=1)
book_obj.publisher 是什么? *****
和我这本书关联的出版社对象
book_obj.publisher.id 和我这本书关联的出版社的id值
book_obj.publisher.name 和我这本书关联的出版社的名称
book_obj.publisher_id 是什么?
和我这本书关联的出版社的id值
多对多操作
今日内容
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 = "表名"
day69 2018-05-11
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文件!!!
单表增删改查
单表的双下划线操作
外键的跨表查询
正向查询
反向查询
多对多的跨表查询
正向查询
反向查询
分组和聚合
F和Q
事务
执行原生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
crm:
讲师与学生
1 初始化 course_record,studyrecord,
2 考勤
3 录入成绩
4 显示成绩 ajax 查询
销售与客户
day95
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 权限组件
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 # 删除某本书籍
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()
restframework
1 APIView
2 序列组件
3 视图、
4 组件(认证权限频率)
5 数据解析器
6 分页和Response
权限组件
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)
关于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
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("没有访问权限!") 思考: 菜单权限显示
原生form
forms组件
ChoiceField(Field)
ModelChoiceField(ChoiceField)
ModelMultipleChoiceField(ModelChoiceField)
1 针对form表单设计form组件
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())
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
跨域
jsonp
同源是指,协议,域名,端口相同。
cors
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
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))
day74 下午 2018-05-21
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也失效
如何扩展自带的auth_user表
新建一个表, 一对一关联上面的auth_user表
继承的方式
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名.类名’
BBS项目需求分析:
UserInfo
文章表:
title
publish_date
desc
author
详细内容 一对一关联 文章详情表
文章详情表
info
评论表
标签
标签名
和文章 多对多
分类
分类名
和文章的关联关系 多对多/一对多
点赞
是赞还是踩
文章
谁点的 关联user
day76 2018-05-23
滑动验证码补充说一下
极验科技
复习下form组件和文件上传
BBS的注册功能
day77 2018-05-24
form组件梳理
注册功能:
1. 利用form组件生成HTML代码
2. 使用AJAX提交数据,并且在页面显示错误信息
3. 后端还是使用form做校验
额外补充:
滑动验证码
前端预览头像
站点主页
Django admin简单使用
告诉admin 我有哪一些表
只有超级用户才能登陆admin管理后台
blank=True 控制django admin 可以不填
auth模块再讲解
详见今天auth_demo示例代码
Bootstrap布局
2 8 2布局
media的配置
ORM查询操作
当查询比写入操作多的时候,我们尽量减少跨表查询,节省时间。
文章表的评论数据和点赞踩灭数据 是通过额外字段写在文章表里的
--------------------------------明天内容 ----------------------------
day78 2018-05-25
复习下分组和聚合 https://www.cnblogs.com/liwenzhou/p/8660826.html
分组
ORM中values或者values_list 里面写什么字段,就相当于select 什么字段
ret = models.Employee.objects.all().values(“dept”, “age”)
相当于:
SELECT employee
.dept
, employee
.age
FROM employee
LIMIT 21; args=()
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=()
extra --> 在执行ORM查询的时候执行额外的SQL语句
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=()
直接执行原生的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)
个人站点首页
文章分类
标签分类
日期归档
sql:
子查询
join查询
分组查询(单表分组,多表分组)
ORM:
跨表查询
翻译sql
Queryset.annotate() #
Publish.objects.all().annotate()
博客系统
个人站点(ORM查询------跨表查询与分组查询)
—
文章详细页
1 一次请求的完整流程
----response
----伴随着其他请求
2 render()到底渲染的什么?
作业1 一旦js文件变为静态文件,点赞的js代码如何重构
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' | +-------------------+---------------+
user article_id is_up
1 1 True
1 1 False
0-9 ↩︎
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。