Django 模板分割及多语言支持案例【需求文档】-->【实现方案】

Django 模板分割及多语言支持案例

这个案例旨在提供一个清晰的示范,展示如何将复杂的页面分解为多个可复用的模板组件,使代码更加模块化和易于管理。希望这篇案例文章对你有所帮助。

概述
在 Django 项目开发中,使用模板分割和多语言支持能有效提升代码的可维护性和用户体验。本案例通过一个简单的博客项目,展示如何将 Django 模板拆分为多个文件,并实现多语言支持。

需求文档

  1. 背景
    在开发Django项目时,将模板分割成多个文件并实现多语言支持是提高代码可维护性和用户体验的重要方法。本项目旨在展示如何使用Django模板进行模块化开发和多语言支持。通过一个简单的博客项目,我们将实现页面分割、文章列表显示及商品信息展示,并根据语言切换进行动态更新。

  2. 功能需求
    2.1 基础模板

功能:存储页面的基础配置,提供页面结构和通用样式。

文件名:base.html

详细描述:

包含HTML头部信息。

提供通用的样式定义。

定义内容插入块 {% block content %},供其他页面继承和填充内容。

2.2 主页模板

功能:显示主页内容,包含语言切换选项和文章列表。

文件名:home.html

详细描述:

继承自 base.html。

定义页面标题块 {% block title %}。

显示当前语言。

提供语言切换下拉菜单。

插入文章列表模板 {% include “article_list.html” %}。

2.3 文章列表模板

功能:循环显示文章列表,根据当前语言显示相应的文章标题和概括。

文件名:article_list.html

详细描述:

使用 {% for %} 循环显示所有文章。

根据当前语言显示中文或英文文章标题及概括。

插入相应语言的商品列表模板 {% include “products_list_cn.html” %} 或 {% include “products_list_en.html” %}。

2.4 中文商品列表模板

功能:显示文章中的商品列表,最多显示5个商品。

文件名:products_list_cn.html

详细描述:

根据是否存在商品标题,动态插入商品部分模板 {% include “products_part_1_cn.html” %} 至 {% include “products_part_5_cn.html” %}。

2.5 商品部分模板

功能:显示具体的商品信息。

文件名:products_part_1_cn.html 至 products_part_5_cn.html

详细描述:

显示商品标题、概括和图片。

根据商品信息动态生成页面内容。

  1. 界面展示
    3.1 主页

当前语言:显示当前选择的语言。

语言切换:提供语言选择下拉菜单,用户可切换语言。

文章列表:根据选择的语言显示对应的文章标题和概括。

商品列表:根据文章显示对应的商品列表和详细信息。

3.2 文章与商品展示

文章标题:根据语言显示中文或英文标题。

文章概括:显示文章的简短概括,并根据语言切换。

商品信息:根据语言动态显示商品标题、概括和图片。

  1. 业务逻辑
    4.1 模板继承

home.html 继承自 base.html,提供页面的基础结构和通用样式。

使用 {% block title %} 和 {% block content %} 定义可插入内容。

4.2 语言切换

在 home.html 中提供语言切换下拉菜单,并通过 JavaScript 实现页面语言切换。

根据选择的语言参数 current_language 动态加载文章和商品内容。

4.3 文章与商品显示

使用 {% for article in articles %} 循环遍历所有文章。

根据 current_language 判断显示中文或英文的文章标题和概括。

根据文章中的商品信息,动态加载相应的商品部分模板。

  1. 总结
    通过本需求文档,我们详细描述了Django项目中模板分割与多语言支持的实现方法。项目包含基础模板、主页模板、文章列表模板和商品部分模板,并通过语言切换动态加载对应内容,提升了代码的可维护性和用户体验。

具体实现

基础模板:base.html
基础模板 base.html 用于存储页面的基础配置,并可被其他页面继承和调用。它包含了 HTML 头部信息和页面主体结构:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{% block title %}主页{% endblock %}</title>
    <!-- Google Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet" />
    <!-- Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        body {
            font-family: 'Roboto', sans-serif;
        }

        .hover-arrow::after {
            content: '>';
            color: #a0aec0;
            right: 0px;
            position: absolute;
            font-weight: bold;
            font-size: 24px;
            width: 25px;
            height: 36px;
            top: 25px;
        }
    </style>
</head>
<body class="bg-gray-900 text-white">
    <div class="max-w-3xl mx-auto py-8 px-4">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

主页模板:home.html
主页模板 home.html 继承自 base.html,并包含页面标题、语言切换选项和文章列表:

{% extends "base.html" %}

