Django3入门
简介
Django一个由python编写的基于MVC框架模式的开源web框架,具有… …
MVC和MTV
MVC即Model+View+Controller是一种常见的web框架模式,但很难将Django严谨的分为于是有了Django特有的MTV框架模式即Model+Template+View
- Model即模型,主要负责数据库和视图之间的沟通
- View即视图,主要负责网页中的业务逻辑,调用Model数据传递给Template
- Template即模板,主要负责渲染页面展示给用户
Django项目和基础设置
创建Django项目
使用django-admin startproject demo1
在当前目录创建一个名为demo1的django项目 ### 创建APP应用 使用python
manage.py startapp app1 在当前django项目中创建一个名为app1的APP应用
在setting.py的INSTALLED_APPS中增加APP应用名注册APP 1
2
3
4
5
6
7
8
9INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app1',
]
项目结构
- setting.py:整个django项目中的配置文件
- url.py:url配置文件,用于将url与视图联系起来
- wsgi.py:网关接口,用于沟通联系django和虚拟主机中的web服务器
- migrations:用于存放Model生成的数据库迁移文件
- admin.py:django自带管理界面的管理文件
- models.py:Model文件,在里面定义需要使用的数据库模型类
- view.py:视图文件,用于编写各个视图
设置语言与时区
在setting.py文件中 1
2
3LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/ShangHai'
启动django项目
使用python manage.py runserver启动django
URL设置
在url.py文件中urlpatterns列表中添加path或者re_path来绑定url和视图函数
1
2
3
4
5
6
7
8
9
10from django.contrib import admin
from django.urls import path,include
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index),
path('book/',include("B.urls")),
re_path(r'^abc$',view.abc)
]
路由绑定
- path:用来绑定字符串路由和视图函数,第一个参数为路由,第二个参数为绑定的视图函数
- re_path:用来绑定re正则路由和视图函数,第一个为匹配路由的正则表达式,第二个参数为绑定的视图函数
- include:指定子路由文件 (path(‘book/’,include(“B.urls”))即将book/路由下的所有子路由配置放到B文件夹下的urls.py文件)
路由参数
1 | path('/<int:id>',view.index) |
匹配任意int类型url,并且该路由参数可被视图函数接收参数名为id 其余类型参数:
str | 字符串类型 |
---|---|
int | 整数类型 |
slug | ASCII编码 |
uuid | uuid格式 |
path | URL路径类型 |
路由命名
为了方便在模板中调用路由通常会给路由进行命名,在模板只需要调用名称即可获得相应路由
1 | path('/<int:id>',include(("B.urls","index")),namespace="user") |
namespace是对指定子路由整个进行名称定义,一般配合name使用
在templates模板中调用方法
1 | <a href="{% url 'index' %}"> 只使用name时</a> |
反向解析
可以通过url反向解析出该url的name和namepace等信息
1 | from django.shortcuts import reverse |
resolve的内置函数
函数名称 | 功能 |
---|---|
func | 路由的视图函数对象或视图类对象 |
args | 以列表格式获取路由的变量信息 |
kwargs | 以字典格式获取路由的变量信息 |
url_name | 获取路由命名name |
app_name | 获取include函数第二个元素值 |
app_names | 同上,以列表格式表示 |
namespace | 获取路由的命名空间 |
namespaces | 同上,以列表格式表示 |
view_name | 获取整个路由的名称,包括命名空间 |
路由重定向
通过urls.py文件配置路由重定向
1 | from django.contrib import admin |
通过视图函数进行重定向
1 | from django.shortcuts import redirect |
Views
view负责主要的业务逻辑,并从数据库查询数据同时反馈给template
基本视图函数
1 | from django.http import HttpResponse |
相应类型 | 说明 |
---|---|
HttpResponseRedirect(“/”) | 状态码302,重定向到该地址 |
HttpResponsePermanentRedirect(“/”) | 状态码301,永久重定向到该地址 |
HttpResponseBadRequest(“400”) | 状态码400,访问页面不从在或请求错误 |
HttpResponseNotFound(“404”) | 状态码404,访问的页面不存在或请求错误 |
HttpResponseForbidden(“403”) | 状态码403,没有访问权限 |
HttpResponseNotAllowed(“405”) | 状态码405,不允许使用该请求方式 |
HttpResponseServerError(“500”) | 状态码500,服务器内容错误 |
JsonResponse(“{‘key’:‘value’}”) | 状态码200,响应json数据 |
StreamingHttpResponse() | 状态码200,以流式输出 |
使用HTML文件
1 | from django.shortcuts import render,redirect |
绑定404与500页面
1 | #view函数 |
下载视图
1 | #urls.py文件 |
上传视图
1 | def upload(request): |
Templates
设置使用
在项目目录下templates文件夹
在setting.py文件中配置templates文件夹路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')], #将此处改为templates文件夹路径
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]增加static文件夹路径
### template语法1
STATICFILES_DIRS = [os.path.join(BASE_DIR,'static'),] #在setting.py中新增此项
for 标签变量1
2
3
4
5
6
7
8
9
10
11
12
13
14{{ name }} #加载视图函数传出的字典中'name'字段数据、
{% load static %} #加载static文件,在整个html文件中使用一次即可
{% static "文件路径" %} #设置static文件路径
{% if 条件 %}内容{% elif 条件 %}内容{% endif %} #if条件判断,可以使用or,and,not,in
{% for i in value %}内容{% empty %}内容{%cycle 'a' 'b'%}{% endfor %} #条件循环判断,当value没有值时输出empty内容,cycle中第一次循环输出a第二次输出b第三次输出a
{% url xxx:xxx %} #通过路由名称获取Url
{% extends xxx %} #继承xxx模板
{% block xxx %} #将该代码定义为父代码供extends继承
forloop.counter | 循环当前迭代(从1开始索引) |
---|---|
forloop.counter0 | 循环当前迭代(从0开始索引) |
forloop.revcounter | 循环当前迭代(倒叙) |
forloop.revcounter0 | 循环当前迭代(倒叙从0开始索引) |
forloop.first | 当第一次循环时为真 |
forloop.last | 最后一次循环时为真 |
forloop.parentloop | 当嵌套循环时,parentloop表示外层循环 |
自定义标签
在项目目录下创建标签文件夹并在该目录下创建templatetags文件夹
将标签文件夹名称注册进app配置里(和app注册一样)
在templatetags目录下创建mytags.py文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from django import template
# 创建模板对象
register = template.Library()
# 定义模板节点类
class ReversalNode(template.Node):
def __init__(self, value):
self.value = str(value)
def render(self, context):
return self.value[::-1]
# 注册标签名,如果没设标签名则用函数名
def do_reversal(parse, token):
try:
tag_name, value = token.split_contents()
except:
raise template.TemplateSyntaxError("syntax")
return ReversalNode(value)在html文件中使用自定义标签需要先使用{% load mytags %}吧自定义标签加载进去,mytags为创建的文件名
过滤器
用法 1
{{变量|过滤器:值|过滤器:值}}
filesizeformat | 以人们习惯的方式显示文件大小格式 |
---|---|
first | 只取出列表数据中的第一个 |
last | 只取出列表数据中的最后一个 |
length | 返回列表数据的长度 |
length_is | 测试数据是否为指定长度 |
floatformat | 以指定的浮点数格式来显示数据 |
linebreaks | 把文字内容的换行符号转换为HTML的和 |
linebreaksbr | 把文字内容的换行符转换成 |
linenumber | 为显示的文字加上行号 |
lower/upper | 把字符串内容全部换成小写/大写 |
random | 以随机数将面前的数据内容显示出来 |
safe | 把字符串为安全的,不需要再处理转移字符 |
slugify | 标记字符串空格变成“-”,让此字符串可以放在网址栏 |
striptags | 把所有HTML标记都删除 |
truncatechars | 把过长的字符串裁切成指定长度 |
wordcount | 计算字数 |
yesno | 按照只的内容时True、False还是None,显示出有意义的内容 |
自定义过滤器
创建方式同自定义标签
```python from django import template
register = template.Library()
@register.filters(name=‘replace’) def do_replace(value, agrs): oldValue = agrs.split(“:”)[0] newValue = agrs.split(‘:’)[1] return value.replace(oldValue, newValue)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
### 使用Jinja2模板引擎
Jinja2模板引擎设计思想源于Django模板引擎,并拓展了其语法与功能,是Python里面被广泛应用的模板引擎
1. 使用pip安装Jinja2库
2. 在setting同级目录创建jinja2.py文件
```python
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update({
'static': staticfiles_storage.url,
'url': reverse,
})
return env将jinja2.py文件中的函数写入setting.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [BASE_DIR / 'djangoProject/jinja2.py',BASE_DIR / 'templates'], #需要将jinja2配置文件和templates文件夹都写进来
'APP_DIRS': True,
'OPTIONS': {
'environment': 'djangoProject.jinja2.environment'
}
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Jinja2 for循环标签变量
变量 | 描述 |
---|---|
loop.index | 循环的当前迭代,索引从1开始 |
loop.index0 | 循环的当前迭代,索引从0开始 |
loop.revindex | 循环结束时的迭代次数,索引从0开始 |
loop.revindex0 | 循环结束时的迭代次数,索引从1开始 |
loop.first | 如果是第一次迭代就为True |
loop.last | 如果是最后一次迭代久违True |
loop.length | 循环总次数 |
loop.depth | 当前循环深度,从1级开始 |
loop.depth0 | 当前循环深度,从0级开始 |
loop.previtem | 上一次迭代对象 |
loop.nextitem | 下一次迭代对象 |
loop.changed(value) | 若是上次迭代的值与当前迭代的值不同,则返回True |
jinja2常用过滤器
过滤器 | 说明 |
---|---|
{{value\|abs}} | 设置数值的绝对值 |
{{ value\|default('new')}} | 设置默认值 |
{{ value\|escape}} | 转义字符,转成HTML语法 |
{{ value\|first}} | 获取第一个元素 |
{{ value\|last}} | 获取最后一个元素 |
{{ value\|length}} | 获取长度 |
{{ value\|join('-')}} | 同python用法 |
{{ value\|safe}} | 转义处理 |
{{ value\|int}} | 转成Int型 |
{{ value\|float}} | 转成float型 |
{{ value\|lower}} | 转成小写 |
{{ value\|upper}} | 转成大写 |
{{ value\|replace('a','b')}} | 字符串替换 |
{{ value\|truncate(9,true)}} | 字符串截断 |
{{ value\|striptags}} | 删除value中所有的HTML标签 |
{{ value\|trim}} | 删除value前后的空白字符 |
{{ value\|string}} | 转换成字符串 |
{{ value\|wordcount}} | 计算字符串的单词个数 |
自定义JInja2的过滤器
1 | #修改jinja2.py文件 |
Models
主要负责数据库和视图之间的沟通数据库是动态网站的重要组成部分,在Django中使用了ORM的概念把数据存取的过程进行了抽象化,通过Models来定义数据表。
### 数据库配置
Django默认使用的是自带的一个小型数据库,只支持测试使用,所以使用时必须现在setting文件中进行相应的数据库配置,以下为MySQL配置。
1
2
3
4
5
6
7
8
9
10DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', #使用MySQL作为数据库
'NAME': 'mydb', #数据库名称
'USER': 'root', #数据库用户名
'PASSWORD': '123456', #数据库密码
'HOST': '10.30.59.136', #数据库IP
'PORT': '3306', #数据库端口
}
}1
2
3
4import pymysql
pymysql.install_as_MySQLdb() #MySQLdb并不支持python3.x 需要使用pymysql并设置为和MySQLdb同样使用
#需要安装pymysql库
- 在APP目录里models.py文件里创建数据表模型 ### 数据库迁移 该步目的为把models里的数据表模型在数据库中创建或更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class Model(models.Model):
字段名=models.字段类型()
class Demo(models.Model):
boolean = models.BooleanField(max_length=10) #布尔类型
char = models.CharField() #varchar类型
date = models.DateField() #date类型
datetime = models.DateTimeField() #datetime类型
double = models.FloatField() #double类型
decimal = models.DecimalField() #decimal类型
email = models.EmailField() #存储邮箱varcgar类型存储
int = models.IntegerField() #int类型
image = models.ImageField() #保存图片路径
text = models.TextField() #logtext类型
# max_length 设置长度
# primary_key 设置主键
# blank 是否允许为空
# null 允许为空
# default 默认值
# db_index 是否增加索引
# unique 是否为唯一值
# db_column 指定字段名
# verbose_name 后台显示名称
#设置外键
book = models.ForeignKey(Demo2,on_delete=models.CASCADE)
# Demo2 为外键指向的另一张表的类名
生成迁移文件 python manage.py makemigrations 执行迁移文件生成表
python manage.py migrate ### 数据库操作 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#数据库操作格式
类.object.操作方法
#增加数据
Demo.object.create(字段=数据)
#查询数据
Demo.object.all() #查询该表全部数据
Demo.object.values("字段") #查询指定字段
Demo.object.filter(字段=参数,字段=参数) #条件查询(多参数时为与)
Demo.object.exclude(条件) #返回不包含此条件的数据
Demo.object.get(条件) #只获取一条数据,如果查询结果多于一条时报错
#排序
Demo.object.order_by("字段") #根据字段排序
#更新数据
filter = Demo.object.filter(字段=参数,字段=参数)
filter.name = "name" #将查询结果中的name字段内容更新成"name"
filter.save()
#该方法指定修改一条数据
filter = Demo.object.filter(字段=参数,字段=参数).update(name = "name")
#批量修改多字段
#删除数据
Demo.object.all().delete() #批量删除全部数据
Demo.object.filter(字段=参数,字段=参数).delete() #批量删除符合条件的数据
Demo.object.get(条件).delete() #删除一条数据
查询谓词
用法在操作方法里面跟在字段后
Demo.object.filter(id__exact=1)
#__exact 等值查询
#__contains 包含指定值
#__startswith 以xxx开始
#__endswith 以xxx结束
#__gte 大于等于指定值
#__lt 小于指定值
#__lte 小于等于指定值
#__gt 大于指定值
#__in 查找数据是否在指定范围(in)
#__range 查找数据是否在指定的区间范围(between)
在APP目录下的admin.py文件中以以下格式注册数据表
1
admin.site.register(models.Demo) #Demo为数据表类名
使用命令行在项目目录下使用命令创建超级用户
1
python manage.py createsuperuser
打开//admin/页面登陆超级账号
在后台显示的数据表字段名可以在models.py中使用verbose_name设置
- admin设置 ### Models内部类
1
2
3
4
5
6class BookManage(admin.ModelAdmin):
list_display=['name','author','date'] # admin中显示字段
list_display_links=['author'] #控制可以进入更改页面的字段
list_filter=['author'] #增加过滤器(分类)
search_fields=['name','author'] #开启搜索框,可以根据指定字段搜索
list_editable=['name'] #设置允许在更改列表页面改动的字段### F()和Q() F()可以用来对数据中字段值进行引用1
2
3
4
5模型类内部类 Meta
class Meta:
db_table = '数据表名' 设置数据表名称
verbose_name = '单数名' 给模型对象一个名称,用于在admin管理界面中显示
verbose_name_plural = '复数名' 给模型对象一个名称,用于在admin管理界面中显示Q()用来复杂条件查询1
2
3filter = Demo.object.filter(字段=参数,字段=参数).update(age = F("age")+10)
#获取该查询中的age字段并在原本的age字段数值+10重新赋值给age
#可以防止多用户同时访问时数据更新不及时造成数据存储错误## Cookice和Session1
2
3
4
5filter = Demo.object.filter(Q(name="python")|Q(name="java"))
Q()支持使用逻辑运算符
Q('字段')|Q('字段') 逻辑或
Q('字段')&Q('字段') 逻辑与
Q('字段')~Q('字段') 逻辑非