赞
踩
M:Model,模型,和数据库进行交互
V:View,视图,负责产生Html页面
C:Controller,控制器,接收请求,进行处理,与M和V进行交互,返回应答。
项目文件夹下的组成部分:
M:Model,模型,和MVC中的M功能相同,和数据库进行交互。
V:view,视图,和MVC中的C功能相同,接收请求,进行处理,与M和T进行交互,返回应答。
T:Template,模板,和MVC中的V功能相同,产生Html页面
中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。
1.Django 中耗时的任务用一个进程或者线程来执行,比如发邮件,使用 celery。
2.部署 django 项目的时候,配置文件中设置了进程和协程的相关配置。
3.django利用多线程增加异步任务.celery消息队列。
4.django中使用多线程发送邮件.send_mail()。
5.django原生为单线程序,当第一个请求没有完成时,第二个请求阻塞,直到第一个请求完成,第二个请 求才会执行. 使用uwsgi编程多并发,使用nginx+uwsgi提供高并发,nginx的并发能力超高,单台并发能力过万 (不绝对).
6.django自带的development server为多线程模式,但是他还有一个小问题就是它不是线程安全的。可能在请求很多时会出现数据不同步,当然,这一般不是问题,因为我们通常只在自己机器上调试时才用Development Server。
cookie是有过期时间的,如果不指定,默认关闭浏览器之后cookie就会过期。 如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 False ,cookie可以在用户浏览器中保持有效达 SESSION_COOKIE_AGE 秒(存活时间)。 如果不想用户每次打开浏览器都必须重新登陆的话,可以用这个参数。 如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 True ,当浏览器关闭时,Django会使cookie失效
Django中操作session: session也是有过期时间,如果不指定,默认两周就会过期。 request.session.set_expiry(0);那么当浏览器关闭时,session失效
删除session:del request[key]
1、输入参数
- get 的参数只能是model中定义的那些字段,只支持严格匹配
- filter 的参数可以是字段,也可以是扩展的where查询关键字,如in,like等
2、返回值
- get 返回值是一个定义的model对象
- filter 返回值是一个新的QuerySet对象,然后可以对QuerySet在进行查询返回新的QuerySet对象,支持链式操作,QuerySet一个集合对象,可使用迭代或者遍历,切片等,但是不等于list类型(使用一定要注意)
3、异常
- get 只有一条记录返回的时候才正常,也就说明get的查询字段必须是主键或者唯一约束的字段。当返回多条记录或者是没有找到记录的时候都会抛出异常
- filter 有没有匹配的记录都可以。
在接受一个Http请求之前的准备
启动一个支持WSGI网关协议的服务器监听端口等待外界的Http请求,比如Django自带的开发者服务器或者uWSGI服务器。
服务器根据WSGI协议指定相应的Handler来处理Http请求,并且初始化该Handler,在Django框架中由框架自身负责实现这一个Handler。 此时服务器已处于监听状态,可以接受外界的Http请求 当一个http请求到达服务器的时候 服务器根据WSGI协议从Http请求中提取出必要的参数组成一个字典(environ)并传入Handler中进行处理。
在Handler中对已经符合WSGI协议标准规定的http请求进行分析,比如加载Django提供的中间件,路由分配,调用路由匹配的视图等。 返回一个可以被浏览器解析的符合Http协议的HttpResponse。
Django根据设置的缓存方式,浏览器第一次请求时,cache会缓存单个变量或整个网页等内容到硬盘或者内存中,同时设置response头部,当浏览器再次发起请求时,附带f-Modified-Since请求时间到Django,Django 发现f-Modified-Since会先去参数之后,会与缓存中的过期时间相比较,如果缓存时间比较新,则会重新请求数据,并缓存起来然后返回response给客户端,如果缓存没有过期,则直接从缓存中提取数据,返回给response给客户端。
1、提交方式
form表单通常是通过在HTML中定义的action,method及submit来进行表单提交,另外也可以通过在js中调用submit函数来进行表单提交。 具体的提交方式有很多种,比如可以通过封装成XMLHttpRequest对象进行提交。
Ajax是基于XMLHttpRequest进行的。
2、页面刷新
Form提交,更新数据完成后,需要转到一个空白页面再对原页面进行提交后处理。哪怕是提交给自己本身的页面,也是需要刷新的,因此局限性很大。
Ajax可以实现页面的局部刷新,整个页面不会刷新。
3、请求由谁来提交
Form提交是浏览器完成的,无论浏览器是否开启JS,都可以提交表单。
Ajax是通过js来提交请求,请求与响应均由js引擎来处理,因此不启用JS的浏览器,无法完成该操作。
4、是否可以上传文件
最初,ajax出于安全性考虑,不能对文件进行操作,所以就不能通过ajax来实现文件上传,但是通过隐藏form提交则可以实现这个功能,所以这也是用隐藏form提交的主要用途。 后来XMLHttpRequest引入了FormData类型,使得通过Ajax也可以实现文件上传。
对于开发人员来说,网站性能优化一般包括Web前端性能优化、应用服务器性能优化、存储服务器性能优化三类。
Web前端性能优化:
1、减少http请求
http协议是无状态的应用层协议,意味着每次http请求都需要建立通信链路、进行数据传输,而在服务器端,每个http请求都需要启动独立的线程去处理。减少http请求的数目可有效提高访问性能。减少http的主要手段是合并CSS、合并javascript、合并图片。
2、使用浏览器缓存
对一个网站而言,CSS、javascript、logo、图标,这些静态资源文件更新的频率都比较低,而这些文件又几乎是每次http请求都需要的。如果将这些文件缓存在浏览器中,可以极好的改善性能。通过设置http头中的cache-control和expires的属性,可设定浏览器缓存,缓存时间可以自定义。
3、启用压缩
在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。如果可以的话,尽可能的将外部的脚本、样式进行合并,多个合为一个。文本文件的压缩效率可达到80%以上,因此HTML、CSS、javascript文件启用GZip压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在网络带宽良好,而服务器资源不足的情况下要综合考虑。
4、CSS放在页面最上部,javascript放在页面最下面
浏览器会在下载完成全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载CSS。 Javascript则相反,浏览器在加载javascript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此javascript最好放在页面最下面。
应用服务器优化
应用服务器也就是处理网站业务的服务器,网站的业务代码都部署在这里,主要优化方案有缓存、异步、集群等。
1、合理使用缓存
当网站遇到性能瓶颈时,第一个解决方案一般是缓存。在整个网站应用中,缓存几乎无处不在,无论是客户端,还是应用服务器,或是数据库服务器。在客户端和服务器的交互中,无论是数据、文件都可以缓存,合理使用缓存对网站性能优化非常重要。
缓存一般用来存放那些读写次数比较高,变化较少的数据,比如网站首页的信息、商品的信息等。应用程序读取数据时,一般是先从缓存中读取,如果读取不到或数据已失效,再访问磁盘数据库,并将数据再次写入缓存。
缓存的基本原理是将数据存储在相对有较高访问速度的存储介质中,比如内存。一方面缓存访问速度快,另一方面,如果缓存的数据是需要经过计算处理得到的,那使用缓存还可以减少服务器处理数据的计算时间。
使用缓存并不是没有缺陷:内存资源是比较宝贵的,不可能将所有数据都缓存,一般频繁修改的数据不建议使用缓存,这会导致数据不一致。 网站数据缓存一般遵循二八定律,即80%的访问都在20%的数据上。所以,一般将这20%的数据缓存,可以起到改善系统性能,提高服务器读取效率。
2、异步操作
使用消息队列将调用异步化,可以改善网站系统的性能。
在不使用消息队列的情况下,用户的请求直接写入数据库,在高并发的情况下,会对数据库造成非常大的压力,也会延迟响应时间。
在使用消息队列后,用户请求的数据会发送给消息队列服务器,消息队列服务器会开启进程,将数据异步写入数据库。消息队列服务器的处理速度远超过数据库,因此用户的响应延迟可得到改善。
消息队列可以将短时间内的高并发产生的事务消息,存储在消息队列中,从而提高网站的并发处理能力。在电商网站的促销活动中,合理使用消息队列,可以抵御短时间内用户高并发的冲击。
3、使用集群
在网站高并发访问的情况下,使用负载均衡技术,可以为一个应用构建由多台服务器组成的服务器集群,将并发访问请求,分发到多台服务器上处理,避免单一服务器因负载过大,而导致响应延迟。
4、代码优化
网站的业务逻辑代码主要部署在应用服务器上,需要处理复杂的并发事务。合理优化业务代码,也可以改善网站性能。
任何web网站都会遇到多用户的并发访问,大型网站的并发用户会达到数万。每个用户请求都会创建一个独立的系统进程去处理。由于线程比进程更轻量,占用资源更少,所以,目前主流的web应用服务器都采用多线程的方式,处理并发用户的请求,因此,网站开发多数都是多线程编程。
使用多线程的另一个原因是服务器有多个CPU,现在手机都到了8核CPU的时代,一般的服务器至少是16核CPU,要想最大限度的使用这些CPU,必须启动多线程。
那么,启动多少线程合适呢?
启动线程数和CPU内核数量成正比,和IO等待时间成正比。如果都是计算型的任务,那么线程数最多不要超过CPU内核数,因为启动再多,CPU也来不及调用。如果任务是等待读写磁盘、网络响应,那么多启动线程会提高任务并发度,提高服务器性能。 或者用个简化的公式来描述: 启动线程数 = (任务执行时间/(任务执行事件 - IO等待时间)) * CPU内核数
存储优化
数据的读写是网站处理并发访问的另一瓶颈。使用缓存虽然可以解决一部分数据读写压力,但很多时候,磁盘仍然是系统最严重的瓶颈。而且磁盘是网站最重要的资产,磁盘的可用性和容错性也至关重要。
机械硬盘和固态硬盘:机械硬盘是目前最常用的硬盘,通过马达带动磁头到指定磁盘的位置访问数据,每次访问数据都需要移动磁头,在读取连续数据和随机访问上,磁头移动的次数相差巨大,因此机械硬盘的性能表现差别巨大,读写效率较低。而在网站应用中,大多数数据的访问都是随机的,在这种情况下,固态硬盘具有更高的性能。但目前固态硬盘在工艺上、数据可靠性上还有待提升,因此固态硬盘的使用尚未普及,从发展趋势看,取代机械硬盘应该是迟早的事情。
总结:
网站性能优化是在用户高并发访问,网站遇到问题时的解决方案。所以网站性能优化的主要内容是改善高并发用户访问情况下的网站响应速度。
网站性能优化的最终目的是改善用户的体验。但性能优化本身也是需要综合考虑的。比如说,性能提高一倍,服务器数量也要增加一倍,这样的优化是否可以考虑?
技术是由业务驱动的,离开业务的支撑,任何性能优化都是空中楼阁。
在django中,路由是浏览器访问服务器时,先访问的项目中的url,再由项目中的url找到应用中url,这些url是放在一个列表里,遵从从前往后匹配的规则。
在flask中,路由是通过装饰器给每个视图函数提供的,而且根据请求方式的不同可以一个url用于不同的作用。
@app.route('<URL>')中URL显式支持string、int、float、path 4种类型,隐式支持正则
第一步:写正则类,继承BaseConverter,将匹配到的值设置为regex的值
class RegexUrl(BaseConverter):
def __init__(self, url_map, *args):
super(RegexUrl, self).__init__(url_map)
self.regex = args[0]
第二步:把正则类赋值给我们定义的正则规则
app.url_map.converters['re'] = RegexUrl
第三步:在URL中使用正则
@app.route('/regex/<re("[a-z]{3}"):id>')
def regex111(id):
return 'id:%s'%id
手动创建上下文的两种方法:
{{ expression | filter1 | filter2 | ... }} 即 表达式(expression)使用filter1过滤后再使用filter2过滤..
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']设置的作用?
作用:可以配置请求执行完逻辑之后自动提交,而不用我们每次都手动调用session.commit()
补充:
监听数据库中的数据,当发生改变,就会显示一些内容 app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True
显示打印的数据以及sql语句,建议不设置,默认为False app.config['SQLALCHEMY_ECHO'] = True
filter()模糊查询
把过滤器添加到原查询上,返回一个新查询。
filter_by()精确查询
把等值过滤器添加到原查询上,返回一个新查询
1.蓝图定义
蓝图/Blueprint是Flask应用程序组件化的方法,可以在一个应用内或跨越多个项目共用蓝图。使用蓝图可以极大地简化大型应用的开发难度,也为Flask扩展提供了一种在应用中注册服务的集中式机制。
2.蓝图的应用场景
1.把一个应用分解为一个蓝图的集合。这对大型应用是理想的。一个项目可以实例化一个应用对象,初始化几个扩展,并注册一集合的蓝图。
2.以 URL 前缀和/或子域名,在应用上注册一个蓝图。 URL 前缀/子域名中的参数即成为这个蓝图下的所有视图函数的共同的视图参数(默认情况下)。
3.在一个应用中用不同的 URL 规则多次注册一个蓝图。
4.通过蓝图提供模板过滤器、静态文件、模板和其它功能。一个蓝图不一定要实现应用或者视图函数。
5.初始化一个 Flask 扩展时,在这些情况中注册一个蓝图。
3.蓝图的缺点
不能在应用创建后撤销注册一个蓝图而不销毁整个应用对象。
4.使用蓝图的三个步骤
1.创建 一个蓝图对象
blue = Blueprint("blue",__name__)
2.在这个蓝图对象上进行操作 ,例如注册路由、指定静态文件夹、注册模板过滤器...
@blue.route('/')
def blue_index():
return 'Welcome to my blueprint'
3.在应用对象上注册这个蓝图对象
app.register_blueprint(blue,url_prefix='/blue')
1、图中Browse是浏览器,WebServerA是受信任网站/被攻击网站A,WebServerB是恶意网站/攻击网站B。
(1)一开始用户打开浏览器,访问受信任网站A,输入用户名和密码登陆请求登陆网站A。
(2)网站A验证用户信息,用户信息通过验证后,网站A产生Cookie信息并返回给浏览器。
(3)用户登陆网站A成功后,可以正常请求网站A。
(4)用户未退出网站A之前,在同一浏览器中,打开一个TAB访问网站B。
(5)网站B看到有人访问后,他会返回一些攻击性代码。
(6)浏览器在接受到这些攻击性代码后,促使用户不知情的情况下浏览器携带Cookie(包括sessionId)信息,请求网站A。这种请求有可能更新密码,添加用户什么的操作。
2、从上面CSRF攻击原理可以看出,要完成一次CSRF攻击,需要被攻击者完成两个步骤:
(1)登陆受信任网站A,并在本地生成COOKIE。
(2)在不登出A的情况下,访问危险网站 B。
如果不满足以上两个条件中的一个,就不会受到CSRF的攻击
3、以下情况可能会导致CSRF:
1.登录了一个网站后,打开一个tab页面并访问另外的网站。
2.关闭浏览器了后,本地的Cookie尚未过期,你上次的会话还没有已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了……)
解决办法:就是在表单中添加from.csrf_token
flask中有三个session:
第一个:数据库中的session,例如:db.session.add()
第二个:在flask_session扩展中的session,使用:from flask_session import Session,使用第三方扩展的session可以把信息存储在服务器中,客户端浏览器中只存储sessionid
第三个:flask自带的session,是一个请求上下文, 使用:from flask import session。自带的session把信息加密后都存储在客户端的浏览器cookie中
1、可以传入的参数
(1)字符串:‘hello’,但是‘abc’,不行,因为abc是python内置的模块
(2)__name__,约定俗成
2、不可以插入的参数
(1)python内置的模块,re,urllib,abc等
(2)数字
请求钩子是通过装饰器的形式实现的,支持以下四种:
1、before_first_request在处理第一个请求前运行
2、before_request:在每次请求前运行
3、after_request:如果没有未处理的异常抛出,在每次请求后运行
4、teardown_request:即使有未处理的异常抛出,在每次请求后运行
应用:
请求钩子
@api.after_request
def after_request(response):
设置默认的响应报文格式为application/json
如果响应报文response的Content-Type是以text开头,则将其改为默认的json类型
If response.headers.get("Content-Type").startswith("text"):
response.headers["Content-Type"] = "application/json" return response
@app.route('<URL>')中 URL 显式支持 string、int、float、path uuid any 6 种类型,隐式支持正 则。
第一步:写正则类,继承 BaseConverter,将匹配到的值设置为 regex 的值。
- class RegexUrl(BaseConverter):
- def __init__(self, url_map, *args):
- super(RegexUrl, self).__init__(url_map)
- self.regex = args[0]
第二步:把正则类赋值给我们定义的正则规则。
app.url_map.converters['re'] = RegexUrl
第三步:在 URL 中使用正则。
- @app.route('/regex/<re("[a-z]{3}"):id>')
- def regex111(id):
- return 'id:%s'%id
current_app、g 是应用上下文。
request、session 是请求上下文。
手动创建上下文的两种方法:
两者区别:
两者作用:
请求上下文(request context): Flask 从客户端收到请求时,要让视图函数能访问一些对象,这样才能处理请求。请求对象是一 个很好的例子,它封装了客户端发送的 HTTP 请求。 要想让视图函数能够访问请求对象,一个显而易见的方式是将其作为参数传入视图函数,不过这会导致程序中的每个视图函数都增加一个参数,除了访问请求对象,如果视图函数在处理请求时还要访问其他对象,情况会变得更糟。为了避免大量可有可无的参数把视图函数弄得一团糟,Flask 使用上下文临时把某些对象变为全局可访问。
应用上下文(application context): 它的字面意思是应用上下文,但它不是一直存在的,它只是 request context 中的一个对 app 的代理(人),所谓 local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而 生,随 request 而灭的。
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
# 动态追踪修改设置,如未设置只会提示警告
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
#查询时会显示原始 SQL 语句
app.config['SQLALCHEMY_ECHO'] = True
补充:
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']:可以配置请求执行完逻辑之后自动提 交,而不用我们每次都手动调用 session.commit();
监听数据库中的数据,当发生改变,就会显示一些内容: app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True;
显示打印的数据以及 sql 语句,建议不设置,默认为 False: app.config['SQLALCHEMY_ECHO'] = True。
在 Flask 中,为了处理 web 表单,我们一般使用 Flask-WTF 扩展,它封装了 WTForms,并且它有 验证表单数据的功能。
WTForms 支持的 HTML 标准字段:
WTForms 常用验证函数
使用 Flask-WTF 需要配置参数 SECRET_KEY。
CSRF_ENABLED 是为了 CSRF(跨站请求伪造)保护。 SECRET_KEY 用来生成加密令牌,当 CSRF 激活的时候,该设置会根据设置的密匙生成加密令牌。
1.可以通过 postman 测试工具测试,或者看 log 日志信息找到错误信息的大概位置。
2.断点调试
1.URL 反转:根据视图函数名称得到当前所指向的 url。
2.url_for() 函数最简单的用法是以视图函数名作为参数,返回对应的 url,还可以用作加载静态文件。
<link rel="stylesheet" href="{{url_for('static',filename='css/index.css')}}">
该条语句就是在模版中加载 css 静态文件。
3.url_for 和 redirect 区别
url_for 是用来拼接 URL 的,可以使用程序 URL 映射中保存的信息生成 URL。
url_for() 函数最简单的用法是以视图函数名作为参数, 返回对应的 URL。例如,在示例程序中 hello.py 中调用 url_for('index') 得到的结果是 /。
redirect 是重定向函数,输入一个 URL 后,自动跳转到另一个 URL 所在的地址,例如,你在函数 中写 return redirect('https://www.baidu.com') 页面就会跳转向百度页面。
- from flask import Flask, redirect, url_for
-
- app = Flask(__name__)
-
-
- @app.route('/')
- def index():
- login_url = url_for('login')
- return redirect(login_url)
- return u'这是首页'
-
-
- @app.route('/login/')
- def login():
- return u'这是登陆页面'
-
-
- @app.route('/question/<is_login>/')
- def question(is_login):
- if is_login == '1':
- return u'这是发布问答的页面'
- else:
- return redirect(url_for('login'))
-
-
- if __name__ == '__main__':
- app.run(debug=True)
请求钩子是通过装饰器的形式实现的,支持以下四种:
1,before_first_request 在处理第一个请求前运行
2,before_request:在每次请求前运行
3,after_request:如果没有未处理的异常抛出,在每次请求后运行
4,teardown_request:即使有未处理的异常抛出,在每次请求后运行
应用:
# 请求钩子
- @api.after_request
- def after_request(response):
- """设置默认的响应报文格式为 application/json"""
- # 如果响应报文 response 的 Content-Type 是以 text 开头,则将其改为
- # 默认的 json 类型
- if response.headers.get("Content-Type").startswith("text"):
- response.headers["Content-Type"] = "application/json"
- return respon
字段查询
all():返回模型类对应表格中的所有数据。
get():返回表格中满足条件的一条数据,如果查到多条数据,则抛异常:MultipleObjectsReturned, 查询不到数据,则抛异常:DoesNotExist。
filter():参数写查询条件,返回满足条件 QuerySet 集合数据。
条件格式:
**模型类属性名**__条件名=值
注意:此处是模型类属性名,不是表中的字段名
关于 filter 具体案例如下:
判等 exact。
- BookInfo.object.filter(id=1)
-
- BookInfo.object.filter(id__exact=1) # 此处的__exact 可以省略
模糊查询 like
例:查询书名包含'传'的图书。contains
BookInfo.objects.filter(btitle__contains=’传’)
空查询 where 字段名 isnull
BookInfo.objects.filter(btitle__isnull=False)
范围查询 where id in (1,3,5)
BookInfo.objects.filter(id__in=[1,3,5])
比较查询 gt lt(less than) gte(equal) lte
BookInfo.objects.filter(id__gte=3)
日期查询
- BookInfo.objects.filter(bpub_date__year = 1980)
- BookInfo.objects.filter(bpub_date__gt = date(1980,1,1))
exclude:返回不满足条件的数据。
BookInfo.objects.exclude(id=3)
F 对象
作用:用于类属性之间的比较条件。
1.导入F
from django.db.models import F
2. 例:where bread > bcomment
BookInfo.objects.filter(bread__gt =F(‘bcomment’))
3. 例:
BookInfo.objects.filter(bread__gt=F(‘bcomment’)*2)
Q 对象
作用:用于查询时的逻辑条件。可以对 Q 对象进行&|~操作。
- from django.db.models import Q
-
- BookInfo.objects.filter(id__gt=3, bread__gt=30)
-
- BooInfo.objects.filter(Q(id__gt=3) & Q(bread__gt=3))
-
- BookInfo.objects.filter(Q(id__gt=3) | Q(bread__gt=30))
-
- BookInfo.objects.filter(~Q(id=3))
order_by 返回 QuerySet
作用:对查询结果进行排序。
- BookInfo.objects.all().order_by('id')
-
- BookInfo.objects.all().order_by('-id')
-
- BookInfo.objects.filter(id__gt=3).order_by('-bread')
聚合函数
作用:对查询结果进行聚合操作。
sum count max min avg
aggregate:调用这个函数来使用聚合。
- from django.db.models import Sum,Count,Max,Min,Avg
-
- BookInfo.objects.aggregate(Count('id'))
{'id__count': 5} 注意返回值类型及键名
BookInfo.objects.aggregate(Sum(‘bread’))
{‘bread__sum’:120} 注意返回值类型及键名
count 函数
作用:统计满足条件数据的数目。
例:统计所有图书的数目。
BookInfo.objects.all().count()
例:统计 id 大于 3 的所有图书的数目。
BookInfo.objects.filter(id__gt = 3).count()
模型类关系
一对多关系
例:图书类-英雄类
models.ForeignKey() 定义在多的类中。
多对多关系
例:新闻类-新闻类型类
models.ManyToManyField() 定义在哪个类中都可以。
一对一关系
例:员工基本信息类-员工详细信息类
models.OneToOneField() 定义在哪个类中都可以。
Django 在中间件中预置了六个方法,这六个方法的区别在于不同的阶段执行,对输入或输出进行干预,方法如下:
1.初始化:无需任何参数,服务器响应第一个请求的时候调用一次,用于确定是否启用当前中间件。
- def __init__():
- pass
2.处理请求前:在每个请求上调用,返回 None 或 HttpResponse 对象。
- def process_request(request):
- pass
3.处理视图前:在每个请求上调用,返回 None 或 HttpResponse 对象。
- def process_view(request, view_func, view_args, view_kwargs):
- pass
4.处理模板响应前:在每个请求上调用,返回实现了 render 方法的响应对象。
- def process_template_response(request, response):
- pass
5.处理响应后:所有响应返回浏览器之前被调用,在每个请求上调用,返回 HttpResponse 对象。
- def process_response(request, response):
- pass
6.异常处理:当视图抛出异常时调用,在每个请求上调用,返回一个 HttpResponse 对象。
- def process_exception(request,exception):
- pass
1.uWSGI 是一个 Web 服务器,它实现了 WSGI 协议、uwsgi、http 等协议。Nginx 中 HttpUwsgiModule 的作用是与 uWSGI 服务器进行交换。WSGI 是一种 Web 服务器网关接口。它是一 个 Web 服务器(如 nginx,uWSGI 等服务器)与 web 应用(如用 Flask 框架写的程序)通信的一种 规范。
要注意 WSGI / uwsgi / uWSGI 这三个概念的区分。
WSGI 是一种通信协议。
uwsgi 是一种线路协议而不是通信协议,在此常用于在 uWSGI 服务器与其他网络服务器的数据通信。
uWSGI 是实现了 uwsgi 和 WSGI 两种协议的 Web 服务器。
2. nginx 是一个开源的高性能的 HTTP 服务器和反向代理:
首先浏览器发起 http 请求到 nginx 服务器,Nginx 根据接收到请求包,进行 url 分析,判断访问的 资源类型,如果是静态资源,直接读取静态资源返回给浏览器,如果请求的是动态资源就转交给 uwsgi 服务器,uwsgi 服务器根据自身的 uwsgi 和 WSGI 协议,找到对应的 Django 框架,Django 框架下的应用进行逻辑处理后,将返回值发送到 uwsgi 服务器,然后 uwsgi 服务器再返回给 nginx,最后 nginx 将返回值返回给浏览器进行渲染显示给用户。
1.设计表时,尽量少使用外键,因为外键约束会影响插入和删除性能;
2.使用缓存,减少对数据库的访问;
3.在 orm 框架下设置表时,能用 varchar 确定字段长度时,就别用 text;
4.可以给搜索频率高的字段属性,在定义时创建索引;
5.Django orm 框架下的 Querysets 本来就有缓存的;
6.如果一个页面需要多次连接数据库,最好一次性取出所有需要的数据,减少对数据库的查询次数;
7.若页面只需要数据库里某一个两个字段时,可以用 QuerySet.values();
8.在模板标签里使用 with 标签可以缓存 Qset 的查询结果。
将验证码保存到数据库或 session,设置过期时间为 1 分钟,然后页面设置一个倒计时(一般是前端 js 实现这个计时的展示,一分钟过后再次点击获取新的信息。
django:主要是用来搞快速开发的,他的亮点就是快速开发,节约成本,正常的并发量不过 10000, 如果要实现高并发的话,就要对 django 进行二次开发,比如把整个笨重的框架给拆掉,自己写 socket 实现 http 的通信,底层用纯 c,c++写提升效率,ORM 框架给干掉,自己编写封装与数据库交互的框 架,因为啥呢,ORM 虽然面向对象来操作数据库,但是它的效率很低,使用外键来联系表与表之间的 查询;
flask:轻量级,主要是用来写接口的一个框架,实现前后端分离,提升开发效率,Flask 本身相当于一 个内核,其他几乎所有的功能都要用到扩展(邮件扩展 Flask-Mail,用户认证 Flask-Login),都需要 用第三方的扩展来实现。比如可以用 Flask-extension 加入 ORM、窗体验证工具,文件上传、身份验 证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。
其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是 Flask 框架的核心。Python 最出名的框架要数 Django,此外还有 Flask、Tornado 等框架。虽然 Flask 不是最出名的框架,但是 Flask 应该算是最灵活的框架之一,这也是 Flask 受到广大开发者喜爱的原因。
Tornado: Tornado 是一种 Web 服务器软件的开源版本。Tornado 和现在的主流 Web 服务器框 架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。 得利于其非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接,因此 Tornado 是实时 Web 服务的一个 理想框架。
40.django 如何提升性能(高并发)?
对一个后端开发程序员来说,提升性能指标主要有两个:一个是并发数,另一个是响应时间。网站性能的优化一般包括 web 前端性能优化,应用服务器性能优化,存储服务器优化。
对前端的优化主要有:
1.减少 http 请求,减少数据库的访问量,比如使用雪碧图。
2.使用浏览器缓存,将一些常用的 css,js,logo 图标,这些静态资源缓存到本地浏览器,通过设 置 http 头中的 cache-control 和 expires 的属性,可设定浏览器缓存,缓存时间可以自定义。
3 对 html,css,javascript 文件进行压缩,减少网络的通信量。
对我个人而言,我做的优化主要是以下三个方面:
1.合理的使用缓存技术,对一些常用到的动态数据,比如首页做一个缓存,或者某些常用的数据做 个缓存,设置一定得过期时间,这样减少了对数据库的压力,提升网站性能。
2.使用 celery 消息队列,将耗时的操作扔到队列里,让 worker 去监听队列里的任务,实现异步操 作,比如发邮件,发短信。
3.就是代码上的一些优化,补充:nginx 部署项目也是项目优化,可以配置合适的配置参数,提升 效率,增加并发量。
4.如果太多考虑安全因素,服务器磁盘用固态硬盘读写,远远大于机械硬盘,这个技术现在没有普 及,主要是固态硬盘技术上还不是完全成熟, 相信以后会大量普及。
5.另外还可以搭建服务器集群,将并发访问请求,分散到多台服务器上处理。
6.最后就是运维工作人员的一些性能优化技术了。
REST:Representational State Transfer 的缩写,翻译:“具象状态传输”。一般解释为“表现层 状态转换”。
REST 是设计风格而不是标准。是指客户端和服务器的交互形式。我们需要关注的重点是如何设计 REST 风格的网络接口。
REST 的特点:
1.具象的。一般指表现层,要表现的对象就是资源。比如,客户端访问服务器,获取的数据就是资 源。比如文字、图片、音视频等。
2.表现:资源的表现形式。txt 格式、html 格式、json 格式、jpg 格式等。浏览器通过 URL 确定资 源的位置,但是需要在 HTTP 请求头中,用 Accept 和 Content-Type 字段指定,这两个字段是对资源表现的描述。
3.状态转换:客户端和服务器交互的过程。在这个过程中,一定会有数据和状态的转化,这种转化 叫做状态转换。其中,GET 表示获取资源,POST 表示新建资源,PUT 表示更新资源,DELETE 表示删除资源。HTTP 协议中最常用的就是这四种操作方式。
RESTful 架构:
1.每个 URL 代表一种资源;
2.客户端和服务器之间,传递这种资源的某种表现层;
3.客户端通过四个 http 动词,对服务器资源进行操作,实现表现层状态转换。
一、域名:
将 api 部署在专用域名下: http://api.example.com 或者将 api 放在主域名下: http://www.example.com/api/
二、版本:
将 API 的版本号放在 url 中。
三、路径:
路径表示 API 的具体网址。每个网址代表一种资源。 资源作为网址,网址中不能有动词只能有名词,一般名词要与数据库的表名对应。而且名词要使用复数。
错误示例:
正确示例:
四、使用标准的 HTTP 方法:
对于资源的具体操作类型,由 HTTP 动词表示。 常用的 HTTP 动词有四个。
示例:
五、过滤信息:
如果资源数据较多,服务器不能将所有数据一次全部返回给客户端。API 应该提供参数,过滤返 回结果。
实例:
六、状态码:
服务器向用户返回的状态码和提示信息,常用的有:
七、错误信息:
一般来说,服务器返回的错误信息,以键值对的形式返回。
{ error: 'Invalid API KEY' }
八、响应结果:
针对不同结果,服务器向客户端返回的结果应符合以下规范。
九、使用链接关联相关的资源:
在返回响应结果时提供链接其他 API 的方法,使客户端很方便的获取相关联的信息。
十、其他:
服务器返回的数据格式,应该尽量使用 JSON,避免使用 XML。
runserver 方法是调试 Django 时经常用到的运行方式,它使用 Django 自带的 WSGI Server 运 行,主要在测试和开发中使用,并且 runserver 开启的方式也是单进程 。
在单元测试方面,Django 继承 python 的 unittest.TestCase 实现了自己的 django.test.TestCase,编写测试用例通常从这里开始。测试代码通常位于 app 的 tests.py 文件中(也可以在 models.py 中编写,一般不建议)。在 Django 生成的 depotapp 中,已经包含了这个文件, 并且其中包含了一个测试用例的样例:
- 1. python manage.py test:执行所有的测试用例
-
- 2. python manage.py test app_name, 执行该 app 的所有测试用例
-
- 3. python manage.py test app_name.case_name: 执行指定的测试用例
一些测试工具:unittest 或者 pytest
1.有部署经验,在阿里云服务器上部署的
2.技术有:nginx + uwsgi 的方式来部署 Django 项目
3.无标准答案(例:压力测试一两千)
设置 Cookie
- def cookie_set(request):
- response = HttpResponse("<h1>设置 Cookie,请查看响应报文头</h1>")
- response.set_cookie('h1', 'hello django')
- return response
读取 Cookie
- def cookie_get(request):
- response = HttpResponse("读取 Cookie,数据如下:<br>")
- if request.COOKIES.has_key('h1'):
- response.write('<h1>' + request.COOKIES['h1'] + '</h1>')
- return response
以键值对的格式写会话。
根据键读取值。
清除所有会话,在存储中删除值部分。
清除会话数据,在存储中删除会话的整条数据。
删除会话中的指定键及值,在存储中只删除某个键及对应的值。
设置会话的超时时间,如果没有指定过期时间则两个星期后过期。
如果 value 是一个整数,会话将在 value 秒没有活动后过期。
如果 value 为 0,那么用户会话的 Cookie 将在用户的浏览器关闭时过期。
如果 value 为 None,那么会话在两周后过期。
Session 依赖于 Cookie,如果浏览器不能保存 cookie 那么 session 就失效了。因为它需要浏览器的 cookie 值去 session 里做对比。session 就是用来在服务器端保存用户的会话状态。
cookie 可以有过期时间,这样浏览器就知道什么时候可以删除 cookie 了。 如果 cookie 没有设 置过期时间,当用户关闭浏览器的时候,cookie 就自动过期了。你可以改变 SESSION_EXPIRE_AT_BROWSER_CLOSE 的设置来控制 session 框架的这一行为。缺省情况下, SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 False ,这样,会话 cookie 可以在用户浏览器中保持有效达 SESSION_COOKIE_AGE 秒(缺省设置是两周,即 1,209,600 秒)如果你不想用户每次打开浏览器都必须重新登陆的话,用这个参数来帮你。如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 True,当浏览器关闭时,Django 会使 cookie 失效。
SESSION_COOKIE_AGE:设置 cookie 在浏览器中存活的时间。
1、优化算法时间
算法的时间复杂度对程序的执行效率影响最大,在 Python 中可以通过选择合适的数据结构来优化 时间复杂度,如 list 和 set 查找某一个元素的时间复杂度分别是 O(n)和 O(1)。不同的场景有不同的优化方式,总得来说,一般有分治,分支界限,贪心,动态规划等思想。
2、循环优化
每种编程语言都会强调需要优化循环。当使用 Python 的时候,你可以依靠大量的技巧使得循环运 行得更快。然而,开发者经常漏掉的一个方法是: 避免在一个循环中使用点操作。每一次你调用方法 str.upper,Python 都会求该方法的值。然而, 如果你用一个变量代替求得的值,值就变成了已知的,Python 就可以更快地执行任务。优化循环的关键,是要减少 Python 在循环内部执行的工作量,因为 Python 原生的解释器在那种情况下,真的会减缓执行的速度。(注意:优化循环的方法有很多,这只是其中的一个。例如,许多程序员都会说,列表推导是在循环中提高执行速度的最好方式。这里的关键是,优化循环是程序取得更高的执行速度的更 好方式之一。)
3、函数选择
在循环的时候使用 xrange 而不是 range;使用 xrange 可以节省大量的系统内存,因为 xrange() 在序列中每次调用只产生一个整数元素。而 range()將直接返回完整的元素列表,用于循环时会有不必要的开销。在 python3 中 xrange 不再存在,里面 range 提供一个可以遍历任意长度的范围的 iterator。
4、并行编程
因为 GIL 的存在,Python 很难充分利用多核 CPU 的优势。但是,可以通过内置的模块 multiprocessing 实现下面几种并行模式:
多进程:对于 CPU 密集型的程序,可以使用 multiprocessing 的 Process,Pool 等封装好的类, 通过多进程的方式实现并行计算。但是因为进程中的通信成本比较大,对于进程之间需要大量数据交互的程序效率未必有大的提高。
多线程:对于 IO 密集型的程序,multiprocessing.dummy 模块使用 multiprocessing 的接口封装 threading,使得多线程编程也变得非常轻松(比如可以使用 Pool 的 map 接口,简洁高效)。
布式:multiprocessing 中的 Managers 类提供了可以在不同进程之共享数据的方式,可以在此基础上开发出分布式的程序。 不同的业务场景可以选择其中的一种或几种的组合实现程序性能的优化。
5、使用性能分析工具
除了上面在 ipython 使用到的 timeit 模块,还有 cProfile。cProfile 的使用方式也非常简单: python-mcProfilefilename.py,filename.py 是要运行程序的文件名,可以在标准输出中看到每一个 函数被调用的次数和运行的时间,从而找到程序的性能瓶颈,然后可以有针对性地优化。
6、set 的用法
set 的 union,intersection,difference 操作要比 list 的迭代要快。因此如果涉及到求 list 交集,并集或者差的问题可以转换为 set 来操作。
7、PyPy
PyPy 是用 RPython(CPython 的子集)实现的 Python,根据官网的基准测试数据,它比 CPython 实现的 Python 要快 6 倍以上。快的原因是使用了 Just-in-Time(JIT)编译器,即动态编译器,与静态编译器(如 gcc,javac 等)不同,它是利用程序运行的过程的数据进行优化。由于历史原因,目前 pypy 中还保留着 GIL,不过正在进行的 STM 项目试图将 PyPy 变成没有 GIL 的 Python。如果 python 程序中含有 C 扩展(非 cffi 的方式),JIT 的优化效果会大打折扣,甚至比 CPython 慢(比 Numpy)。 所以在 PyPy 中最好用纯 Python 或使用 cffi 扩展。
中间件不用继承自任何类(可以继承 object),下面一个中间件大概的样子:
- class CommonMiddleware(object):
- def process_request(self, request):
- return None
-
- def process_response(self, request, response):
- return response
还有 process_view, process_exception 和 process_template_response 函数。
1)初始化:无需任何参数,服务器响应第一个请求的时候调用一次,用于确定是否启用当前中间件。
- def __init__(self):
- pass
2)处理请求前:在每个请求上,request 对象产生之后,url 匹配之前调用,返回 None 或 HttpResponse 对象。
- def process_request(self, request):
- pass
3)处理视图前:在每个请求上,url 匹配之后,视图函数调用之前调用,返回 None 或 HttpResponse 对象。
- def process_view(self, request, view_func, *view_args, **view_kwargs):
- pass
4)处理响应后:视图函数调用之后,所有响应返回浏览器之前被调用,在每个请求上调用,返回 HttpResponse 对象。
- def process_response(self, request, response):
- pass
5)异常处理:当视图抛出异常时调用,在每个请求上调用,返回一个 HttpResponse 对象。
- def process_exception(self, request, exception):
- pass
Django REST framework 是一个强大而灵活的 Web API 工具。使用 RESTframework 的理由有:
情景:用户发起 request,并等待 response 返回。在这些 views 中,可能需要执行一段耗时的程 序,那么用户就会等待很长时间,造成不好的用户体验,比如发送邮件、手机验证码等。
使用 celery 后,情况就不一样了。
解决:将耗时的程序放到 celery 中执行。
将多个耗时的任务添加到队列 queue 中,也就是用 redis 实现 broker 中间人,然后用多个 worker 去监听队列里的任务去执行。
Jieba 分词支持三种分词模式:
精确模式:试图将句子最精确地切开,适合文本分析;
全模式:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词
功能: 分词,添加自定义词典,关键词提取,词性标注,并行分词,Tokenize:返回词语在原文的起始位置,ChineseAnalyzer for Whoosh 搜索引擎。
web 开发中,部署方式大致类似。简单来说,使用 Nginx 主要是为了实现分流、转发、负载均衡, 以及分担服务器的压力。Nginx 部署简单,内存消耗少,成本低。Nginx 既可以做正向代理,也可以做反向代理。
正向代理:请求经过代理服务器从局域网发出,然后到达互联网上的服务器。
特点:服务端并不知道真正的客户端是谁。
反向代理:请求从互联网发出,先进入代理服务器,再转发给局域网内的服务器。
特点:客户端并不知道真正的服务端是谁。
区别:正向代理的对象是客户端。反向代理的对象是服务端。
一个动态网站的基本权衡点就是,它是动态的。 每次用户请求页面,服务器会重新计算。从开销处理的角度来看,这比你读取一个现成的标准文件的代价要昂贵的多。
这就是需要缓存的地方。
Django 自带了一个健壮的缓存系统来保存动态页面这样避免对于每次请求都重新计算。方便起见, Django 提供了不同级别的缓存粒度:可以缓存特定视图的输出、可以仅仅缓存那些很难生产出来的部分、或者可以缓存整个网站 Django 也能很好的配合那些“下游”缓存, 比如 Squid 和基于浏览器的缓存。这里有一些缓存不必要直接去控制但是可以提供线索, (via HTTPheaders)关于网站哪些部分需要缓存和如何缓存。
设置缓存:
缓存系统需要一些设置才能使用。 也就是说,你必须告诉他你要把数据缓存在哪里- 是数据库中, 文件系统或者直接在内存中。 这个决定很重要,因为它会影响你的缓存性能,是的,一些缓存类型要比其他的缓存类型更快速。 你的缓存配置是通过 setting 文件的 CACHES 配置来实现的。这里有 CACHES 所有可配置的变量值。
1.在用户输入目的 URL 后,浏览器先向 DNS 服务器发起域名解析请求;
2.在获取了对应的 IP 后向服务器发送请求数据包;
3.服务器接收到请求数据后查询服务器上对应的页面,并将找到的页面代码回复给客户端;
4.客户端接收到页面源代码后,检查页面代码中引用的其他资源,并再次向服务器请求该资源;
5.在资源接收完成后,客户端浏览器按照页面代码将页面渲染输出显示在显示器上;
Session 采用的是在服务器端保持状态的方案,而 Cookie 采用的是在客户端保持状态的方案。但 是禁用 Cookie 就不能得到 Session。因为 Session 是用 Session ID 来确定当前对话所对应的服务 器 Session,而 Session ID 是通过 Cookie 来传递的,禁用 Cookie 相当于失去了 SessionID,也 就得不到 Session。
Django 和其他 Web 框架的 HTTP 处理的流程大致相同,Django 处理一个 Request 的过程是首先通过中间件,然后再通过默认的 URL 方式进行的。我们可以在 Middleware 这个地方把所有 Request 拦截住,用我们自己的方式完成处理以后直接返回 Response。
1. 加载配置
Django 的配置都在 “Project/settings.py” 中定义,可以是 Django 的配置,也可以是自定义的配置,并且都通过 django.conf.settings 访问,非常方便。
2. 启动
最核心动作的是通过 django.core.management.commands.runfcgi 的 Command 来启动, 它运行 django.core.servers.fastcgi 中的 runfastcgi,runfastcgi 使用了 flup 的 WSGIServer 来启动 fastcgi 。而 WSGIServer 中携带了 django.core.handlers.wsgi 的 WSGIHandler 类的一个实例,通过 WSGIHandler 来处理由 Web 服务器(比如 Apache,Lighttpd 等)传过来的请求,此时才是真正进入 Django 的世界。
3. 处理 Request
当有 HTTP 请求来时,WSGIHandler 就开始工作了,它从 BaseHandler 继承而来。 WSGIHandler 为每个请求创建一个 WSGIRequest 实例,而 WSGIRequest 是从 http.HttpRequest 继承而来。接下来就开始创建 Response 了。
4. 创建 Response
BaseHandler 的 get_response 方法就是根据 request 创建 response,而具体生成 response 的动作就是执行 urls.py 中对应的 view 函数了,这也是 Django 可以处理“友好 URL ” 的关键步骤,每个这样的函数都要返回一个 Response 实例。此时一般的做法是通过 loader 加载template 并生成页面内容,其中重要的就是通过 ORM 技术从数据库中取出数据,并渲染到 Template 中,从而生成具体的页面了。
5. 处理 Response
Django 返回 Response 给 flup,flup 就取出 Response 的内容返回给 Web 服务器,由后者返回给浏览器。
总之,Django 在 fastcgi 中主要做了两件事:处理 Request 和创建 Response,而它们对应的核心就是“ urls 分析”、“模板技术”和“ ORM 技术”。
如图所示,一个 HTTP 请求,首先被转化成一个 HttpRequest 对象,然后该对象被传递给 Request 中间件处理,如果该中间件返回了 Response,则直接传递给 Response 中间件做收尾处理。 否则的话 Request 中间件将访问 URL 配置,确定哪个 view 来处理,在确定了哪个 view 要执行,但是还没有执行该 view 的时候,系统会把 request 传递给 view 中间件处理器进行处理,如果该中间件返回了 Response,那么该 Response 直接被传递给 Response 中间件进行后续处理,否则将执行确定的 view 函数处理并返回 Response,在这个过程中如果引发了异常并抛出,会被 Exception 中间件处理器进行处理。
如果用户在 A 应用服务器登陆的 session 数据没有共享到 B 应用服务器,那么之前的登录状态就没有了。
使用 HttpResponseRedirect
redirect
状态码:302,301
exists():判断查询集中否有数据,如果有则返回 True,没有则返回 False。
runserver 方法是调试 Django 时经常用到的运行方式,它使用 Django 自带的 WSGI Server 运 行,主要在测试和开发中使用,并且 runserver 开启的方式也是单进程 。
uWSGI 是一个 Web 服务器,它实现了 WSGI 协议、uwsgi、http 等协议。注意 uwsgi 是一种通信协议,而 uWSGI 是实现 uwsgi 协议和 WSGI 协议的 Web 服务器。uWSGI 具有超快的性能、 低内存占用和多 app 管理等优点,并且搭配着 Nginx 就是一个生产环境了,能够将用户访问请求与应用 app 隔离开,实现真正的部署。相比来讲,支持的并发量更高,方便管理多进程,发挥多核的优势, 提升性能。
Nginx 相对 Apache 的优点:
Apache 相对 Nginx 的优点:
char 长度是固定的,不管你存储的数据是多少他都会都固定的长度。而 varchar 则是可变长度但他 要在总长度上加 1 字符,这个用来存储位置。所以在处理速度上 char 要比 varchar 快速很多,但是对费存储空间,所以对存储不大、但在速度上有要求的可以使用 char 类型,反之可以用 varchar 类型。
惰性执行、缓存 。
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、 与 if 合用
一般团购,秒杀,特价之类的活动,这样会使访问量激增,很多人抢购一个商品,作为活动商品, 库存肯定是很有限的。控制库存问题,数据库的事务功能是控制库存超卖的有效方式。
1.在秒杀的情况下,肯定不能如此频率的去读写数据库,严重影响性能问题,必须使用缓存,将需 要秒杀的商品放入缓存中,并使用锁来处理并发情况,先将商品数量增减(加锁、解析)后在进行其他方面的处理,处理失败再将数据递增(加锁、解析),否则表示交易成功。
2.这个肯定不能直接操作数据库的,会挂的。直接读库写库对数据库压力太大了,要用到缓存。
3.首先,多用户并发修改同一条记录时,肯定是后提交的用户将覆盖掉前者提交的结果了。这个直 接可以使用加乐观锁的机制去解决高并发的问题。
HttpRequest 是 django 接受用户发送过来的请求报文后,将报文封装到 HttpRequest 对象中去。
HttpResponse 返回的是一个应答的数据报文。render 内部已经封装好了 HttpResponse 类。
视图的第一个参数必须是 HttpRequest 对象,两点原因:表面上说,他是处理 web 请求的,所以 必须是请求对象,根本上说,他是基于请求的一种 web 框架,所以,必须是请求对象。
因为 view 处理的是一个 request 对象,请求的所有属性我们都可以根据对象属性的查看方法来获取具体的信息:
格式:request.属性
request.path 请求页面的路径,不包含域名
request.get_full_path 获取带参数的路径
request.method 页面的请求方式
request.GET GET 请求方式的数据
request.POST POST 请求方式的数据
request.COOKIES 获取 cookie
request.session 获取 session
request.FILES 上传图片(请求页面有 enctype="multipart/form-data"属性时 FILES 才有数据。
?a=10 的键和值时怎么产生的,键是开发人员在编写代码时确定下来的,值时根据数据生成或者用户填写的,总之是不确定的。
403 错误:表示资源不可用,服务器理解客户的请求,但是拒绝处理它,通常由于服务器上文件和目录的权限设置导致的 web 访问错误。
如何解决:
1、把中间件注释。
2、在表单内部添加{% scrf_token %}
request.GET.get()取值时如果一键多值情况,get 是覆盖的方式获取的。
getlist()可以获取多个值。
在一个有键无值的情况下,该键名 c 的值返回空。
有键无值:c: getlist 返回的是列表,空列表
在无键无值也没有默认值的情况下,返回的是 None
无键无值:e:None
HttpResponse 常见属性:
content: 表示返回的内容
charset: 表示 response 采用的编码字符集,默认是 utf-8
status_code:返回的 HTTP 响应状态码 3XX 是对请求继续进一步处理,常见的是重定向。
常见方法:
init:创建
httpResponse 对象完成返回内容的初始化
set_cookie:设置 Cookie 信息:格式:set_cookies('key','value',max_age=None,expires=None) max_age 是一个整数,表示指定秒数后过期,expires 指定过期时间,默认两个星期后过期。
write 向响应体中写数据
应答对象:
方式一:
方式二:
方式三:
方式四:
方式五:
方式六:
ajax 实现网页局部刷新功能:
使用场景:模板中的超链接,视图中的重定向
使用:在定义 url 时为 include 定义 namespace 属性,为 url 定义 name 属性
在模板中使用 url 标签:{% url 'namespace_value:name_value'%}
在视图中使用 reverse 函数:redirect(reverse('namespce_value:name_value’))
根据正则表达式动态生成地址,减轻后期维护成本。
注意反向解析传参数,主要是在我们的反向解析的规则后面添加了两个参数,两个参数之间使用空格隔 开:<a href="{% url 'booktest:fan2' 2 3 %}">位置参数</a>
import logging
logger=logging.getLogger(__name__) # 为 loggers 中定义的名称
logger.info("some info ...)
可用函数有:
logger.debug() logger.info() logger.warning() logger.error()
Django 文件管理:
对于 jdango 老说,项目中的 css,js,图片都属于静态文件,我们一般会将静态文件放到一个单独的目录中,以方便管理,在 html 页面调用时,也需要指定静态文件的路径。静态文件可以放在项目根目录下,也可以放在应用的目录下,由于这些静态文件在项目中是通用的,所以推荐放在项目的根目录下。
在生产中,只要和静态文件相关的,所有访问,基本上没有 django 什么事,一般都是由 nignx 软 件代劳了,为什么?因为 nginx 就是干这个的。
1. 优化数据库查询
1.1 一次提供所有数据
1.2 仅提供相关的数据
2. 代码优化
2.1 简化代码
2.2 更新或替代第三方软件包
2.3 重构代码
我们常规处理并发的解决方案:
1.动态页面静态化。
2.制作数据库散列表,即分库分表。
3.增加缓存。
4.增加镜像。
5.部署集群。
6.负载均衡。
7.异步读取,异步编程。
8.创建线程池和自定义连接池,将数据持久化。
9.把一件事,拆成若干件小事,启用线程,为每个线程分配一定的事做,多个线程同时进行把该事 件搞定再合并。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。