{% block title %}主页{% endblock %}

{% block content %}
    <div class="mb-4">
        <span class="text-white text-xl font-bold">当前语言: {{ current_language }}</span>
    </div>
    <div class="mb-4">
        <label for="language-select" class="text-white text-xl">选择语言: </label>
        <select id="language-select" onchange="changeLanguage(this)">
            <option value="cn" {% if current_language == 'cn' %}selected{% endif %}>简体中文</option>
            <option value="en" {% if current_language == 'en' %}selected{% endif %}>English</option>
        </select>
    </div>
    {% include "article_list.html" %}
    <script>
        function changeLanguage(select) {
            const lang = select.value;
            const url = new URL(window.location.href);
            url.searchParams.set('lang', lang);
            window.location.href = url.toString();
        }
    </script>
{% endblock %}

文章列表模板:article_list.html
article_list.html 用于循环显示文章列表,根据当前语言显示相应的标题和文章概括,并插入商品列表模板:

{% for article in articles %}
<br>

{% if article.title_en and current_language == 'en' %} 
 <div class="flex items-center mb-6">
    <div class="w-8 h-8 bg-orange-500 rounded-full flex items-center justify-center">
        <span class="text-white text-xl font-bold">Hot</span>
    </div>
    <div class="ml-3">
        <h1 class="text-lg font-bold">
            <a href="/article/{{ article.id }}/?lang={{ current_language }}" class="text-blue-400 hover:underline">
                {{ article.title_en }}
            </a>
        </h1>
    </div>
</div>
<p class="text-gray-400 mb-6 leading-relaxed">
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    {% with summary=article.summary_en|default_if_none:""|slice:":80" %}
    {{ summary|ljust:80 }}
    {% endwith %}
</p>
{% include "products_list_en.html" %}
{% endif %}

{% if article.title_cn and current_language == 'cn' %} 
 <div class="flex items-center mb-6">
    <div class="w-8 h-8 bg-orange-500 rounded-full flex items-center justify-center">
        <span class="text-white text-xl font-bold"></span>
    </div>
    <div class="ml-3">
        <h1 class="text-lg font-bold">
            <a href="/article/{{ article.id }}/?lang={{ current_language }}" class="text-blue-400 hover:underline">
                {{ article.title_cn }}
            </a>
        </h1>
    </div>
</div>
<p class="text-gray-400 mb-6 leading-relaxed">
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    {% with summary=article.summary_cn|default_if_none:""|slice:":80" %}
    {{ summary|ljust:80 }}
    {% endwith %}
</p>
{% include "products_list_cn.html" %}
{% endif %}

{% endfor %}

商品列表模板:products_list_cn.html
products_list_cn.html 用于显示中文商品列表。根据该篇文章是否插入商品,最多5个,最少0个 来进行显示:

<div class="space-y-4">
    {% if article.product_1_title_cn %}
        {% include "products_part_1_cn.html" %}
    {% endif %}
    {% if article.product_2_title_cn %}
        {% include "products_part_2_cn.html" %}
    {% endif %}
    {% if article.product_3_title_cn %}
        {% include "products_part_3_cn.html" %}
    {% endif %}
    {% if article.product_4_title_cn %}
        {% include "products_part_4_cn.html" %}
    {% endif %}
    {% if article.product_5_title_cn %}
        {% include "products_part_5_cn.html" %}
    {% endif %}
</div>

商品部分模板:products_part_1_cn.html
products_part_1_cn.html 用于显示文章中的第一个商品:

<a href="{{ article.product_1_link_cn }}" class="block">
    <div class="relative bg-gray-800 p-4 rounded-lg hover:bg-gray-700 cursor-pointer hover-arrow transition-all">
        <h2 class="text-lg font-bold mb-1">
            {{ article.product_1_title_cn }}
        </h2>
        <p class="text-gray-400 text-sm" style="padding-right: 120px;">
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            {% with summary=article.product_1_summary_cn|default_if_none:""|slice:":80" %}
                {{ summary|ljust:80 }}
            {% endwith %}
        </p>
        {% if article.image_1 %}
        <div class="absolute top-2 right-12 w-16 h-16" 
             {% if article.tag_choice_1 == 'circle_image' %} style="border-radius: 50%; overflow: hidden;" 
             {% elif article.tag_choice_1 == 'square_image' %} style="border-radius: 0;" 
             {% elif article.tag_choice_1 == 'triangle_image' %} style="clip-path: polygon(50% 0%, 0% 100%, 100% 100%);" 
             {% elif article.tag_choice_1 == 'pentagon_image' %} style="clip-path: polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%);" 
             {% elif article.tag_choice_1 == 'hexagon_image' %} style="clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);" 
             {% else %} style="display: none;" 
             {% endif %}>
            <img src="{{ article.image_1 }}" alt="Article Image" class="w-full h-full object-cover">
        </div>
        {% endif %}
    </div>
