Django 之 三大系统


路由系统 - urls.py

基本用法(完全匹配, 正则匹配, 别名, 子路由)

  • 总 urls.py
    from django.urls import path, re_path, include
    from main_page import views as main_page_views
    from host import urls as host_urls
    
    urlpatterns = [
        # path 模块: 完全匹配, 包括最后的斜线
        # name 参数: 为路由设置别名, 供 view 视图中 redirect(reverse()) 使用
        # 路由结尾的斜线强烈建议写上, 否则可能会因为这个报错
        path("index/", main_page_views.index, name="index"),
    
    	# re_path 模块: 根据正则规则匹配, 以 r 开头
        re_path(r"^main_page/", main_page_views.main_page),
    
    	# include 方法: 引出子路由 
        re_path(r"^host/", include(host_urls)),
    ]
    
    
  • 子 urls.py
    from django.urls import path
    from host import views
    
    urlpatterns = [
        # 匹配条目: host/add 
        path("add/", views.add),
    ]
    
    
  • views.py
    from django.shortcuts import render, redirect, HttpResponse
    from django.urls import reverse
    
    # Create your views here.
    
    
    def index(request):
        return HttpResponse("index")
    
    
    def main_page(request):
    	# 此处对应路由系统中别名的使用
        return redirect(reverse("index"))
    
    

传参用法(位置参数, 关键字参数)

  • urls.py
    # 必须使用 re_path 模块
    from django.urls import re_path
    
    urlpatterns = [
        # 位置参数
    	re_path(r"re1/(\d+)/(\d+)/$", views.re_1),
    
    	# 关键字参数, 按变量名传参
    	# 第一个位置的变量名是 num2, 第二个位置的变量名是 num1
    	re_path(r"^re2/(?P<num2>\d+)/(?P<num1>\d+)", main_page_views.re_2),
    ]
    
    
  • views.py
    # 接收位置参数
    def re_1(request, x, y):
    	# 参数拿过来的时候, 类型都是 string
        r = int(x) + int(y)
        return HttpResponse(r)
    
    
    # 接收关键字参数
    def re_2(request, num1, num2):
    	# 是根据传过来的参数的变量名
        return HttpResponse(num1+num2)
    
    

视图系统 - views.py

FBV 和 CBV

  • urls.py
    urlpatterns = [
        # FBV 和 CBV 的示例
        re_path("^FBV$", main_page_views.fbv),
        re_path("^CBV$", main_page_views.CBV.as_view()),
    ]
    
    
  • views.py
    # 需要导入 views 模块
    from django import views
    
    
    # FBV, Function
    def fbv(request):
    	return HttpResponse("FBV")	
    
    
    # CBV, Class, 继承 views.View
    class CBV(views.View):
    	# 常用的 4 种请求方式
    	def get(self, request):
    	    return HttpResponse("CBV - get")
    
        def post(self, request):
            return HttpResponse("CBV - post")
    
        def put(self, request):
            return HttpResponse("CBV - put")
    
        def delete(self, request):
            return HttpResponse("CBV - del")
    	
    

给 CBV 加装饰器

from django.utils.decorators import method_decorator

# 这是个装饰器
def wrapper(func):
    def inner(*args, **kwargs):
        ret = func(*args, **kwargs)
        return ret
    return inner


class Asset(views.View):
  
    def get(self, request):
        pass

	# 使用 method_decorator装饰器, 并且将需要使用的装饰器作为参数传给它
	@method_decorator(wrapper)
    def post(self, request):
        pass
        

直接返回 json 格式 - JsonResponse 模块

  • views.py
    # 需要导入 JsonResponse 模块
    # django 实现序列化, 默认只支持字典
    # safe = False 时可以返回其他类型
    from django.http import JsonResponse
    
    
    # 第一种, 默认情况下, 只有是 dict 类型才能使用 JsonResponse 返回, 返回其他类型会报错
    def json1(request):
        r = {"a": 1, "b": 2}
        return JsonResponse(r)
        
    # 如果想返回其他类型, 需要加 safe=False 的参数
    def json2(request):
        r = [1, 2, 3, 4]
        return JsonResponse(r, safe=False)
    
    

template – 模板系统

  • 在 templates 目录下寻找 html 文件
  • 查找顺序: 项目 templates 目录 --> app 内 templates 目录

变量语法示例 - {{ }}

  • views.py
    # 为了配合演示, 将视图系统中的数据做展示
    def index(request):
        # 做假数据
        name = "Tim"                                    # 单纯的变量
        score1 = {"math": 99, "chinese": 98}            # dict
        score2 = ["math", "chinese"]                    # list
        english_score1 = ""                             # 空值
        english_score2 = "默认值 - 不是空值"               # 空值
        filesize = 10240000                             # 文件大小
        link = "<a href=http://www.baidu.com>baidu</a>" # 超链接
    
        return render(request, "test.html", {
            "name": name,
            "score1": score1,
            "score2": score2,
            "english_score1": english_score1,
            "english_score2": english_score2,
            "today": today,
        	"filesize": filesize,
            "link": link,
            {{ today|date:"Y-m-d H:m:s" }}
            # 也可以用这个方式将内部所有变量进行返回
            "data": locals()}
                      )
                  
    
  • test.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {{ name }}<br>
        {{ score1.math }}<br>
        {{ score2.0 }}<br>
        {{ english_score1|default:"数据暂时为空" }}<br>
        {{ english_score2|default:"数据暂时为空" }}<br>
        {{ filesize|filesizeformat }}<br>
        {{ today|date:"Y-m-d H:m:s" }}<br>
        {{ link }}<br>
        {{ link|safe }}<br>
    </body>
    </html>
    
    
  • 结果
    在这里插入图片描述

