Django模板

Django模板

在项目迭代流程中,前端页面都会进行大量的修改,如果将页面放到视图函数中,那么当对前端页面修改的时候,也会使得视图函数发生变化,大大加重了后端的负担。从 MTV 设计模式的角度出发,视图层是实现业务逻辑的,在视图层编写代码和编写 HTML 页面是两项可以相互独立的工作。

在 Django 中我们把 “模板” 称之为 Template,是设计模式中的 T 层,模板用于编写html代码,还可以嵌入模板代码转换更方便的完成页面开发,再通过在视图中渲染模板,将生成模板的设计实现了业务逻辑视图与显示内容模板的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。

模板系统的配置

其实 T 层应用是这样实现的,当创建好一个 Django 项目后,在项目的同级目录下(或在应用目录下)创建一个名为 templates 文件夹,对它进行简单的配置后,这个文件夹将被 Django 自动识别。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]
TEMPLATES 变量内容解析:
  • BACKEND : Django默认设置,指定了要是用的模板引擎的 Python 路径;
  • DIRS : 一个目录列表,指定模板文件的存放路径,可以是一个或者多个。模板引擎将按照列表中定义的顺序查找模板文件;
  • APP_DIRS : 一个布尔值,默认为 Ture,表示会在安装应用中的 templates 目录中搜索所有模板文件;当值为 Ture时,可不用在DIRS参数中添加在应用中的templstes文件夹
  • OPTIONS : 指定额外的选项,不同的模板引擎有着不同的可选参数。
# 一般情况下,是直接在项目根目录下创建templates文件夹,设置 TEMPLATES 的 DIRS 值则为
'DIRS': [os.path.join(BASE_DIR,'templates')]

# dirs为空时,默认的templates位置为app下
'DIRS': []

模板响应

html内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板响应</title>
</head>
<body>
    <h1>第一次模板响应</h1>
</body>
</html>

views视图函数

from django.shortcuts import render


def home(request):
    return render(request, 'equipment/home.html')

urls配置

from django.urls import path
from . import views

app_name = 'equipment'

urlpatterns = [
    path('home/', views.home, name='home'),
]

主路由配置

from django.urls import path, include

urlpatterns = [
    path('equip/', include('equipment.urls')),
]

响应内容

在这里插入图片描述

模板传参

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板响应传参</title>
</head>
<body>
    <h1>第一次模板响应{{info}}</h1>
</body>
</html>

模板传参:

第一次模板响应{{info}}

中使用{{}}括起来的内容是一个模板的变量,其中event_list是变量名,用于接收视图函数中传递的数据

views视图

def home(request):
    info = "Hello World!!"
    return render(request, 'equipment/home.html', context={'info': info})

带参数响应

在这里插入图片描述

render方法: render 是 View 层加载模板的一种方式,它封装在 django.shortcuts 模块中,它的作用是结合一个给定的模板和一个给定的字典,并返回一个渲染后的 HttpResponse 对象。通俗的讲就是把字典格式的内容, 加载进 templates 目录中定义的 HTML 文件, 最终通过浏览器渲染呈现。

render(request, template_name, context=None, content_type=None, status=None, using=None)

render方法参数解析:

request: 是一个固定参数,用于生成响应的请求对象;

template_name: templates 中定义的文件, 要注意路径名. 比如html文件所在路径为 templates\home\index.html, 参数就要写home\index.html;

context: 要传入文件中用于渲染呈现的数据, 默认是字典格式;内容为{‘模板变量’:视图函数变量}

content_type: 生成的文档要使用的媒体格式类型。默认为 DEFAULT_CONTENT_TYPE 设置的值;

status: http 的响应代码,默认是 200;

using: 用于加载模板使用的模板引擎的名称。

request、template_name、context为必传参数

模板语法

模板分为静态部分和动态部分,其中动态部分主要就是模板语言,下面通过模板变量、标签、过滤器、注释几个方面进行说明。

模板变量

通过后端传递在前端html页面当中通过模板语法获取变量的值

from django.shortcuts import render


def hello(request):
    
    text = "Hello World !"
    
    return render(request, 'equipment/hello.html', context={"text": text})

设置路由

from django.urls import path
from . import views

app_name = 'equipment'

urlpatterns = [
    path('hello/', views.hello, name='hello'),
]

在equipment/templates/equipment当中创建hello.html文件,编写内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello World</title>
</head>
<body>
    <h1 style="text-align: center; color: crimson">{{ text }}</h1>
</body>
</html>

效果展示

在这里插入图片描述

标签

模板中的常见标签有for、if、比较运算符、布尔运算符等

for语法的使用
from django.shortcuts import render


