Introduction
开源web应用框架,由python开发
MVC设计典范,一种业务逻辑,数据,界面显示分离的方法组织代码。核心思想解耦,
Model:逻辑部分,通常负责在数据库中取数据
View:处理数据显示的部分
Controller: 处理用户交互的部分,
MTV:
Model:负责业务对象和数据库对象(ORM)
Template: 一个html页面
View: 相当于MVC里的Controller, 负责业务逻辑和在设当的时候调用Model和Template
Python三大主流web框架
django, flask, tornado
django
自带的组件和功能非常多,socket部分默认使用wsgiref
flask
自带组件少,依赖于三方组件
socket部分使用werkzeug
模板语法使用jinja2
Tornado
异步非阻塞
socket, 路由匹配和模板语法都是Tornado自己实现的
安装
1.11.4 2.0, 2.1 可适配 python 3.6
pip install Django==1.11.4
初步使用
创建项目
django-admin startproject project
three . /F
项目目录说明
manage.py 一个命令行工具,可以使我们用多种方式对Django项目进行交互
project目录:
__init__.py
是一个空文件
settings.py 是项目配置文件
urls.py 是项目的URL声明
wsgi.py 是项目与WSGI兼容的Web服务器入口
应用目录说明
migrations/, 所有数据库相关的操作
admin.py, 后台管理
apps.py, 注册apps使用
tests.py, 测试代码使用
views.py 处理业务逻辑
基本操作
配置数据库
在settings.py文件中,通过DATABASES选项配置
ENGINE: django.db.backends.mysql
NAME: database_name
USER:
PASSWORD:
HOST:
PORT:"3306"
在__init__.py
里写入
import pymysql
pymysql.install_as_MySQLdb()
创建项目
在一个项目中可以创建多个应用,每个应用运行一种业务逻辑
python manage.py startapp app_name
项目目录说明:
__init__.py
admin.py #
models.py
views.py
激活应用
settings.py 将应用名加入到INSTALLED_APPS选项中
模型
由一个数据表,就对应由一个模型
在models.py文件中定义模型
from django.db import models
class MyModels(models.Model):
name = models.CharFiled(max_length=20)
score = models.IntegerField()
# 类中的属性对应表中的字段
def __str__(self):
return f"{self.name}"
说明:不需要定义主键,在生成时自动添加,并且值为自动增加的
数据库支持
Django对各种数据库提供了很好的支持,Django为这些数据库提供了统一的接口
ORM
对象关系映射
任务:根据对象的类型生成表结构,将类对象,列表的操作转换为sql语句,将sql查询到的结果转为对象,列表
优点:极大减轻了开发人员的工作量,不需要面对因数据库的变更而修改代码
数据库迁移
-
生成迁移文件
python manage.py makemigrations
-
执行迁移
python manage.py migrate # 执行迁移
定义模型
定义属性
如果手动设置主键后,则django不会再生成默认主键列
不允许使用连续下划线
字段类型:
.AutoField # 自动增长的主键
.CharField # 字符串
.TestField # 长文本,大于3000
.IntegerFiled # 整数类型
.DecimalField # 小数
.BooleanField
.FloatField
.DateField
.TimeField
.DateTimeField
.FileField # 一个上传文件的字段
字段选项
db_column # 设置字段名称
primary_key=True
unique=True
关系
.ForeignKey: 一对多
元选项
在模型类中定义Meta类,用于设置元信息
class TestClass:
...
class Meta:
db_table="xxx" # 定义数据表名,推荐使用小写字母,默认项目名小写_表名
ordering=[] # 对象的默认排序字段,获取对象列表时使用
模型成员
类属性:objects, 时Manager类型,作用是与数据库进行交互
当定义模型类时没有制定管理器,则Django为模型创建一个名为objects的管理器
可以自定义管理器
自定义管理器Manager类
模型管理器时Django的模型与数据库交换的接口,
作用:向管理器类中添加额外的方法,修改管理器返回的原始查询集,重写get_queryset()方法
创建对象
目的:向数据库中添加数据,注意__init__
方法已经在父类中,在自定义的模型中无法使用
方法: 1. 在模型类中增加一个类方法,2.在自定义的管理器添加一个额外的方法
models.User.objects.create(username=xxx, password=xxx) # 创建对象后,会直接写入数据库
模型查询
查询集:表示从数据库获取的对象集合,
查询集可以有多个过滤器
查询集
- 在管理器上调用过滤器返回新的查询集
- 惰性执行
- 直接访问数据的情况:迭代和序列化,与if合用
- 返回查询结果的方法的过滤器:all(), filter(key=value, key2=value2), exclude(), oder_by(), values(),
- 返回单个数据,get()没找到或找到多条数据都会引发异常, count()返回查询集合结果数量, first(), last(), exists()
查询集的缓存
字段查询
比较运算符,聚合函数,F对象,Q对象
语法
属性名称__比较运算符=值
外键
属性名__id
转义
类似like语句中使用%是为了匹配占位,如果要匹配%号
比较运算符
- exact: 判断,大小写敏感
- contains:是否包含,大小写敏感
- startswith, endswith
- 以上如果在前面加i, 表示不区分大小写
- isnull, isnotnull
- in
- gt, gte, lt, lte
- year, month, day, hore, minute,
- 跨关联查询
- 查询快捷:pk
聚合函数
-
使用aggregate函数返回聚合函数的值
-
Avg
-
Count
-
Max
.aggregate(Max("age"))
F对象
可以使用模型的A属性和B属性作比较
filter(xx_gt=F("xxx"))
支持F对象的算术运算
Q对象
过滤器的方法中的关键字参数,条件为And模式,Q对象可以用来进行or查询
Q() | Q()
~Q() | Q() # ~表示取反
限制查询集
返回集是列表,可以用下标限制访问
数据操作
python manage.py shell
from myApp.models import TestClass
from django.utils import timezone
TestClass.objects.all() # 查看所有数据
test_obj = TestClass() # 创建空的对象
test_obj.name = "test"
test_obj.save() # 保存信息到数据库
g = TestClass.objects.get(pk=2) # pk is id
g.delete() # 从数据库中删除数据
test_obj.field = other_obj # 关联对象
other_obj.TestClass_set.all() # 反向获取关联对象
stu = grade1.students_set.create(name="test") # 不用先实例化学生对象,然后再关联班级。直接一步执行,保存到数据库
启动服务器
格式
python manage.py runserver ip:port
# ip 不写代表本机IP, 端口号默认8000
# 这是一个纯python写的轻量级服务器,仅仅在开发测试中使用
Admin站点管理
概述
内容发布
负责添加,修改,删除内容
公告访问
配置
在setting.py文件中的INSTALLED_APPS添加django.contrib.admin
创建管理员用户:
python manage.py createsuperuser
修改admin.py文件
from .models import TestClass
admin.site.register(TestClass)
自定义管理页面
# admin.py 文件
class TestClassAdmin(admin.ModelAdmin):
list_display = ['pk', 'name'] # 显示字段
list_filter = [] # 添加过滤器
search_fields = [] # 添加搜索字段
list_per_page = []
# 添加,修改页属性
fields = [] # 规定属性的先后顺序
fieldsets = [] # 给属性分组, 与fields不能同时使用
关联对象
class ToBeLinkedClass(admin.TabularInline):
model = Students
extra = 2
布尔值显示问题
class TestClassAdmin(admin.ModelAdmin):
def gender(self):
if self.gender = True:
return "male"
else:
return "Female"
gender.short_description= "gender"
action_on_bottom = True # 执行动作显示位置
使用装饰器完成注册
视图
在django中,视图对web请求进行回应。视图就是一个python函数,在views.py中设置函数,响应:网页,重定向,错误视图(404, 500),JSON数据
from django.http import HttpResponse
def index(request):
return HttpResponse("test view")
配置URL
修改project目录下的urls.py文件,制定根级urls(settings.py文件中的ROOT_URLCONF)
urlpatterns = [
url("patterns")
] # url实例的列表
在myApp应用目录下创建
一个urls.py文件
from. import views
from django.conf.urls import url
urlpatterns = [
url(r"^$]
url匹配注意事项:如果要获取url中的值,要在正则中加括号;匹配正则前面不需要反斜杠;
引入其他url配置
在应用中创建urls.py, 在工程urls.py文件使用include()
url的反向解析
如果在视图,模板中使用了硬编码的链接,url匹配发生改变时,动态生成链接地址
视图函数
参数:request, 通过正则表达式获得的参数
一般在views.py文件中定义
错误视图
-
404:url匹配不成功,在templates目录下定义404.html,参数request_path
配置setting.py, DEBUG:如果为True, 永远不会调用404, ALLOWED...
-
500: 服务端错误
-
500:
-
400: 客户端出现在客户的操作
HttpResponse对象
给浏览器返回数据,HttpResponse是由程序员创建
用法:
- 不调用模板
- 调用模板,使用render方法
- 原型,render(request, templateName, [, context])
- 作用,结合数据和模板,返回一个完整的HTML页面
- 参数:
- request:请求体对象
- templateName:模板名称
- context: 需要渲染在模板上的数据
属性:
-
content:表示返回的内容
-
charset:
-
status_code:
-
content-Type:制定输出的MIM
方法:
- init
- write
- flush:以文件的形式输出缓冲区
- set_cookie
- delete_cookie
子类HttpResponseRedirect, 可以重定向,服务器端的跳转
子类JsonResponse,异步请求,Ajax, data:字典对象, content-type:application/json
HttpRequest对象
服务器接收http请求后,会根据报文创建一个HttpRequest对象,传递给视图的第一个参数
属性:
- path: 请求的完成路径,不包含域名和端口
- method:请求的方式:GET, POST
- encoding: 表示浏览器提交的数据的编码方式
- GET:类似于字典的对象,包含了get请求的所有参数
- POST:类似于字典的对象,包含了POST请求的所有参数
- FILES:类似于字典的对象,包含了所有上传的文件
- COOKIES:就是字典,包含所有的cookie
- session:类似字典的对象,包是当前会话
方法
- is_ajax(): 如果是通过XMLHttpRequest发起的
QueryDict对象
包括GET,POST,
方法:get(),根据键获取值, 返回列表最后一个元素;getlist()将键的值以列表形式返回
状态保持
http协议是无状态的,每一次请求都是新的请求,实现状态的保持,在客户端或者服务端存储有关会话的数据
存储方式:
- cookie: 所有数据存储在客户端,不要存储敏感的数据
- session:所有的数据存储在服务端,在客户端存储用cookie存储session_id
目的:在一段时间内,跟踪请求者的状态
注意:不同的请求者不会共享这个数据
启用sessiong, 在setting.py文件中设置,默认是启用的
每个HttpRequest对象都有一个session属性,它就是一个类似字典的对象
方法:get(key), clear(), flush()删除当前的会话,并删除会话的cookie
request.session['username'] = username
username = request.session["username"]
render(request, {"username":username})
from django.contrib.auth import logout
# 清除session
设置过期时间:
set_exprity(value), value是整数,单位秒;或者时间对象,或者0(关闭浏览器时失效)
模板
模板时HTML页面,可以根据视图中传入的数据进行填充
创建模板
templates/myApp1
模板语法
变量
要遵守标识符规则,如果使用的变量不存在则插入的是空字符串
如果调用方法,但不能传入参数
{{输出值,可以时变量,可以是对象.属性}}
{{%执行代码%}}
{%for num in item_num%}
{%endfor%}
标签
语法:{% tag %}
作用:在输出中创建文本,控制逻辑和循环
-
if
{% if 表达式 %} 语句 {% elif 表达式2 %} 语句2 {% else %} 语句3 {% endif %}
-
for
{% for xx in xxx %} 语句 {% endfor %} {% for xx in xxx %} 语句 {% empty %} 语句2 # 列表为空执行 {% endfor %} {{forloop.counter}} # 循环的次数
-
comment
{% comment %} 注释多行 {% endcomment %}
-
ifequal, ifnotequal
{% ifequal value1 value2 %}
-
include
-
url, 作用反向解析
{% url 'namespace' p1 p2 %}
-
csrf_token: 用于跨站请求伪造保护
-
block, extends: 用于模板的继承
-
autodscape:用于html转移
过滤器
在变量显示前修改
-
lower, upper, join
-
可以传递参数,参数用引号引起来
lst | join:"#"
-
如果变量没有被提供,或值为空,提供默认的
{{test| default: 99}}
-
根据给定时间格式转换为日期字符串
datavalue | data: 'y-m-d'
-
HTML转移
-
加减, add,
注释
单行
{# 注释内容 #}
反向解析
<a href='good'> 链接 </a>
<a href='{% url "app:good"}'
模板继承
作用:可以减少页面内容的重复定义,实现页面的重用
block标签:在父模板中预留区域,子模板去填充
extends标签: 继承模板,写在模板文件的第一行
{% block main %}
{% endblock main}
{% extends "xx.html" %}
{% block main %}
xxxxx
{% endblock main}
html转义
将接收到的字符串当成html代码渲染
code | safe
autoescape
跨站请求伪造
防止CSRF, 在setting.py文件中加入...
{% csrf_tocken %}
配置模板路径
修改settings.py文件
TEMPLATES下DIRS
将数据传递给模板
def views_test(request):
...
lst = [1, 3, 4]
return render(request, "..html", {"key1":lst})
高级扩展
静态文件
css, font, img, js, json, other
一般放在staticmyApp文件夹下
配置setting.py文件
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
模板文件中动态绑定
{% load static %}
<link rel='stylesheet', href= "{% static 'xxx/xxx/xx.css' %}",
<script src = "{% static 'xxx/xx.js' %}"</script>
中间件
一个轻量级,底层的创建,可以介入Django的请求和响应
方法:
__init__
:不需要传入参数,服务器响应第一个请求的时候调用- process_request(),在执行视图前调用,分配url之前,每个请求上都会调用
- process_view(request, view_args, kwargs):调用视图之前
- process_template_reponse(request, response):在视图刚好执行完调用, 返回模板之前
- process_response:最终返回之前
- process_exception(request, exception):视图抛出异常时调用
自定义中间件
继承MiddlewareMixin
配置setting.py文件
上传图片
文件上传中,文件存储在request.FILES属性中
存储路径static/upfile
setting.py配置
上传文件必须是post请求
分页
Paginator对象
返回一个分页对象,属性:num_pages,页码列表,
方法:page(num), 获得一个Page对象
异常:InvalidPage, 当page()传入页码无效时
PageNotAnInteger, EmptyPage,
Page对象
属性:object_list,
方法:
-
has_next(),判断是否有下一页
-
has_revious()
-
next_page_number() 返回下一页的页码
-
previous_page_number()
all_list = Students.objects.all()
paginator = Pageinator(all_list, 6)
page = paginator.get(id)
return render(request, "../html", {"students":page})
ajax
需要动态生成,
富文本
pip install django-tinymce
TINYMCE_DEFAULT_CONF = {
'theme':'advanced'
}
创建一个模型类
继承HTMLField类
Celery
用户发起请求,并且要等待response返回,但是视图中有一些耗时操作
网页一段时间同步一次数据
解决:将耗时操作放到celery中执行,使用celery定时执行
概念:
- 任务:将耗时操作封装成一个函数
- 队列
- 工人
- 代理
pip install celery
pip install celery-with-redis
pip install django-celery
import djcelery
djcelery.setup_loader()
BROKER_URL = 'redis://...'
CELERY_IMPORTS =
在应用目录下,创建task.py文件
迁移,生成celery需要的表
在工程目录下的project目录下创建celery.py
在工程目录__init__.py
文件添加