0
点赞
收藏
分享

微信扫一扫

Django 之 三大系统



文章目录

  • 路由系统 - urls.py
  • 基本用法(完全匹配, 正则匹配, 别名, 子路由)
  • 传参用法(位置参数, 关键字参数)
  • 视图系统 - views.py
  • FBV 和 CBV
  • 给 CBV 加装饰器
  • 直接返回 json 格式 - JsonResponse 模块
  • template -- 模板系统
  • 变量语法示例 - {{ }}
  • 循环语法示例 - {% %}
  • 配合路由别名使用 - {% url %}
  • 母版和组件
  • 使用实例
  • 上传文件
  • 多选示例


路由系统 - 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 条评论