def goods_list(request):

    shop_list = [
        {'id': 1, 'name': '华为P60Pro焕彩紫', 'cate': '手机', 'memory': '8G', 'rom': '128G', 'price': '5499.00'},
        {'id': 2, 'name': '华为P60天空蓝手机', 'cate': '手机', 'memory': '8G', 'rom': '256G', 'price': '5699.00'},
        {'id': 3, 'name': '华为Meta60手机', 'cate': '手机', 'memory': '12G', 'rom': '512G', 'price': '6999.00'},
    ]

    return render(request, 'equipment/goods.html', context={'goods_list': shop_list})

设置路由

from django.urls import path
from . import views

app_name = 'equipment'

urlpatterns = [
    path('goods_list/', views.goods_list, name='goods_list'),
]

在equipment/templates/equipment下创建goods_list.html文件,添加内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>手机信息展示页面</title>
</head>
<body>
    <div style="width: 80%; margin: 50px auto; text-align: center">
        <table border="1" style="text-align: center; width: 100%; " >
            <tr >
                <th>编写</th>
                <th>名称</th>
                <th>内存</th>
                <th>存储</th>
                <th>价格</th>
                <th>分类</th>
            </tr>
            {% for goods in goods_list %}
                <tr >
                    <td>{{ goods.id }}</td>
                    <td>{{ goods.name }}</td>
                    <td>{{ goods.memory }}</td>
                    <td>{{ goods.rom }}</td>
                    <td>{{ goods.price }}</td>
                    <td>{{ goods.cate }}</td>
                </tr>
            {% endfor %}
        </table>
    </div>
</body>
</html>

效果展示

在这里插入图片描述

if语句

隔行变色

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>手机信息展示页面</title>
</head>
<body>
    <div style="width: 80%; margin: 50px auto; text-align: center">
        <table border="1" style="text-align: center; width: 100%; " >
            <tr >
                <th>编写</th>
                <th>名称</th>
                <th>内存</th>
                <th>存储</th>
                <th>价格</th>
                <th>分类</th>
            </tr>
            {% for goods in goods_list %}
                {% if forloop.counter|divisibleby:"2" %}
                    <tr style="background:gray">
                {% else %}
                    <tr>
                {% endif %}
                    <td>{{ goods.id }}</td>
                    <td>{{ goods.name }}</td>
                    <td>{{ goods.memory }}</td>
                    <td>{{ goods.rom }}</td>
                    <td>{{ goods.price }}</td>
                    <td>{{ goods.cate }}</td>
                </tr>
            {% endfor %}
        </table>
    </div>
</body>
</html>

效果展示

在这里插入图片描述

