'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文件
Templates(存放HTML文件的配置) <-- 告诉Django去哪儿找我的HTML文件
静态文件(css/js/图片)
STATIC_URL = ‘/static/’
STATICFILES_DIRS = [
os.path.join(BASE_DIR, “static”),
]
注释掉setting.py中 带有 csrf 的那一行(大概45~47行)
今日内容
复习:
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 %}
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\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='' 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': }
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
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\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
# 方案2
######################################################
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 ↩︎