</a>

商品部分模板:products_part_2_cn.html - products_part_5_cn.html
商品部分模板的配置方式类似于 products_part_1_cn.html。对于每个商品部分,都需要创建相应的模板文件 products_part_2_cn.html 到 products_part_5_cn.html,并按照上述方式进行配置。

这样一来,通过基础模板、主页模板、文章列表模板和商品部分模板的组合,可以实现页面的模块化开发和多语言支持,提高代码的可维护性和用户体验。

英文商品列表模板:products_list_en.html
products_list_en.html 用于显示英文商品列表。根据该篇文章是否插入商品,最多5个,最少0个来进行显示:

<div class="space-y-4">
    {% if article.product_1_title_en %}
        {% include "products_part_1_en.html" %}
    {% endif %}
    {% if article.product_2_title_en %}
        {% include "products_part_2_en.html" %}
    {% endif %}
    {% if article.product_3_title_en %}
        {% include "products_part_3_en.html" %}
    {% endif %}
    {% if article.product_4_title_en %}
        {% include "products_part_4_en.html" %}
    {% endif %}
    {% if article.product_5_title_en %}
        {% include "products_part_5_en.html" %}
    {% endif %}
</div>

英文商品部分模板:products_part_1_en.html
products_part_1_en.html 用于显示文章中的第一个英文商品:

<a href="{{ article.product_1_link_en }}" class="block">
    <div class="relative bg-gray-800 p-4 rounded-lg hover:bg-gray-700 cursor-pointer hover-arrow transition-all">
        <h2 class="text-lg font-bold mb-1">
            {{ article.product_1_title_en }}
        </h2>
        <p class="text-gray-400 text-sm" style="padding-right: 120px;">
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            {% with summary=article.product_1_summary_en|default_if_none:""|slice:":80" %}
                {{ summary|ljust:80 }}
            {% endwith %}
        </p>
        {% if article.image_1 %}
        <div class="absolute top-2 right-12 w-16 h-16" 
             {% if article.tag_choice_1 == 'circle_image' %} style="border-radius: 50%; overflow: hidden;" 
             {% elif article.tag_choice_1 == 'square_image' %} style="border-radius: 0;" 
             {% elif article.tag_choice_1 == 'triangle_image' %} style="clip-path: polygon(50% 0%, 0% 100%, 100% 100%);" 
             {% elif article.tag_choice_1 == 'pentagon_image' %} style="clip-path: polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%);" 
             {% elif article.tag_choice_1 == 'hexagon_image' %} style="clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);" 
             {% else %} style="display: none;" 
             {% endif %}>
            <img src="{{ article.image_1 }}" alt="Article Image" class="w-full h-full object-cover">
        </div>
        {% endif %}
    </div>
</a>

英文商品部分模板:products_part_2_en.html - products_part_5_en.html
英文商品部分模板的配置方式与 products_part_1_en.html 类似。对于每个商品部分,都需要创建相应的模板文件 products_part_2_en.html 到 products_part_5_en.html,并按照上述方式进行配置。

通过这些模板的组合和使用,可以学习如何在 Django 项目中使用模板继承与分割,以及如何实现多语言支持,从而提升项目的可维护性和用户体验。

为什么会使用这种自定义的方式?

虽然Django自带的翻译机制(i18n)是一个非常强大的工具,适用于大多数情况下的多语言支持,但在特定的需求和场景下,本文所采用的方法却有其不可替代的优势。以下是这些特定场景和需求的详细分析:

  1. 即时数据展示和内容管理
    优点:
    直接展示数据库内容:通过条件判断直接展示数据库中的多语言内容,无需在翻译文件之间进行中转,这可以确保数据的实时性和一致性。

便于内容管理:在一些需要频繁更新的项目中,如新闻网站或电子商务平台,内容管理人员可以直接在数据库中更新不同语言的内容,无需等待翻译文件的生成和编译。

  1. 灵活的模板定制
    优点:
    模板自定义:本文方法允许对不同语言的模板进行高度定制,例如,中文和英文模板可以有完全不同的布局和样式。这在一些文化差异较大的项目中尤为重要。

