【Django】高级用法

本文为 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,得到值:

aGKxH0.png

再显示一张图片,在 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 中定义视图,对提交的博客内容进行保存即可。

猜你喜欢

转载自blog.csdn.net/weixin_44413191/article/details/107761948