本文为 Django 学习总结,讲解 Django 的高级用法
运行环境
- Windows 10
- Pycharm Community Edition 2020.1.3
- Django 3.0.8
所有的代码见【Django】系列。
静态文件
包括 css、js、图片、Json 文件、字体文件等。静态文件一般放在 project 目录下的 static 文件夹下,与 templates 同级。在 static 文件夹下还要创建每个应用对应的文件夹,在对应文件夹下还要创建存放不同类型文件的文件夹。看起来可能有点绕,可以参考下图:
现在我们想将模板中的字体设置为红色的,可以直接在 style.css 中配置:
h1{
color:red;
}
然后在 settings.py 中配置静态文件夹路径,在 settings.py 的最后一行加入:
# 设置用来访问这个文件夹的URL地址
STATIC_URL = '/static/'
# 把项目中的static文件夹设置为静态文件夹
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static') # static对应前面创建的目录
]
使用下面的代码在 html 中引入 css 样式:
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" type="text/css" href="/static/myApp/css/style.css"/>
</head>
<body>
<h1>Mike is a good man</h1>
</body>
得到结果:
想要使用 jquery-3.1.1.min.js 和 sunck.js 文件。其中 jquery-3.5.1.min.js 在 jquery 官网直接下载,并放到 js 目录下。sunck.js 中添加:
// sunck.js
console.log("good man")
需要在 link
后添加下面的代码。:
<script type="text/javascript"
src="/static/myApp/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript"
src="/static/myApp/js/sunck.js"></script>
刷新后查看 Consule,得到值:
再显示一张图片,在 h1
后添加下面的代码:
<img src="/static/myApp/img/IMG_0468.PNG"/>
但是,如果文件名发生了变化,html 文件中的所有路径都需要变化,工作量很大,我们可以采取类似反向解析的方法,给路径起“别名”。
首先在 html 文件第一行引入静态文件:
{% load static from staticfiles %}
图片就可以用下面的方式添加:
{% load static %} # django3中使用。django2中使用load static from staticfiles
得到结果:
将这些硬链接改为“别名”,如果我们修改了静态文件的名称,也无需修改 html 中的路径。
中间件
一个轻量级、底层的插件,可以介入 Django 的请求和相应,本质为一个 Python 类。settings.py 中的 MIDDLEWARE
即为系统提供的中间件
方法
__init__
:
不需要传参数,服务器响应第一个请求时自动调用,用于确认是否启用该中间件。
process_request(self, request)
:
在执行视图(分配 url 匹配视图)之前被调用,每个请求都会调用,返回 None 或 HttpResponse 对象
process_view(self, request, view_func, view_args, view_kwargs)
:
调用视图之前执行,每个请求都会调用,返回 None 或 HttpResponse 对象
process_template_response(self, request, response)
:
在视图刚好执行完后调用,每个请求都会调用,返回 None 或 HttpResponse 对象
process_response(self, request, response)
:
所有响应返回浏览器之前调用,每个请求都会调用,返回 HttpResponse 对象
process_exception(self, request, request, exception)
:
当视图抛出异常时调用,返回 HttpResponse 对象
总结为下图:
自定义中间件
我们现在想要在某个过程中拿到中间件的执行结果。首先自定义中间件,在 templates 同级目录下创建 middleware 文件夹,创建该应用对应的文件夹,并创建 mymiddle.py 来自定义中间件:
在 myMiddle.py 中添加下面的代码:
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
def process_request(self, request):
print("get参数为:", request.GET.get("a"))
使用自定义中间件
需要配置 settings.py 文件,添加路径:
'middleware.myApp.myMiddle.MyMiddle',
在浏览器中输入 127.0.0.1:8000/?a=1
,打印出结果:
上传图片
文件上传时,文件数据存储在 request.FILES 属性中。一般将上传图片存储在 static 目录下创建的 upfile 目录中,然后配置 settings.py 文件,在最后添加:
# 上传文件目录
MEDIA_ROOT=os.path.join(BASE_DIR, r'static\upfile')
此时的服务器为 project 文件夹。新建上传文件的模板:
<body>
<!--要添加enctype="multipart/form-data"属性-->
<form method="post" action="/savefile/" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="file"/>
<input type="submit" value="上传"/>
</form>
</body>
配置 url 和视图将页面展示出来:
定义的视图文件如下:
def upfile(request):
return render(request, 'myApp/upfile.html')
import os
from django.conf import settings
def savefile(request):
if request.method == "POST": # 上传文件必须是POST请求
f = request.FILES["file"] # 相当于文件描述符
# 合成文件在服务器端的路径
filePath = os.path.join(settings.MEDIA_ROOT, f.name)
with open(filePath, 'wb') as fp: # wb表示图片文件,普通文件为w
for info in f.chunks():
fp.write(info)
return HttpResponse("上传成功")
else:
return HttpResponse("上传失败")
成功上传到 upfile 文件夹下:
分页
Paginator 对象
创建对象
格式为 Paginator(列表, 整数)
,返回分页对象。
属性
count
:得到对象总数num_pages
:页面总数page_range
:页码列表,如[1,2,3,4,5]
,页码从 1 开始。
方法
page(num)
,获得 Page 对象,如果提供的页码不存在会抛出InvalidPage
异常
常见的异常
InvalidPage
:当向page()
传递的是一个无效的页码时抛出PageNotAnInteger
:当向page()
传递的不是一个整数时抛出EmptyPage
:当向page()
传递一个有效值,但该页面没有数据时抛出
Page 对象
创建对象
Paginator 对象的 page()
方法返回得到的对象,无需手动创建
属性
object_list
:当前页上所有数据(对象)的列表number
:当前页的页码值paginator
:当前page
关联的paginator
对象
方法
has_next()
:判断是否有下一页,如果有返回True
has_previous()
:判断是否有上一页,如果有返回True
has_other_pages()
:判断是否有上一页或下一页,如果有返回True
next_page_numbers()
:返回下一页的页码,如果不存在抛出InvalidPage
异常pervious_page_number()
:返回上一页的页码,如果不存在抛出InvalidPage
异常len()
:返回当前页的数据(对象)个数
实例演示
下面用一个学生列表分页的实例演示上述的方法。
首先配置 url:
re_path(r'^studentpage/(\d+)/$', views.studentpage),
定义视图函数:
from .models import Students
from django.core.paginator import Paginator
def studentpage(request, pageid):
# 所有学生列表
allList = Students.objects.all()
paginator = Paginator(allList, 2)
page = paginator.page(pageid)
return render(request, 'myApp/studentpage.html', {"students":page})
渲染对应的 studentpage 模板:
<body>
<ul>
{% for stu in students %}
<li>
{{stu.sname}}--{{stu.sgrade}}
</li>
{% endfor %}
</ul>
</body>
浏览器中输入第一页的 url 查看第一页的数据:
可以在此基础上添加按钮进行页面展示。
渲染模板中添加:
<ul>
{% for index in students.paginator.page_range %}
{% if index == students.number %}
<li>{{index}}</li>
{% else %}
<li>
<a href="/studentpage/{{index}}/">{{index}}</a>
</li>
{% endif %}
{% endfor %}
</ul>
点击页面按钮,跳转页面并将当前页的页码置为无法点击:
ajax
需要动态生成,请求 JSON 数据。我们通过点击按钮显示学生列表,获取 JSON 数据。
首先新建 ajaxstudents.html,添加下面的内容:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="/static/myApp/js/jquery-3.1.1.min.js"></script>
</head>
<body>
<h1>学生信息列表</h1>
<button id="btn">显示学生信息</button>
<script type="text/javascript" src="/static/myApp/js/sunck.js"></script>
</body>
配置 url 后得到页面显示为:
然后在 sunck.js 中添加下面的内容,获取 JSON 数据:
$(document).ready(function() {
document.getElementById("btn").onclick = function(){
$.ajax({
type:"get",
url:"/studentsinfo/",
dataType:"json",
success:function(data, status){
console.log(data)
}
})
}
})
视图中获取学生列表,并传递 JSON 数据:
from django.http import JsonResponse
def studentsinfo(request):
stus = Students.objects.all()
list = []
for stu in stus:
list.append([stu.sname, stu.sage])
return JsonResponse({"data": list})
成功在 Console 中得到了学生列表的 JSON 数据:
然后需要将学生列表作为标签插入到模板中,修改 sunck.js 中的 success:function
为:
success:function(data, status){
console.log(data)
var d = data["data"]
for(var i = 0; i < d.length; i++){
document.write('<p>'+d[i][0]+'</p>')
}
}
点击按钮,显示学生列表:
富文本
安装
直接使用命令 pip install django-tinymce
进行安装
在站点中使用
我们平时写博客时,会有一些加粗、斜体的文字编辑功能,这就是富文本。
首先配置 settings.py 文件,在 INSTALLED_APPS
中添加:
INSTALLED_APPS = [
……
'tinymce'
]
并在文件最后添加下面的代码。advanced 主题可能会出问题,在没有默认配置时 tinymce 会自动确定配置,直接删除即可。
# 富文本
TINYMCE_DEFAULT_CONFIG = {
# 'theme': 'advanced', # 配置模式
'width': 600,
'height': 400,
}
在 models.py 中再创建一个模型:
from tinymce.models import HTMLField
class Text(models.Model):
str = HTMLField() # 大文本类型
重新迁移,迁移步骤见【跑通 Django】。
然后注册 admin,相关讲解见【Django 站点管理】。在 admin.py 中添加:
from .models import Text
admin.site.register(Text)
使用命令 python manage.py createsuperuser
创建管理员用户。进入 admin 界面,在 Text 中点击 Add 添加,可以看到富文本:
在自定义视图中使用
首先写一个 edit.html 模板:
<head>
<meta charset="UTF-8">
<title>富文本</title>
<!--没有tiny_mce.js会自动创建-->
<script type="text/javascript" src="/static/tiny_mce/tiny_mce.js"></script>
<!--将textarea标签变为富文本-->
<script type="ext/javascript">
tinyMCE.init({
'mode': 'textarea',
'theme': 'advanced',
'width': 800,
'height': 600,
})
</script>
</head>
<body>
<form action="/saveedit/" method="post">
<textarea name="str">Mike is a good man</textarea>
<input type="submit" value="提交"/>
</form>
</body>
在 saveedit 中定义视图,对提交的博客内容进行保存即可。