高度灵活:开发者可以针对不同语言版本进行不同的样式和内容调整,而不必受限于统一的翻译文件结构。这种灵活性在需要针对不同市场进行本地化优化时非常有用。

  1. 快速开发和原型设计
    优点:
    快速实现:不需要配置和管理翻译文件,开发者可以快速实现多语言支持,适用于项目初期的快速原型设计和验证。

低学习曲线:对于刚接触Django的开发者来说,不需要额外学习i18n的相关知识即可实现多语言支持,降低了开发难度和时间成本。

  1. 特定业务逻辑需求
    优点:
    复杂业务逻辑处理:在某些特定的业务需求下,需要在展示内容时进行复杂的逻辑判断和处理。例如,不同语言版本可能需要展示不同的广告或促销信息,这种情况下,通过模板条件判断可以更灵活地实现业务需求。

可扩展性:本文方法可以针对特定业务需求进行扩展,如在不同语言版本中显示不同的商品列表和内容,满足更加个性化的需求。

  1. 无需额外配置和依赖
    优点:
    简化配置:不需要依赖Django的中间件和配置,减少了系统依赖和配置复杂度,适用于一些简单的项目和开发环境。

减少出错可能:由于无需生成和编译翻译文件,减少了在这一步骤中可能出现的错误和不一致问题。

总结
虽然Django自带的翻译机制是处理多语言支持的最佳实践,但在特定需求和场景下,本文的方法提供了无法替代的灵活性和便捷性。这种方法在处理实时数据、定制化模板、快速开发和特定业务需求上具有明显优势,适用于一些需要快速实现、频繁更新和高度定制的项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/940794.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode:104.二叉树的最大深度

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;104.二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节…

Fastjson <= 1.2.47 反序列化漏洞复现

0x01 前言 Fastjson 是一个 Java 语言编写的高性能功能完善的 JSON 库&#xff0c;可以将 Java 对象转换为 JSON 格式&#xff0c;也可以将 JSON 字符串转换为 Java 对象&#xff0c;在中国和美国使用较为广泛。 0x02 漏洞成因 Fastjson < 1.2.68 版本在处理反序列化对象时…

python:函数

一、嵌套函数 1.1概念 嵌套函数是定义在另一个函数作用域内部的函数。外部函数可以访问其内部声明的嵌套函数&#xff0c;而嵌套函数则可以访问其外部函数的作用域&#xff08;包括参数和局部变量&#xff09;。 1.2实例 一般情况下&#xff0c;我们是这样书写嵌套函数的&a…

Linux 下的 GPT 和 MBR 分区表详解

文章目录 Linux 下的 GPT 和 MBR 分区表详解一、分区表的作用二、MBR&#xff08;Master Boot Record&#xff09;1. **特点**2. **优点**3. **缺点**4. **适用场景** 三、GPT&#xff08;GUID Partition Table&#xff09;1. **特点**2. **优点**3. **缺点**4. **适用场景** 四…

基于单片机的智能婴儿床监护系统多功能婴儿床摇篮系统

功能介绍 以STM32单片机为控制核心蓝牙传输控制可以进行哭闹检测、尿床检测、音乐播放、语音提醒、哭闹时可以进行摇床有不同的模式自动模式和睡眠模式 实物可做&#xff0c;其他功能也可以 电路图 PCB 源代码 u8 Temperature_High; //室内温度高阈值 u8 Temperature_…

人工智能在VR展览中扮演什么角色?

人工智能&#xff08;AI&#xff09;在VR展览中扮演着多重关键角色&#xff0c;这些角色不仅增强了用户体验&#xff0c;还为展览的组织者提供了强大的工具。 接下来&#xff0c;由专业从事VR展览制作的圆桌3D云展厅平台为大家介绍AI在VR展览中的一些主要作用&#xff1a; 个性…

JVM和数据库面试知识点

JVM内存结构 主要有几部分&#xff1a;堆、栈、方法区和程序计数器 堆是JVM中最大的一块内存区域&#xff0c;用于存储对象实例&#xff0c;一般通过new创建的对象都存放在堆中。堆被所有的线程共享&#xff0c;但是它的访问时线程不安全的&#xff0c;通常通过锁的机制来保证线…

flask-admin+Flask-WTF 实现实现增删改查

背景&#xff1a; flask-adminflask-wtf在网上可以搜索到很多资料&#xff0c;但有价值的很少&#xff0c;或许是太简单&#xff0c;或者是很少人这么用&#xff0c;或者。。。&#xff0c;本文将作者近礼拜摸索到的一点经验分享出来&#xff0c;给自己做个记录。 材料&#…

C++简明教程(文章要求学过一点C语言)(3)

