http协议: ( 基于TCP/IP通讯协议来传递数据(HTML 文件, 图片文件, 查询结果等)) HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写, 是用于从万维网(WWW:World Wide Web) 服务器传输超文本到本地浏览器的传送协议
HTTP是无链接:无链接的含义是限制每次链接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开链接。 采用这种方式能够节省传输时间。 HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据均可以经过HTTP发送。客户端 以及服务器指定使用适合的MIME-type内容类型。 HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺乏状态意味着若是后续处理须要前面 的信息,则它必须重传,这样可能致使每次链接传送的数据量增大。另外一方面,在服务器不须要先前信息时它的应答就较快
请求头 | 释义 | 例子 |
---|---|---|
Accept | 指定客户端可以接收的内容类型 | Accept : text / plain / text / html |
Cache-Control | 指定请求和响应遵循的缓存机制 | Cache-Control : no-cache |
Cookie | HTTP请求发送时,会把保存在该请求域名下的全部cookie值一块儿发送给web服务器 | Cookie: $Version=1; Skin=new; |
Content-Type | 请求的与实体对应的MIME信息 | Content-Type: application / x-www-form-urlencoded |
Host | 指定请求的服务器的域名和端口号 | 0.0.0.0 |
Referer | 先前网页的地址,当前请求网页紧随其后,即来路 | -www.zhihu-com |
User-Agent | 发起请求的用户的身份标识 |
GET:请求指定的页面信息,并返回实体主体 HEAD:相似于get请求,只不过返回的响应中没有具体内容,用于获取报头 POST:向指定的资源提交数据进行请求处理,数据被包含在请求体中,POST请求可能致使新的资源的创建或已有资源的修改 put:从客户端向服务器传送的数据取代指定的文档的内容 DELETE:请求服务器删除指定的内容 CONNECT:Http/1.1 协议中预留给能将链接改成管道方式的代理服务器 OPTIONS:容许客户端查看服务器的性能 TRACE:回显服务器收到的请求,主要用于测试和诊断
1xx:指示信息–表示请求已接收,继续处理。 2xx:成功–表示请求已被成功接收、理解、接受。 3xx:重定向–要完成请求必须进行更进一步的操做。 4xx:客户端错误–请求有语法错误或请求没法实现。 5xx:服务器端错误–服务器未能实现合法的请求
200 OK :客户端请求成功,通常用于GET和POST请求 400 Bad Request:客户端请求有语法错误,不能被服务器所理解。 301 Moved Permanently:永久移动,请求的资源已被永久移动到新url,返回信息会包含新的url,浏览器会自动定向到 新url 401 Unauthorized :请求未经受权,这个状态代码必须和WWW-Authenticate报头域一块儿使用。 403 Forbidden :服务器收到请求,可是拒绝提供服务。 404 Not Found :请求资源不存在,举个例子:输入了错误的URL。 500 Internal Server Error :服务器发生不可预期的错误。 502 Bad Gateway : 充当网关或代理的服务器,从远端接收到一个无效的请求 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
http : 超文本传输协议, 明文传输80端口 链接简单且是无状态的 https: 须要到ca申请证书, 要费用 具备安全性的ssl加密传输协议 端口是443 https协议是有ssl+http协议构建的可进行加密传输,身份认证的网络协议,安全
WebSocket是HTML5开始提供的一种在单个TCP链接上进行全双工通信的协议。 在WebSocket API中,浏览器和服务器只须要完成一次握手,二者之间就直接能够建立持久性的链接,并进行双向数据传输。 旧--不少网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,而后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器须要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费不少的带宽等资源。 新---HTML5定义的WebSocket协议,能更好的节省服务器资源和带宽,而且可以更实时地进行通信。浏览器经过 JavaScript 向服务器发出创建WebSocket链接的请求,链接创建之后,客户端和服务器端就能够经过TCP链接直接交换数据。
django实现websocket大体上有两种方式,一种channels,一种是dwebsocket。channels依赖于redis,twisted等,相比之下使用dwebsocket要更为方便一些。 安装: pip install dwebsocket 配置: # setting.py INSTALLED_APPS = [ ..….. ..….. ‘dwebsocket’, ] MIDDLEWARE_CLASSES = [ ..…..… ..…..… ‘dwebsocket.middleware.WebSocketMiddleware’ # 为全部的URL提供websocket,若是只是单独的视图须要能够不选 ] WEBSOCKET_ACCEPT_ALL=True # 能够容许每个单独的视图实用websockets
简单使用:
模拟文件下载的简单示例html
from dwebsocket.decorators import accept_websocket @accept_websocket def test(request): if not request.is_websocket(): # 判断是否是websocket链接 return render(request, 'websocket.html') else: download = Haproxy() t = threading.Thread(target=download.run) t.start() sent = [] while download.status: if len(download.res_dict) > len(sent): for i in download.res_dict.keys(): if i not in sent: sent.append(i) request.websocket.send(str(sent[-1]+str(download.res_dict[sent[-1]])).encode('utf-8')) # 发送消息到客户端 if not download.status: request.websocket.send('下载完成'.encode('utf-8'))
效果图:前端
详细:python
dwebsocket
有两种装饰器:require_websocket
和accept_websocekt
,使用require_websocket
装饰器会致使视图函数没法接收致使正常的http
请求,通常状况使用accept_websocket
方式就能够了,jquery
dwebsocket
的一些内置方法:nginx
request.is_websocket()
:判断请求是不是websocket
方式,是返回true
,不然返回false
request.websocket
: 当请求为websocket
的时候,会在request
中增长一个websocket
属性,WebSocket.wait()
返回客户端发送的一条消息,没有收到消息则会致使阻塞WebSocket.read()
和wait
同样能够接受返回的消息,只是这种是非阻塞的,没有消息返回None
WebSocket.count_messages()
返回消息的数量WebSocket.has_messages()
返回是否有新的消息过来WebSocket.send(message)
像客户端发送消息,message
为byte
类型使用JSONP Web页面上调用js的script脚本文件不受跨域影响 建立一个回调函数,而后在远程服务上调用这个函数而且将JSON 数据形式做为参数传递,完成回调 jquery中可使用jquery提供的getJSON方法来发送JSONP请求获取数据 (随机产生一个函数名随请求送到服务 器,服务器将JSON数据填充进回调函数,JSONP请求结束后执行回调函数) 缺点: 先后端都要支持,只能发个get请求 CORS解决跨域 处理简单请求: 只须要在返回的响应头中加上 Access-Control-Allow-Origin 字段.而且把该字段的值设置为 跨域请求的来源地址或简单的设置为 * 处理非简单请求:自定义一个中间件,在后端简单的给响应对象添加上 经常使用请求方法(PUT、DELETE)的支持 from django.utils.deprecation import MiddlewareMixin class CorsMiddleware(MiddlewareMixin): def process_response(self, request, response): # 给响应头加上 Access-Control-Allow-Origin 字段 并简单的设置为 * response['Access-Control-Allow-Origin'] = '*' if request.method == 'OPTIONS': # 容许发送 PUT 请求 response['Access-Control-Allow-Methods'] = 'PUT, DELETE' # 容许在请求头中携带 Content-type字段,从而支持发送json数据 response['Access-Control-Allow-Headers'] = 'Content-type' return response
CORS
解决方案,使用django-cors-headers
已封装, 在settings
文件中进行相关配置web
强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。 比较缓存,将缓存信息中的Etag和Last-Modified经过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。
Django Flask Toenado
wsgi server (好比uWSGI) 要和 wsgi application(好比django )交互,uwsgi须要将过来的请求转给django处理,那么 uWSGI 和 django 的交互和调用就须要一个统一的规范,这个规范就是WSGI WSGI(Web Server Gateway Interface) WSGI --- 全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口 WSGI 的官方定义是,the Python Web Server Gateway Interface。从名字就能够看出来,这东西是一个 Gateway,也就是网关。网关的做用就是在协议之间进行转换 WSGI 是做为 Web 服务器与 Web 应用程序或应用框架之间的一种低级别的接口
缓存是将一个或某个views的返回值保存至内存或者memcache等中,必定时间后当再有人来访问时候,则再也不去执行view中的操做,而是直接从内存或者redis中以前缓存的内容拿到,并返回 django中的6种缓存机制 开发调试 内存文件数据库 Memcache缓存(python-memcached模块) Memcache缓存(pylibmc模块) 另外: 基于redis实现的缓存 应用方面: 全站应用 单独视图的缓存 局部视图的应用
Django 信号 pre_save,预处理 models 若是一个 models 在保存到数据库以前,咱们须要对存入数据进行预处理,这时候咱们就须要pre_save。 pre_save 和 post_save 相似于 React 的生命周期,是针对 Django models 在保存(save())先后的钩子(hook),这两个方法可让咱们在 models 的保存先后,对数据或者其余内容进行一些处理。而这种钩子函数,在 Django 中被称之为 signal(信号)。 SlugField 构建语义化 url SlugField 本质上至关于存放字符串,可是在乎义上,主要用于把某些字段造成语义化的,能够访问的短网址(slug)字符串。
举例而言,假设有一个关于文章的 models,有两个字段,分别是标题 title 和短网址 slug。ajax
class Article(models.Model): title = models.CharField(max_length=100) slug = models.SlugField(max_length=40)
这时候存入models
的一条信息,title 是 The song of ice and fire
。若是咱们想用文章的标题做为 url
进行访问,完整的标题多是:redis
www.xxx.com/article/The song of ice and fire
可是url
是不能出现空格的,所以空格会被转变成%20
,最后网址获得sql
www.xxx.com/article/The%20song%20of%20ice%20and%20fire
咱们不但愿出现这么多难看的%20
,而是但愿用短横线 - 替代空格,获得数据库
www.xxx.com/article/the-song-of-ice-and-fire
而Django
的django.utils.text
提供了一个方法叫slugify
,能够把刚才的文章标题The song of ice and fire
作两个转变:
由于这种转变主要用于作url
拼接,因此咱们把这种结果都统一放在SlugField
字段里面,用以构建语义化的url
网址。
pre_save
+ slugify
构建SlugField
完整的代码以下示例:
slug
是惟一的字段,不能出现重复slug
,因此 SlugField
的属性是 unique=True
pre_save.connect(pre_save_post_receiver, sender=Post)
把Post
这个 models
以及自定义的处理函数pre_save_post_receiver
链接起来,表示在 Post
存储以前,先用该函数进行数据预处理。slug
,若是没有slug
,就把标题 title
用 slugify
转化成 slug
slug
,就把以前的 slug
对应的数据的id
拿过来,拼接在本次 slug
的后面。固然也能够用其余方法进行区分,避免重复。在models.py
from django.db import models from django.db.models.signals import pre_save from django.utils.text import slugify class Post(models.Model): # ... title = models.CharField(max_length=150) slug = models.SlugField(unique=True) def create_slug(instance): slug = slugify(instance.title) qs = Post.objects.filter(slug=slug).order_by("-id") exists = qs.exists() if exists: new_slug = "{0}-{1}".format(slug, qs.first().id) return new_slug return slug def pre_save_post_receiver(sender, instance, *args, **kwargs): if not instance.slug: instance.slug = create_slug(instance) pre_save.connect(pre_save_post_receiver, sender=Post)
Nginx+uwsgi nginx做为服务器最前端,负责接收client的全部请求,统一管理。静态请求由Nginx本身处理。 非静态请求经过uwsgi传递给Django,由Django来进行处理,从而完成一次WEB请求
user = Users.objects.order_by(‘id’) user = Users.objects.order_by(‘id’)[0:1] # 若是须要逆序 在字段前加负号 例 (‘-id’)
优势 : Memcached是Django原生支持的缓存系统,速度快,效率高 缺点 : 基于内存的缓存系统有个明显的缺点就是断电数据丢失
User.objects.filter().exclude(id=5) # 查询id不为5的用户
select * from company where title like "%abc%" or mecount>999 order by createtime desc; # desc表示的是降序 objects.filter(Q(title__contains='abc')|Q(mecount__gh=999)).order_by(-createtime)
http://www.baidu.com
到页面返回, 中间都是发生了什么 ?1. 浏览器向 DNS 服务器请求解析该 URL中的域名所对应的 IP 地址; 2. 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器创建TCP链接; 3. 浏览器发出读取文件(URL中域名后面部分对应的文件)的HTTP 请求,该请求报文做为 TCP 三次握手的 第三个报文的数据发送给服务器 4. 服务器对浏览器请求做出响应,并把对应的 html 文本发送给浏览器; 5. 释放 TCP链接,四次挥手; 6. 浏览器将该 html 文本并显示内容;
1.19 Django请求的生命周期
wsgi
—> 中间件 —> 路由 -–-–> 视图 —> 中间件 —> wsgi
经过Django中的信号去实现
中间件的概述: 中间件是一个轻量,低级别的的插件系统,用于在全局范围内改变django的输入和输出,实际做用就是在视图函数之执行以前后执行 以后作一些额外的操做。本质上是一个自定义类,类中定义几个方法,Django框架会在处理请求的特定的时间去执行这些方法 应用场景: 1. django项目中默认启用了csrf保护,每次请求时经过CSRF中间件检查请求中是否有正确的token值 2. 当用户在页面上发送请求时,经过自定义的认证中间件,判断用户是否已登陆,未登陆跳转登陆页面 3. 当有用户请求过来时,判断用户是否在白名单或者在黑名单里非同源策略中跨域问题,使用CORS解决跨域问题时候,须要本身定义中间件或者使用 django-cors-headers须要 在中间中进行配置 4. 当要全站使用缓存的情形,须要在中间件中进行配置 ..........
FBV:function base view 函数处理请求 经过在view.py里面定义一个函数,而后经过函数的request参数获取method的类型,而后根据提交的不一样方式进 行不一样的处理。 CBV:class base view 类处理请求 经过自定义一个子类继承这个类,咱们能够利用View里面的dispatch()方法来判断请求是get仍是post。 dispatch方法的本质是一个反射器,能够根据名字来调用同名的方法 注:子类里面能够从新定义了dispatch这个方法,同时使用super()来调用父类的构造方法,这样的好处是功能不变,可是能够灵活的添加新的功能 class Login(View): def dispatch(self, request, *args, **kwargs): print('before') obj = super(Login,self).dispatch(request, *args, **kwargs) print('after') return obj
from django.utils.decorators import method_decorator #将装饰器加在某个get/post的方法上 @method_decorator(xxx) def get(self, request): pass
#将装饰器加在本身定义的的dispatch方法上 @method_decorator(xxx) def dispatch(self, request, *args, **kwargs): pass
@method_decorator(xxx, name='post') @method_decorator(xxx, name='get') class AddPublisher(View): pass
# 或者能够在url上加装饰器 -- 会为类视图中的全部请求方法都加上装饰器行为 urlpatterns = [ url(r'^demo/$', xxx(DemoView.as_view())) ]
多个数据库
python manage.py makemigrations
python manage.py migrate -- database db2 //settings
配置多个数据库
读写分离
s = models.Student.objects.using('default').all() models.Student.objects.using('db2').create(name='xxx',)
# myrouter class Router: def db_for_read(self, model, **kwargs): return 'default' def db_for_write(self, model, **kwargs): return 'db2'
settings
中配置
DATABASE_ROUTERS = ['myrouter.Router']
一主多从
# 一主多从 import random class Router: def db_for_read(self, model, **kwargs): return random.choices(['db1', 'db2', 'db3']) def db_for_write(self, model, **kwargs): return 'db'
分库分表
# 分库分表 # app01 db1 app02 db2 class Router: def db_for_read(self, model, **kwargs): if model._meta.app_label == 'app01': return 'db1 ' elif model._meta.app_label == 'app02': return 'db2' def db_for_write(self, model, **kwargs): if model._meta.app_label == 'app01': return 'db1 ' elif model._meta.app_label == 'app02': return 'db2'
---------必知必会13条---------- # 获取对象列表 all() -- 获取全部数据 (对象列表) filter() -- 获取知足条件的全部对象(对象列表)# 获取一个对象,没有或者是多个的时候会报错 exclude() -- 获取不知足条件的全部对象 (对象列表) values() -- 获取对象的字段名和值 values_list() -- 获取对象的值 order_by() -- 排序,默认升序,加 - 降序 (指定多个排序,按第一个升序,遇到相同时候再使用第二个) reverse() -- 给已经排好序的结果倒叙排序 --> 前提是得使用order_by后 distinct() -- 会对彻底相同的内容去重(但不是某一字段相同就去重) # 获取对象: get() first() -- 取第一个 last() -- 最后一个 # 数字 count() -- 计数 # 布尔值 exists() -- 判断是否存在,返回bool
---------单表双下划线---------- __gt 大于 __gte 大于等于 __lt 小于 __lte 小于等于 __isnull 为空 __in =[ ] 在列表中的全部对象 __range=[1,10] 字段值的范围,左右都包含 __contains 包含某一字母 __icontains 大小写都会包含 __startswith 以..开头 __istartswith 以..开头,忽略大小写 __endswith 以..结尾 __isendswith 以..结尾,忽略大小写
# ---------外键操做---------- # 描述多对一的关系 class Publisher(models.Model): name = models.CharField(max_length=32) class Book(models.Model): publisher=models.ForeignKey( 'Publisher', on_delete=models.CASCADE, related_name='books ) # --------------------------- # 基于对象的查询 # 正向查询 -> 有外键的一侧,查关联对象 book_obj = models.Book.objects.get(id =1) # book_obj.publisher -> 关联的对象 # book_obj.publisher_id -> 关联对象的id # book_obj.publisher.id -> 关联对象的id # 反向查询 被关联对象,查有外键的一侧 publiser_obj = models.Publisher.objects.get(id=1) # publisher_obj.book_set -> 管理对象 (全部书籍) # publisher_obj.book_set.all() -> 出版社所管理的全部书籍对象 (全部书籍) # 另外:当指定 relate_name = books" publisher_obj.books ->管理对象 (全部书籍) # 基于字段的查询 models.Book.objects.filter(publisher__name ='xxxx')
#---------多对多---------- 方式一 class Author(): name = models.CharField(max_length=32) books = models.ManyToManyField('Book') 方式二 class Author(models.Model): name = models.CharField(max_length=32) class Author_Book(models.Model): author = models.ForeignKey('Author') book = models.ForeignKey('Book') date = models.DateTimeField() 方式三 class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book', through='Author_Book') class Author_Book(models.Model): author = models.ForeignKey('Author') book = models.ForeignKey('Book') date = models.DateTimeField() # ----------- 查询方法 -------------- # 基于对象的查询 # 正向查询: author_obj = models.Author.objects.get(id=2) # author_obj.books -—> 管理对象 # author_obj.books.all() --> 该做者写的全部书籍对象 # 反向查询 book_obj = models.Book.objects.get(id=2) # 不指定 related_name ='authors' # print(book_obj.author_set.all()) # 指定related_name ='authors' # print(book_obj.authors.all()) ##[<Author: Author object>, <Author: Author object>]> 由于做者没有定义str方法## # --------------- 其余方法 ------------ # set 设置多对多关系 # 所有从新设置id= 2 的三条数据所有清空 author_obj.books.set([]) author_obj.books.set([1,2]) # y要关联对象的id (就是给id为1和id为2 的两本书设置多对多) # add 添加对对多关系 author_obj.books.add(3) # 要关联对象的id author_obj.books.add(models.Book.objects.get(id=3))# 要关联的对象 # remove 删除多对多的关系 author_obj.books.remove(3) # 要关联对象的id author_obj.books.remove(models.Book.objects.get (id=2)) # 要关联的对象 # clear() # 清空当前(id=2也就是author_obj对象)的多对多的关系 author_obj.books.clear() # create() author_obj.books.create(title='楚留香传奇') book_obj.authors.create(name='古龙2')
F
的做用 ?from django.db.models import F # 动态获取字段的值, 能够在一条记录中比较两个字段的value # 查询库存大于50的书籍 ret = models.Book.objects.filter(store__gt=50).values() # for i in ret: # print(i) # 第一种用法,动态的获取想要获取的字段 (能够比较两列的值) # 获取库存大于售出的书籍 ret2 = models.Book.objects.filter(store__gt=F('sale')).values() for i in ret2: print(i) # 第二种用法 (使用update更新) # 库存不变时候,售出数量乘2 models.Book.objects.all().update(sale=F('sale')*2) # 注: update 和更新后使用save的区别 # update 它能够更新指定字段,能够是多个, 然后者会将全部的字段作更新
Q
的做用 ?from django.db.models import Q ret = models.Book.objects.filter(Q(~Q(id__lt=3) | Q(id__gt=5))&Q(id__lt=4)) print(ret) # ~ 取反 # | 或 # & 与 AND
在Django中使用原生Sql主要有如下几种方式: extra:结果集修改器,一种提供额外查询参数的机制(依赖model) raw:执行原始sql并返回模型实例(依赖model) 直接执行自定义sql(不依赖model)
# -------使用extra -------- Book.objects.filter(publisher__name='广东人员出版社').extra(where=['price>50']) Book.objects.filter(publisher__name='广东人员出版社',price__gt=50) Book.objects.extra(select={'count':'select count(*) from hello_Book'})
#---------使用raw ---------- Book.objects.raw('select * from hello_Book') Book.objects.raw("insert into hello_author(name) values('测试')") rawQuerySet为惰性查询,只有在使用时生会真正执行
#--------自定义查询 ---------- 执行自定义sql: from django.db import connection cursor=connection.cursor() # 插入操做 cursor.execute("insert into hello_author(name) values('郭敬明')") # 更新操做 cursor.execute('update hello_author set name='abc' where name='bcd'') # 删除操做 cursor.execute('delete from hello_author where name='abc'') # 查询操做 cursor.execute('select * from hello_author') raw=cursor.fetchone() # 返回结果行游标直读向前,读取一条 cursor.fetchall() # 读取全部
only(field) : 定义须要的字段 (id保留) defer(field): 排除不须要的字段 (id保留)
在数据库有外键的时候,使用select_related()和prefetch_related()能够很好的减小数据库请求的次数,从而提升性能. select_related() 对于一对一字段(OneToOneField)和外键字段(ForeignKey),可使用select_related()来QuerySet进行优化.在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在以后须要的时候没必要再查询数据库了。 select_related经过多表join关联查询,一次性得到全部数据,只执行一次SQL查询 prefetch_related分别查询每一个表,而后根据它们之间的关系进行处理,执行两次查询
values 字典列表,ValuesQuerySet查询集 <QuerySet [ {'id': 2, 'name': '做者2', 'age': 24}, {'id': 3, 'name': '做者3', 'age': 35}] > values_list 返回元祖列表,字段值 <QuerySet [ (2, '做者2', 24), (3, '做者3', 35)] >
objs_list = [] for i in range(100): obj = People('name%s'%i,18) # models里面的People表 objs_list.append(obj) # 添加对象到列表 People.objects.bulk_create(objs_list,100) # 更新操做
form 生成页面可用的HTML标签 | 对用户提交的数据进行校验 | 保留上次输入内容 Model Form 利用 Django 的 ORM 模型model建立Form(表单跟model关系密切)
在使用选择标签时,须要注意choices的选项能够从数据库中获取,可是因为是静态字段获取的值没法实时更新,那么须要自定义构造方法从而达到此目的。
# 重写构造函数 from django.forms import Form from django.forms import widgets from django.forms import fields class MyForm(Form): user = fields.ChoiceField( # choices=((1, '上海'), (2, '北京'),), initial=2, widget=widgets.Select) def __init__(self, *args, **kwargs): super(MyForm,self).__init__(*args, **kwargs) # self.fields['user'].choices = ((1, '上海'), (2, '北京'),) # 或 self.fields['user'].choicesmodels.Classes.objects.all().values_list('id','caption') # 利用ModelChoiceField字段,参数为queryset对象 from django import forms from django.forms import fields from django.forms import models as form_model class FInfo(forms.Form): authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all()) # 多选 # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all()) # 单选
class Author(models.Model): author = models.CharField(max_length=250) class Books(models.Model): book = models.ForeignKey(Author,on_delete=models.CASCADE) # CASCADE:删除做者信息一并删除做者名下的全部书的信息; # PROTECT:删除做者的信息时,采起保护机制,抛出错误:即不删除Books的内容 # SET_NULL:只有当null=True才将关联的内容置空; # SET_DEFAULT:设置为默认值; # SET():括号里能够是函数,设置为本身定义的东西; # DO_NOTHING:字面的意思,啥也不干,你删除你的干我毛线
第一步:django第一次响应来自某个客户端的请求时,后端随机产生一个token值,把这个token保存在SESSION状态中;同时,后端把这个token放到cookie中交给前端页面; 第二步:下次前端须要发起请求(好比发帖)的时候把这个token值加入到请求数据或者头信息中,一块儿传给后端;Cookies: {csrftoken:xxxxx} 第三步:后端校验前端请求带过来的token和SESSION里的token是否一致。
// 在HTML页面中使用 {% csrf_token %},给POST提交数据中添加 csrfmiddlewaretoken的键值对 data :{ 'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val(), i1:$('[name="i1"]').val(), i2:$('[name="i2"]').val() },
// 在HTML页面中使用 {% csrf_token %},在ajax中添加X-csrftoken的请求头 headers:{ 'X-csrftoken': $('[name="csrfmiddlewaretoken"]').val(), },
依赖:pip3 install django-redis from django_redis import get_redis_connection conn = get_redis_connection("default")
url的命名:用于反向解析 # 以命名user_list为例 url(r'/user_list/',view,name='user_list') from django.urls import reverse reverse('user_list') ——> '/app01/user_list/' # 模板中使用 {% url 'user_list' %} ——> '/app01/user_list/' url(r'/edit_user/(\d+)',view,name='edit_user') reverse('edit_user',args=('1',)) ——> '/edit_user/1/' {% url 'edit_user' 1 %} ——> '/edit_user/1/' url(r'/edit_user/(?P<pk>\d+)',view,name='edit_user') reverse('edit_user',args=('1',)) ——> '/edit_user/1/' {% url 'edit_user' 1 %} ——>'/edit_user/1/' reverse('edit_user',kwargs={'pk':2} ——> '/edit_user/2/' {% url 'edit_user' pk=1 %} ——> '/edit_user/1/'
from django import template register = template.Library()
@register.filter def addxx(value,arg=None): return 'xxxxx' @register.simple_tag def simple(*args,**kwargs): return 'cccccc' @register.inclusion_tag('li.html') def show_li(*args,**kwargs): return {'k1':v1}
{% load my_tags %} {{ 'alex'|addxx:'sb' }} {% simple 'v1' 'v2' k1='v3' %} {% show_li %}
orm
中db first
和code first
的含义 ?db first: 先建立数据库,再更新表模型 code first:先写表模型,再更新数据库
一、修改seting文件,在setting里面设置要链接的数据库类型和名称、地址 二、运行下面代码能够自动生成models模型文件 - python manage.py inspectdb 三、建立一个app执行下下面代码: - python manage.py inspectdb > app/models.py
SQL: 优势:执行速度快 缺点:编写复杂,开发效率不高 ---------------------------------- ORM: 优势:让用户再也不写SQL语句,提升开发效率 能够很方便地引入数据缓存之类的附加功能 缺点:在处理多表联查、where条件复杂查询时,ORM的语法会变得复杂。没有原生SQL速度快
MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分: 模型(Model) -- 存取数据 视图(View) -- 信息展现 控制器(Controller) -- 逻辑的控制 具备耦合性低、重用性高、生命周期成本低等优势 Django框架的设计模式借鉴了MVC框架的思想,也是分红三部分,来下降各个部分之间的耦合性。 Django框架的不一样之处在于它拆分的三部分为:Model(模型)、Template(模板)和View(视图),也就是MTV框架 Model(模型):负责业务对象与数据库的对象(ORM) Template(模版):负责如何把页面展现给用户 View(视图):负责业务逻辑,并在适当的时候调用Model和Template 此外,Django还有一个urls分发器,它的做用是将一个个URL的页面请求分发给不一样的view处理,view再调用相应的Model和 Template
contenttype是django的一个组件(app),它能够将django下全部app下的表记录下来 可使用他再加上表中的两个字段,实现一张表和N张表动态建立FK关系。 - 字段:表名称 - 字段:数据行ID 应用:路飞表结构优惠券和专题课和学位课关联