循环语法示例 - {% %}

  • views.py
    def index(request):
        l1 = [100, 200, 300, "", 500]
        l2 = []
        return render(request, "test.html", {"data": locals()})
    
    
  • test.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        l1 结果:<br>
        {% for i in data.l1 %}
            <!-- 循环的序号 -->
            序号:
            {{ forloop.counter }}
    
            <!-- 判断, 如果不是最后一个, 需要换行 -->
            值:
            {% if forloop.last %}
                {{ i|default:"空值" }}
            {% else %}
                {{ i|default:"空值" }}<br>
            {% endif %}
    
        {% empty %}
            "数据整个为空"
        {% endfor %}
    
        <br>==========<br>
    
        l2 结果:<br>
        {% for i in data.l2 %}
            <!-- 循环的序号 -->
            序号:
            {{ forloop.counter }}
    
            <!-- 判断, 如果不是最后一个, 需要换行 -->
            值:
            {% if forloop.last %}
                {{ i|default:"空值" }}
            {% else %}
                {{ i|default:"空值" }}<br>
            {% endif %}
    
        {% empty %}
            "数据整个为空"
        {% endfor %}
    </body>
    </html>
    
    
  • 图示
    在这里插入图片描述

配合路由别名使用 - {% url %}

  • urls.py
    from django.contrib import admin
    from django.urls import path, re_path, include
    from index import views as index_views
    from host import urls as host_urls
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path("login", index_views.login, name="denglu"),
        re_path(r"^login1/(\d+)/", index_views.login1, name='denglu1'),
        re_path(r"^login2/(?P<pk>\d+)/", index_views.login2, name='denglu2'),
    ]
    
    
  • view.spy
    def login(request):
    	return render(request, "login.html")
    
    
    def login1(request, arg1):
        return render(request, "login1.html")
    
    
    def login2(request, pk):
        return render(request, "login2.html")
    
    
  • html
    <!-- login.html, 不带参数-->
    {% url "denglu" data %}
    
    <!-- login1.html, 带位置参数 -->
    {% url "denglu1" data %}
    
    <!-- login2.html, 带关键字参数 -->
    {% url "denglu2" data %}
    	
    

母版和组件

  • 母版文件
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
        <title>
            {% block page_title %}
    			标题的位置
            {% endblock %}
        </title>
    
        <link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
        {% block page_css %}
        	单页面引入 css 文件位置
        {% endblock %}
    </head>
    <body>
        <div class="row">
            <div>
    
            </div>
        </div>
        <div class="container">
            <div class="row" style="margin-top: 70px">
                {% block page_main %}
                	页面代码位置
                {% endblock %}
            </div>
        </div>
    
        <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
        <script src="/static/jQuery/jQuery3.4.1.min.js"></script>
        <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
        <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    
        {% block page_js %}
        	单页面引入 js 文件位置
        {% endblock %}
    </body>
    </html>
    
    
  • 组件, 文件名为 zujian.html
    <p> 这是一个组件文件 </p>
    
    
  • 引入母版和组件
    # 引入母版文件
    {% extends "base.html" %}
    
    # 填充非公用代码
    {% block page_title %}
    	主页
    {% endblock %}
    
    {% block page_main %}
    	<p><a href="/index/">主页</a></p>
    	# include 引入组件, 导入文件名即可
    	{% include "zujian.html" %}
    {% endblock %}
    
    

使用实例

上传文件

  • views.py
    class Upload(views.View):
        
        def get(self, request):
            return render(request, "test.html")
    
        def post(self, request):
            # 保存文件
            file_obj = request.FILES.get("code")
            # 拿到文件名
            filename = file_obj.name
            with open(filename, "wb") as f:
                # 往文件句柄中写入
                # chunk()是 django 自带的方法, 更加标准
                for i in file_obj.chunks():  
                    f.write(i)
            return HttpResponse("上传成功")
    
    
  • test.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <!-- 上传文件的时候一定要写明 enctype -->
        <form action="" method="post" enctype="multipart/form-data">
            <input type="file" name="code">
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    
    

多选示例

  • views.py
    class AuthorEdit(views.View):
    
    def get(self, request, id):
        author = models.Author.objects.filter(id=id).first()
        books = models.Book.objects.all()
        return render(request, "author_edit.html", {"author": author, "books": books})
    
    def post(self, request, id):
        name = request.POST.get("author")
        # getlist 表示取多选数据
        books = request.POST.getlist("books")
    
        author_obj = models.Author.objects.filter(id=id).first()
        author_obj.name = name
        author_obj.books.set(books)
        author_obj.save()
    
        return redirect("/author_list/")
    
  • author_edit.html
    {% extends "mom.html" %}
    
    {% block html_title %}
    编辑作者
    {% endblock %}
    
    {% block html_main %}
        <form action="" method="post">
            {% csrf_token %}
            <p>
                作者:
                <input type="text" name="author" value="{{ author.name }}">
            </p>
            <p>
                书名:
                <select name="books" multiple>
                    {% for foo in books %}
                        {% if foo in author.books.all %}
                        	# selected 表示选中
                            <option selected value="{{ foo.id }}">{{ foo.title }}</option>
                        {% else %}
                            <option value="{{ foo.id }}">{{ foo.title }}</option>
                        {% endif %}
                    {% endfor %}
                </select>
    
                {% for i in books %}
                    {% if i in author.books.all %}
                    	# checked 表示选中
                        <p><input checked type="checkbox" name="books" value="{{ i.id }}">{{ i.title }}</p>
                    {% else %}
                        <p><input type="checkbox" name="books" value="{{ i.id }}">{{ i.title }}</p>
                    {% endif %}
                {% endfor %}
    
            </p>
            <p><input type="submit" value="修改"></p>
        </form>
    {% endblock %}
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值