一、编程工具大揭秘——IDE 当我们准备踏入 C 编程的奇妙世界时&#xff0c;首先要认识一个重要的“魔法盒子”——集成开发环境&#xff08;IDE&#xff09;。IDE 就像是一个全能的编程工作室&#xff0c;它把我们写代码所需要的各种工具都整合到了一起&#xff0c;让编程这件…

STM32-笔记5-按键点灯(中断方法)

1、复制03-流水灯项目&#xff0c;重命名06-按键点灯&#xff08;中断法&#xff09; 在\Drivers\BSP目录下创建一个文件夹exti&#xff0c;在该文件夹下&#xff0c;创建两个文件exti.c和exti.h文件&#xff0c;并且把这两个文件加载到项目中&#xff0c;打开项目工程文件 加载…

实现 WebSocket 接入文心一言

目录 什么是 WebSocket&#xff1f; 为什么需要 WebSocket&#xff1f; HTTP 的局限性 WebSocket 的优势 总结&#xff1a;HTTP 和 WebSocket 的区别 WebSocket 的劣势 WebSocket 常见应用场景 WebSocket 握手过程 WebSocket 事件处理和生命周期 WebSocket 心跳机制 …

leetcode-80.删除有序数组的重复项II-day12

总结&#xff1a;不必过于死磕一道题目&#xff0c;二十分钟没做出来就可参考题解

RTOS之邮箱

邮箱 邮箱 (Mailbox) 服务是实时操作系统中一种常用的线程间通信机制。它提供了一种高效、低开销的消息传递方式&#xff0c;允许线程之间交换固定大小的数据。 1. 邮箱的应用场景 考虑一个简单的示例&#xff1a;线程 1 负责检测按键状态并将状态信息发送出去&#xff0c;线程…

凯酷全科技抖音电商服务的卓越践行者

在数字经济蓬勃发展的今天&#xff0c;电子商务已成为企业增长的新引擎。随着短视频平台的崛起&#xff0c;抖音作为全球领先的短视频社交平台&#xff0c;不仅改变了人们的娱乐方式&#xff0c;也为品牌和商家提供了全新的营销渠道。厦门凯酷全科技有限公司&#xff08;以下简…

AI的进阶之路:从机器学习到深度学习的演变(三)

&#xff08;承接上集&#xff1a;AI的进阶之路&#xff1a;从机器学习到深度学习的演变&#xff08;二&#xff09;&#xff09; 四、深度学习&#xff08;DL&#xff09;&#xff1a;机器学习的革命性突破 深度学习&#xff08;DL&#xff09;作为机器学习的一个重要分支&am…

数据集-目标检测系列 车牌检测识别 数据集 CCPD2019

车牌检测&识别 数据集 CCPD2019 DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种数据集&#xff0c;持续增加中。 需要更多数据资源和技术解决方案&#xff0c;知识星球&#xff1a; “DataBall - X 数据球(free)” 贵在坚持&#xff01; 数据样…

安全算法基础(一)

安全算法是算法的分支之一&#xff0c;还的依靠大量的数学基础进行计算&#xff0c;本文参照兜哥的AI安全样本对抗&#xff0c;做一个简单的算法安全概括&#xff0c;从零学习。 最新的安全算法对于我们常规的攻击样本检测&#xff0c;效果是不理想的&#xff0c;为了探究其原…

[SZ901]JTAG高速下载设置(53Mhz)

SZ901最高支持JTAG 53MHz的时钟频率&#xff0c;下载bit文件和固化程序的速度提升非常明显。 首先设置参数 1&#xff0c;将JTAG0 分频系数修改为3 2&#xff0c;设置参数&#xff0c;更新参数。&#xff08;完成&#xff09; 打开VIVADO VIVADO 正常识别FPGA&#xff0c;速…

图漾相机-ROS1_SDK_ubuntu版本编译(新版本)

文章目录 官网编译文档链接官网SDK下载链接1、下载 Camport ROS1 SDK1.下载git2、下载链接 2、准备编译工作1、安装 catkin2、配置环境变量3. 将Camport3中的linux库文件拷贝到 user/lib目录下4、修改lunch文件制定相机&#xff08;可以放在最后可以参考在线文档&#xff09;**…

openbmc hwmon与sensor监控

1.说明 参考文档: https://github.com/openbmc/entity-manager/blob/master/docs/entity_manager_dbus_api.mdhttps://github.com/openbmc/entity-manager/blob/master/docs/my_first_sensors.md 1.1 简单介绍 注意: 本节是快速浏览整个sensor框架&#xff0c;了解大致open…