过滤器
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>手机信息展示页面</title>
</head>
<body>
    <div style="width: 80%; margin: 50px auto; text-align: center">
        <table border="1" style="text-align: center; width: 100%;" >
            <tr >
                <th>编写</th>
                <th>名称</th>
                <th>内存</th>
                <th>存储</th>
                <th>价格</th>
                <th>分类</th>
                <th>发布日期</th>
            </tr>
            {% for goods in goods_list %}
                {% if forloop.counter|divisibleby:"2" %}
                    <tr style="background:gray">
                {% else %}
                    <tr>
                {% endif %}

                    <td>{{ goods.id }}</td>
                    <td>{{ goods.name }}</td>
                    <td>{{ goods.memory }}</td>
                    <td>{{ goods.rom }}</td>
                    <td>{{ goods.price }}</td>
                    <td>{{ goods.cate }}</td>
                    <td>{{ goods.pub_date | date:'Y-m-d' }}</td>
                </tr>
            {% endfor %}
        {% comment %}
        多行注释,在这里编写注释内容
        {% endcomment %}
        {#        <h1></h1>#}
        </table>
    </div>
</body>
</html>

效果展示

在这里插入图片描述

自定义过滤器

自定义过滤器,处理价格,在价格的前后分别加上字符: ¥ 和 元

在app的目录下,创建templatetags文件夹,文件夹中要有__init__.py文件。

创建过滤器的文件时要以filter_name的形式进行。如处理价格: filter_price.py

from django.template import Library

# 创建Library对象
register = Library()


# 使用装饰器进行处理,定义求余函数filterid(),将num对2求余
@register.filter()
def filter_price(num):
    return f"¥{num}元"

在html当中使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>手机信息展示页面</title>
</head>
<body>
    <div style="width: 80%; margin: 50px auto; text-align: center">
        {% load filter_price %}
        <table border="1" style="text-align: center; width: 100%;" >
            <tr >
                <th>编写</th>
                <th>名称</th>
                <th>内存</th>
                <th>存储</th>
                <th>价格</th>
                <th>分类</th>
                <th>发布日期</th>
            </tr>
            {% for goods in goods_list %}
                {% if forloop.counter|divisibleby:"2" %}
                    <tr style="background:gray">
                {% else %}
                    <tr>
                {% endif %}

                    <td>{{ goods.id }}</td>
                    <td>{{ goods.name }}</td>
                    <td>{{ goods.memory }}</td>
                    <td>{{ goods.rom }}</td>
                    <td>{{ goods.price | filter_price}}</td>
                    <td>{{ goods.cate }}</td>
                    <td>{{ goods.pub_date | date:'Y-m-d' }}</td>
                </tr>
            {% endfor %}
        {% comment %}
        多行注释,在这里编写注释内容
        {% endcomment %}
        {#        <h1></h1>#}
        </table>
    </div>
</body>
</html>

效果展示

在这里插入图片描述

模板继承

继承模板主要是为了提高代码重用性或减少代码冗余率,以减少开发人员的工作量。

在templates下先创建个base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}</title>
    {% block css %}
    {% endblock %}
</head>
<body>
    {% block content %}

    {% endblock %}
</body>
</html>

子模板创建,并继承父模板

在equipment/templates/equipment/pages/目录下创建login.html文件,编写内容如下:

{% extends 'equipment/base.html' %}

{% block title %} 用户登录页面 {% endblock %}

{% block css %}
    <style>
        .login_div {
            margin: 150px auto;
            text-align: center;
        }
    </style>
{% endblock %}

{% block content %}
    <div class="login_div">
        <form action="" method="post">
            <p>姓名: <input type="text"></p>
            <p>密码: <input type="text"></p>
            <p><input type="submit" value="登录"></p>
        </form>
    </div>
{% endblock %}

编写views视图,对页面进行渲染

from django.shortcuts import render


def login(request):
    return render(request, 'equipment/pages/login.html')

编写路由

from django.urls import path
from . import views

app_name = 'equipment'

urlpatterns = [
    path('login/', views.login, name='login'),
]

效果展示

在这里插入图片描述

模板传参

post提交表单

views.py视图

from django.contrib.auth.hashers import make_password, check_password
from django.shortcuts import render

from django.views import View
from equipment.models import User


class RegisterView(View):

    def get(self, request):
        return render(request, 'equipment/register.html')

    def post(self, request):
        username = request.POST.get('username')
        password1 = request.POST.get('password1')
        password2 = request.POST.get('password2')
        email = request.POST.get('email')

        if password1 != password2:
            return render(request, 'equipment/register.html', context={'message': '两次密码不一致!'})

        user_obj = User.objects.filter(username=username).first()

        if user_obj:
            return render(request, 'equipment/register.html', context={'message': '用户已存在!'})

        User.objects.create(username=username, password=make_password(password1), email=email)

        return render(request, 'equipment/register.html', context={'message': '用户注册成功!'})


class LoginView(View):
    """
    登录视图
    """

    def get(self, request):
        return render(request, 'equipment/login.html')

    def post(self, request):
        """
        用户登录
        """
        username = request.POST.get('username')
        password = request.POST.get('password')

        user_obj = User.objects.filter(username=username).first()
        if user_obj is None:
            return render(request, 'equipment/login.html', context={'message': '用户不存在'})

        if check_password(password, user_obj.password):
            return render(request, 'equipment/index.html', context={'username': user_obj.username})

        else:
            return render(request, 'equipment/login.html', context={'message': '密码不正确'})

路由配置

from django.urls import path
from . import views

app_name = 'equipment'

urlpatterns = [
    path('register/', views.RegisterView.as_view(), name='register'),
    path('login/', views.LoginView.as_view(), name='login'),
]

html页面

bash页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}</title>
    {% block css %}
    {% endblock %}
</head>
<body>
    {% block content %}
    {% endblock %}
</body>
</html>

register

{% extends 'equipment/base.html' %}

{% block title %} 注册页面 {% endblock %}

{% block css %}
    <style>
        .register_div {
            margin: 150px auto;
            text-align: center;
        }
    </style>
{% endblock %}

{% block content %}

    <div class="register_div">

        <form action="{% url 'equipment:register' %}" method="post">

            {% csrf_token %}
            <p>&ensp;&ensp;名:<input type="text"  name="username"></p>
            <p>&emsp;&emsp;码:<input type="password"  name="password1"></p>
            <p>确认密码:<input type="password" name="password2"></p>
            <p><input type="submit" value="注册"> <a href="{% url 'equipment:login' %}">有账号,去登录</a></p>
        </form>
    </div>

{% endblock %}

login页面

{% extends 'equipment/base.html' %}

{% block title %} 登录页面 {% endblock %}

{% block css %}
    <style>
        .login_div {
            margin: 150px auto;
            text-align: center;
        }
    </style>
{% endblock %}

{% block content %}
    <div class="login_div">
        <form action="{% url 'equipment:login' %}" method="post">
            {% csrf_token %}
            <p>用户名:<input type="text" name="username"></p>
            <p>&emsp;码:<input type="password" name="password"></p>
            <p><input type="submit" value="登录"> &emsp; <a href="{% url 'equipment:register' %}">没有账号,去注册</a></p>
        </form>
    </div>
{% endblock %}

index页面

{% extends 'equipment/base.html' %}
{% block title %} 首页 {% endblock %}

{% block content %}

    <h1>首页展示</h1>

{% endblock %}

页面效果展示

在这里插入图片描述

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值