Django中母版、组件、inclusion_tag的使用

母版页用于处理html页面相同部分内容,避免出现冗余代码

一、母版的使用:

  • 使用母版情况1:母板中定义页面专用的CSS块和JS块,方便子页面替换。
  • 使用母版情况2:多个页面有很多共同的代码段时可以将相同的代码段提取出来。
  • 使用方法:
    通过在母板中使用 {% block xxx %}来定义"块"。
    在子页面中继承母版 {% extends "xxx.html" %}
    通过母板中的命名块{% block page-main%}....{% endblock %}来对应替换母板中相应的位置。

代码示例:
母版--->base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>个人数据管理中心</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-inverse" role="navigation">
    <div class="container-fluid">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">个人数据管理中心</a>
        </div>
        <div>
        </div>
    </div>
</nav>
{% block page-main%}
{% endblock %}


{% block page-js %}
{% endblock %}
</body>
</html>

子内容-继承母版-->views.html

{% extends "base.html" %}
{% block page-main %}
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-info">
                    <div class="panel-heading">
                        <h4 style="display: inline-block">数据详情</h4>
                        <a href="{{ add_url }}">
                            <button class="btn btn-lg btn-info pull-right">添加数据</button>
                        </a>
                    </div>
                    <div class="panel-body">
                        <table class="table table-hover table-striped table-bordered">
                            <thead>
                            <tr>
                                {% for head in heads_list %}
                                    <td><h4>{{ head }}</h4></td>
                                {% endfor %}
                            </tr>
                            </thead>
                            <tbody>
                            {% for obj in obj_list %}
                                <tr>
                                    {% for field in obj %}
                                        <td>
                                            {{ field }}
                                        </td>
                                    {% endfor %}
                                </tr>
                            {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                {{ page_html|safe }}
                <!------模态框开始-------->
                <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
                     aria-hidden="true">
                    <div class="modal-dialog">
                        <div class="modal-content">
                            <div class="modal-header">
                                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;
                                </button>
                                <h4 class="modal-title" id="myModalLabel">确认删除</h4>
                            </div>
                            <div class="modal-body">您确定要删除所选的数据吗???</div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                                <a id="del-success" href="">
                                    <button type="button" class="btn btn-primary">删除</button>
                                </a>
                            </div>
                        </div><!-- /.modal-content -->
                    </div><!-- /.modal -->
                </div>

                <!------模态框结束-------->

            </div>
        </div>
    </div>
{% endblock %}
{% block page-js %}
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/2.3.2/js/bootstrap.js"></script>
    <script>
        $(function () {
            $(".delete-link").click(function () {
                var url = $(this).attr('href');
                $("#del-success").attr("href", url)
            })
        });
    </script>
{% endblock %}

子内容-继承母版-->addviews.html

{% extends "base.html" %}
{% block page-main %}
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-info">
                    <div class="panel-heading">
                        <h4>添加数据</h4>
                    </div>
                    <div class="panel-body">
                        <form action="" method="post" novalidate>
                            {% csrf_token %}
                            {% for field in form_obj %}
                                <div class="form-group">
                                    <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                                    {{ field }}
                                    <span class="error pull-right" style="color: red">{{ field.errors.0 }}</span>
                                </div>
                            {% endfor %}
                            <input type="submit" class="btn btn-success">
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
{% endblock %}

二、组件的使用:

可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

{% include 'navbar.html' %}

组件和母版的区别:

  • 组件相当于是单拿出来独立的一部分,哪里需要插哪里,即插即用!!!
  • 母版相当于是一个整体的框架,将有差异的各个部分单留出空间来,以方便自定制内容的填充。

三、静态文件配置

简单地说就是:我们自己导入的一些包就叫做静态文件
配置的步骤:

  • 1、在全局中先创建一个static的包,
  • 2、在static里面导入我们的bootstrap,还是jquery等等...
  • 3、然后在settings.py中加上一些配置
STATIC_URL = '/static/'   #这个相当于给配置起的别名,如果这里的名字修改了就按照这里的名字去导入
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static")  #通过和项目根路径拼接得到static的路径
]
  • 4.1、普通导入css,js,jquery
