Django作为Python web开发的重量级框架,想要从事Django开发的必须了解Django框架的使用,这篇文章供大家学习参考,共同交流
前端客户端
后端服务器程序(接收请求报文,解析请求报文)
Gunicorn
Gunicorn(绿色独角兽)是一个Python WSGI的HTTP服务器
方式一:在flask项目下启动
# 第一个app指的是app.py文件,第二个指的是flask应用的名字;
gunicorn -w 4 -b 0.0.0.0:8000 app:app
# 参数详解
# -w INT, --workers INT:用于处理工作进程的数量,为正整数,默认为1;
# -b ADDRESS: ADDRESS,ip加端口,绑定运行的主机;
以配置文件的形式
# gunicorn.conf文件
# 并行工作进程数
workers = 4
# 指定每个工作者的线程数
threads = 2
# 监听内网端口5000
bind = '127.0.0.1:5000'
# 设置守护进程,将进程交给supervisor管理
daemon = 'false'
# 工作模式协程
worker_class = 'gevent'
# 设置最大并发量
worker_connections = 2000
# 设置进程文件目录
pidfile = '/var/run/gunicorn.pid'
# 设置访问日志和错误信息日志路径
accesslog = '/var/log/gunicorn_acess.log'
errorlog = '/var/log/gunicorn_error.log'
# 设置日志记录水平
loglevel = 'warning'
启动unicorn
gunicorn -c gunicorn.conf app:app
# -c CONFIG: CONFIG,配置文件的路径,通过配置文件启动;生产环境使用;
uwisg --WSGI–>
框架程序
构造响应报文,返回响应报文
前端客户端
Django,是用python语言写的开源web开发框架,并遵循MVC(其核心思想是分工,解耦,让不同代码之间降低耦合,增强代码的可扩展性和可移植性,实现先后兼容)设计
对比Flask框架,Django原生提供了众多的功能组件,让开发更简便快速。
django-admin startproject xxx
Python manage.py startapp xxx
Django-admin startproject 项目名称
python manage.py runserver ip:端口
Python manage.py startapp 子应用名称
当前工程的根目录,Django会依此来定位工程内的相关文件,我们也可以使用该参数来构造文件路径。
调试模式,创建工程后初始值为True,即默认工作在调试模式下。
作用:Django程序出现异常时,向前端显示详细的错误追踪信息,
注意:部署线上运行的Django不要运行在调式模式下,会影响用户体验,记得修改DEBUG=False。
初始化的工程默认语言和时区为英语和UTC标准时区
LANGUAGE_CODE = 'en-us' # 语言
TIME_ZONE = 'UTC' # 时区
将语言和时区修改为中国大陆信息
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
项目中的CSS、图片、js都是静态文件。一般会将静态文件放到一个单独的目录中,以方便管理。在html页面中调用时,也需要指定静态文件的路径,Django中提供了一种解析的方式配置静态文件路径。静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。
为了提供静态文件,需要配置两个参数:
STATICFILES_DIRS=[ ] 存放查找静态文件的目录 接收的是list
STATIC_URL 访问静态文件的URL前缀
注意
路由命名
在定义路由的时候,可以为路由命名,方便查找特定视图的具体路径信息。
1) 在使用include函数定义路由时,可以使用namespace参数定义路由的命名空间,如
url(r'^users/', include('users.urls', namespace='users')),
命名空间表示,凡是users.urls中定义的路由,均属于namespace指明的users名下。
命名空间的作用:避免不同应用中的路由使用了相同的名字发生冲突,使用命名空间区别开。
2) 在定义普通路由时,可以使用name参数指明路由的名字,如
urlpatterns = [
url(r'^index/$', views.index, name='index'),
url(r'^say', views.say, name='say'),
]
from django.urls import reverse # 注意导包路径
def index(request):
return HttpResponse("hello the world!")
def say(request):
url = reverse('users:index') # 返回 /users/index/
return HttpResponse('say')
对于未指明namespace的,reverse(路由name)
对于指明namespace的,reverse(命名空间namespace:路由name)
利用HTTP协议向服务器传参有几种途径?
Django中的QueryDict对象
定义在django.http.QueryDict
HttpRequest对象的属性GET、POST都是QueryDict类型的对象
与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况
1)方法get():根据键获取值
如果一个键同时拥有多个值将获取最后一个值
如果键不存在则返回None值,可以设置默认值进行后续处理
dict.get('键',默认值)
可简写为
dict['键']
2) 方法getlist():根据键获取值,值以列表返回,可以获取指定键的所有值
如果键不存在则返回空列表[],可以设置默认值进行后续处理
dict.getlist('键',默认值)
获取请求路径中的查询字符串参数(形如?k1=v1&k2=v2),可以通过request.GET属性获取,返回QueryDict对象。
# /qs/?a=1&b=2&a=3
def qs(request):
a = request.GET.get('a')
b = request.GET.get('b')
alist = request.GET.getlist('a')
print(a) # 3
print(b) # 2
print(alist) # ['1', '3']
return HttpResponse('OK')
重要:查询字符串不区分请求方式,即假使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串数据。
请求体数据格式不固定,可以是表单类型字符串,可以是JSON字符串,可以是XML字符串,应区别对待。
可以发送请求体数据的请求方式有POST、PUT、PATCH、DELETE。
Django默认开启了CSRF防护,会对上述请求方式进行CSRF防护验证,在测试时可以关闭CSRF防护机制,方法为在settings.py文件中注释掉CSRF中间件,如:
1) 表单类型 Form Data
前端发送的表单类型的请求体数据,可以通过request.POST属性获取,返回QueryDict对象。
def get_body(request):
a = request.POST.get('a')
b = request.POST.get('b')
alist = request.POST.getlist('a')
print(a)
print(b)
print(alist)
return HttpResponse('OK')
重要:request.POST只能用来获取POST方式的请求体表单数据。
2)非表单类型 Non-Form Data
非表单类型的请求体数据,Django无法自动解析,可以通过request.body属性获取最原始的请求体数据,自己按照请求体格式(JSON、XML等)进行解析。request.body返回bytes类型。
例如要获取请求体中的如下JSON数据
{"a": 1, "b": 2}
可以进行如下方法操作:
import json
def get_body_json(request):
json_str = request.body
json_str = json_str.decode() # python3.6 无需执行此步
req_data = json.loads(json_str)
print(req_data['a'])
print(req_data['b'])
return HttpResponse('OK')
可以通过request.META属性获取请求头headers中的数据,request.META为字典类型。
具体使用如:
def get_headers(request):
print(request.META['CONTENT_TYPE'])
return HttpResponse('OK')
#第一种方式设置响应对象
HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
content_type='Application/json' / 'image/jpg'
#第二种方式设置响应对象
response = HttpResponse()
response.content='data'
response.status_code = 200/300/400/500
response = HttpResponse()
response['food1'] = 'hotdrynoodles' # 自定义响应头food1, 值为hotdrynoodles
from django.http import JsonResponse
def demo_view(request):
return JsonResponse({'city': 'beijing', 'subject': 'python'},status=xxxx)
from django.shortcuts import redirect
def demo_view(request):
return redirect(reverse('users:say'))
Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookies最典型记住用户名。Cookie是存储在浏览器中的一段纯文本信息
可以通过HttpResponse对象中的set_cookie方法来设置cookie。
HttpResponse.set_cookie(cookie名, value=cookie值, max_age=cookie有效期)
可以通过HttpRequest对象的COOKIES属性来读取本次请求携带的cookie值。request.COOKIES为字典类型。
Session 的作用就是它在 Web服务器上保持用户的状态信息供在任何时间从任何设备上的页面进行访问。因为浏览器不需要存储任何这种信息,所以可以使用任何浏览器,即使是像 Pad 或手机这样的浏览器设备。保持会话状态!
与cookie的区别
1)cookie以文本文件格式存储在浏览器中,而session存储在服务端它
2)cookie的存储限制了数据量,只允许4KB,而session是无限量的
3)我们可以轻松访问cookie值但是我们无法轻松访问会话值,因此它更安全
4)设置cookie时间可以使cookie过期。使用session-destory(),我们将会销毁会话。
session操作
以键值对的格式创建session。
request.session['键']=值
根据键读取值。
request.session.get('键',默认值) #如果value为none,则返回默认值
删除所有session的值
request.session.clear()
清除session数据,在存储中删除session的所有数据。
request.session.flush()
删除session中的指定键及值,在存储中只删除某个键及对应的值。
del request.session['键']
设置session的有效期
request.session.set_expiry(value)
为什么需要类视图
类视图使用装饰器
在url中添加装饰器(此方法会为类视图的所有方法添加装饰器)
在类视图中添加装饰器
在类视图中使用为函数视图准备的装饰器时,不能直接添加装饰器,需要使用method_decorator将其转换为适用于类视图方法的装饰器。
method_decorator装饰器使用name参数指明被装饰的方法
# 为全部请求方法添加装饰器
@method_decorator(my_decorator, name='dispatch')
# 为特定请求方法添加装饰器
@method_decorator(my_decorator, name='get')
@method_decorator(my_decorator) # 为get方法添加了装饰器,其他方法同理
def get(self, request):
pass
类视图mixin扩展类
Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出.
定义一个中间件工厂函数,然后返回一个可以被调用的中间件。
中间件工厂函数需要接收一个可以调用的get_response对象。
返回的中间件也是一个可以被调用的对象,并且像视图一样需要接收一个request对象参数,返回一个response对象。
def simple_middleware(get_response):
# 此处编写的代码仅在Django第一次配置和初始化的时候执行一次。
def middleware(request):
# 此处编写的代码会在每个请求处理视图前被调用。
response = get_response(request)
# 此处编写的代码会在每个请求处理视图之后被调用。
return response
return middleware
多个中间件的执行流程
模板变量
模板变量可以使python的内建类型,也可以是对象。
{{变量}}
模板语句
for循环
{% for item in 列表 %}
循环逻辑
{{forloop.counter}}表示当前是第几次循环,从1开始
{%empty%} 列表为空或不存在时执行此逻辑
{% endfor %} # 结尾语句不能丢
if条件
{% if ... %}
逻辑1
{% elif ... %}
逻辑2
{% else %}
逻辑3
{% endif %} # 结尾语句不能丢
运算符
运算符左右两侧不能紧挨变量或常量,必须有空格。
{% if a == 1 %} # 正确
{% if a==1 %} # 错误
语法如下:
变量|过滤器:参数
自带过滤器
safe,禁用转义,告诉模板这个变量是安全的,可以解释执行
length,长度,返回字符串包含字符的个数,或列表、元组、字典的元素个数。
default,默认值,如果变量不存在时则返回默认值。
data|default:'默认值'
1: 在自己的app里建一个templatetags包,在包里创建一个后面要在HTML文件引用的py文件,
2:在filter_age.py文件中,先导入from django import template ,
#实例化对象
register = template.Library()
#创建一个template能认识的函数,对创建的每一个过滤器,都要用加上装饰器
@register.fitler
def multi_age(x):
return x * x
在HTML中的引用
在文件开头导入
{% load filter_age %}
使用过滤器
{{ age | multi_age }}
{#...#}
{% comment %}
...
{% endcomment %}
ORM框架
O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。
使用django进行数据库开发的步骤如下:
配置数据库连接信息
使用MySQL数据库首先需要安装驱动程序
pip install PyMySQL
在Django的工程同名子目录的__init__.py文件中添加如下语句
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
作用是让Django的ORM能以mysqldb的方式来调用PyMySQL。
修改DATABASES配置信息
#DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#}
#}
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'mysql', # 数据库用户密码
'NAME': 'django_demo' # 数据库名字
}
}
在MySQL中创建数据库
create database django_demo default charset=utf8;
在models.py中定义模型类
1) 数据库表名
模型类如果未指明表名,Django默认以 小写app应用名_小写模型类名 为数据库表名。
可通过db_table 指明数据库表名。
2) 关于主键
django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。
默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。
3) 属性命名限制
不能是python的保留关键字。
不允许使用连续的下划线,这是由django的查询方式决定的。
定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:
属性=models.字段类型(选项)
4)字段类型
类型 | 说明 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性 |
BooleanField | 布尔字段,值为True或False |
NullBooleanField | 支持Null、True、False三种值 |
CharField | 字符串,参数max_length表示最大字符个数 |
TextField | 大文本字段,一般超过4000个字符时使用 |
IntegerField | 整数 |
DecimalField | 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数 |
FloatField | 浮点数 |
DateField | 日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误 |
TimeField | 时间,参数同DateField |
DateTimeField | 日期时间,参数同DateField |
FileField | 上传文件字段 |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
5) 选项
选项 | 说明 |
---|---|
null | 如果为True,表示允许为空,默认值是False |
blank | 如果为True,则该字段允许为空白,默认值是False |
db_column | 字段的名称,如果未指定,则使用属性的名称 |
db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False |
default | 默认 |
primary_key | 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用 |
unique | 如果为True, 这个字段在表中必须有唯一值,默认值是False |
null是数据库范畴的概念,blank是表单验证范畴的
6) 外键
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
CASCADE 级联,删除主表数据时连通一起删除外键表中数据
PROTECT 保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据
SET_NULL 设置为NULL,仅在该字段null=True允许为null时可用
SET_DEFAULT 设置为默认值,仅在该字段设置了默认值时可用
SET() 设置为特定值或者调用特定方法,如
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyModel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user),
)
DO_NOTHING 不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常
迁移
1)生成迁移文件
python manage.py makemigrations
2)同步到数据库中
python manage.py migrate
数据库操作
查看数据库日志
查看mysql数据库日志可以查看对数据库的操作记录。 mysql日志文件默认没有产生,需要做如下配置:
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
# 添加一下代码
general_log_file = /var/log/mysql/mysql.log
general_log = 1
# 重启服务
sudo service mysql restart
使用如下命令打开mysql日志文件。
tail -f /var/log/mysql/mysql.log # 可以实时查看数据库的日志内容
# 如提示需要sudo权限,执行
# sudo tail -f /var/log/mysql/mysql.log
查询集QuerySet
QuerySet是Django提供的强大的数据库接口(API),正是因为通过它,我们可以使用filter, exclude, get等方法进行数据库查询,而不需要使用原始的SQL语言与数据库进行交互。从数据库中查询出来的结果一般是一个集合,这个集合叫就做 queryset查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。
当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):
特性
管理器manager