<link rel = "stysheet",href= "/static/index.css/"> 
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
  • 4.2 动态导入(这种导入更加灵活)
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
  • 还可以用在一下地方:
{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />
{% load static %}
<script src="{% static "mytest.js" %}"></script>
  • 某个文件多处被用到可以存为一个变量:
{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>
  • get_static_prefix的使用
{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

或者

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

四、inclusion_tag

类似于上面的组件,只不过他需要从后端得到数据才能完成渲染成功。多用于返回html代码片段
代码示例:

  • 第一步:在app下创建一个名为templatetags(必须是这个名字)文件夹。
  • 第二步:在这个文件夹下创建一个py文件,名字没要求。
  • 第三步:在py文件中先导入,在注册,代码是固定死的。
from django import template
register = template.Library()
  • 第四步:写视图函数得到页面所需要的数据,将数据return回来,
  • 第五步:给这个视图函数加上@register.inclusion_tag(filename='left_menu.html'),以指定html文件将数据传入。
  • 在需要用到自定义inclusion_tag的html文件中引入,引入固定规则为:
    通过使用{% load py文件名 %} {% 对应html文件名 py文件中的视图函数所需参数 %}的固定形式引用自定义的inclusion_tag。

l_menu.py文件示例:

from django import template
from blog import models
from datetime import datetime

register = template.Library()


@register.inclusion_tag(filename='left_menu.html')
def left_menu(username):
    # 通过用户信息找到当前用户的对象
    user_obj = models.UserInfo.objects.filter(username=username).first()
    # ORM操作查询当前用户对应的所有书籍
    article_list = models.Article.objects.filter(user=user_obj).order_by("create_time").reverse()
    # ORM操作查询当前用户对应的所有分类
    categorys = models.Category.objects.filter(blog=user_obj.blog)
    # ORM操作查询当前用户对应的blog的tags
    tags = models.Tag.objects.filter(blog=user_obj.blog)

    # 时间归档方式一
    #通过对所有对象的create_time字段的处理,通过列表的去重和计数得到对应的前端数据
    date_list = [datetime.strftime(obj.create_time, '%Y-%m') for obj in article_list]
    list2 = list(set(date_list))
    list2.sort(key=date_list.index)
    ret_date_list = [(i, date_list.count(i)) for i in list2]

    #时间归档方式二
    # 对当前blog的所有文章按照年月 分组 查询
    # 1. models.Article.objects.filter(user=user_obj)                   --> 查询出当前作者写的所有文章
    # 2. .extra(select={"y_m": "DATE_FORMAT(create_time, '%%Y-%%m')"}   --> 将所有文章的创建时间格式化成年-月的格式,方便后续分组
    # 3. .values("y_m").annotate(c=Count("id"))                         --> 用上一步时间格式化得到的y_m字段做分组,统计出每个分组对应的文章数
    # 4. .values("y_m", "c")                                            --> 把页面需要的日期归档和文章数字段取出来
    # archive_list = models.Article.objects.filter(user=user_obj).extra(
    #     select={"y_m": "DATE_FORMAT(create_time, '%%Y-%%m')"}
    # ).values("y_m").annotate(c=Count("id")).values("y_m", "c")

    return {
        'username': username,
        'categorys': categorys,
        'tags': tags,
        'ret_date_list': ret_date_list,
    }

left_menu.html示例:

<div class="panel panel-info">
    <div class="panel-heading">
        文章分类
    </div>
    <div class="panel-body">
        <ul class="list-group">
            {% for category in categorys %}
                <li class="list-group-item">
                    <a href="/blogcenter/{{ username }}/category/{{ category.title }}">
                        {{ category.title }}({{ category.article_set.all.count }})
                    </a>
                </li>
            {% endfor %}
        </ul>
    </div>
</div>

<div class="panel panel-success">
    <div class="panel-heading">
        标签
    </div>
    <div class="panel-body">

        <ul class="list-group">
            {% for tag in tags %}
                <li class="list-group-item">
                    <a href="/blogcenter/{{ username }}/tag/{{ tag.title }}">
                        {{ tag }}({{ tag.article_set.all.count }})
                    </a>
                </li>
            {% endfor %}
        </ul>
    </div>
</div>

<div class="panel panel-primary">
    <div class="panel-heading">
        日期归档
    </div>
    <div class="panel-body">
        <ul class="list-group">
            {% for date in ret_date_list %}
                <li class="list-group-item">
                    <a href="/blogcenter/{{ username }}/archive/{{ date.0 }}">
                        {{ date.0 }}({{ date.1 }})
                    </a>
                </li>
            {% endfor %}
        </ul>
    </div>
</div>

base.html文件示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>个人中心</title>
    <link rel="stylesheet" href="/static/bootstrap/bootstrap-3.3.7/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/mycss.css">
</head>
<body>
<div class="container-fluit">
    <div class="row">
        <!--左侧栏开始-->
        <div class="col-md-2">

      //通过使用{% load  py文件名 %}  {% 对应html文件名  py文件中的视图函数
      //所需参数 %}的固定形式引用自定义的inclusion_tag。
            {% load l_menu %}
            {% left_menu username %}
        </div>
        <!--左侧栏结束-->
        {% block page-main %}
        {% endblock page-main %}
    </div>
</div>
<script src="/static/js/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/bootstrap-3.3.7/js/bootstrap.js"></script>
{% block page-js %}
{% endblock page-js %}
</body>
</html>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 22年12月更新:个人网站关停,如果仍旧对旧教程有兴趣参考 Github 的markdown内容[https://...
    tangyefei阅读 35,127评论 22 257
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • 英语: 1.每天坚持早起听两个TED。》有坚持在听英文(中午),效果不是很明显。可能得换一个方式。 2.每天坚持背...
    挖泥巴阅读 670评论 1 49
  • 爸妈都希望我走一条更平坦的路 但谁又愿意 有一个被安排的人生呢 也许你们说的 都对 但我不是你们 你们总说,你们不...
    蓝格子a阅读 162评论 0 0