快捷搜索:  汽车  科技

django模型教程(Django搭建网络相册MTV模式)

django模型教程(Django搭建网络相册MTV模式)视图(View),逻辑层处理与表现相关的事务,即数据如何在页面中进行显示。模型(Model),数据层处理与数据相关的所有事务: 如何存取、如何验证有效性、数据之间的关系等。模板(Template),表现层

Django 框架主要关注的是模型(Model)、模板(Template)和视图(Views),称为MTV模式。

它们各自的职责如下:

层次

职责

模型(Model),数据层

处理与数据相关的所有事务: 如何存取、如何验证有效性、数据之间的关系等。

模板(Template),表现层

处理与表现相关的事务,即数据如何在页面中进行显示。

视图(View),逻辑层

存取模型及调取恰当模板的相关逻辑。模型与模板的桥梁。

简单来说就是 Model 存取数据,View 决定需要调取哪些数据,而 Template 则负责将调取的数据以合理的方式展现出来。

本章主要聊聊模板,以及它们三者的交互。

小试牛刀

首先给 Photo 模型增加一个 Meta 内部类:

# /photo/models.py ... class Photo(models.Model): ... class Meta: ordering = ('-created' )

ordering 属性定义了图片数据的排序,比如这里是按创建时间倒序排列。

接着修改 home() 视图函数:

# /photo/views.py from django.shortcuts import render from photo.models import Photo def home(request): photos = Photo.objects.all() context = {'photos': photos} return render(request 'photo/list.html' context)

  • 前面章节说过,Django 的 ORM 尽可能让你脱离晦涩的数据库操作语句。比如这里,模型类直接用 Photo.objects.all() 取出所有的图片模型对象,就和操作普通的 Python 对象差不多,相当亲切。
  • 视图取出的数据最终要传递给模板,这些数据的集合被称为上下文(context),以字典的形式组织在一起。
  • 将数据载入模板、填充上下文、返回响应体对象,这是常用的流程,因此 Django 提供了 render() 这个快捷函数。它的三个参数分别是当前请求体、模板所在路径和上下文字典。

接下来在项目根目录下新建 /templates/photo/list.html 模板文件:

# /templates/photo/list.html {% for photo in photos %} <img src="{{ photo.image.url }}" alt=""> {% endfor %}

  • 模板里的逻辑语法以 {% .. %} 形式组织。Django 在渲染 html 文件时,碰到 {% .. %} 就知道这不是展现给用户的文字或符号,而是模板的控制流语句。
  • 模板标签中的 photos 就是前面视图上下文中传递的 photos 数据。
  • 模板里的数据用 {{ ... }} 组织,它是实实在在的需要动态替换成展现给用户的内容,注意它和控制流标签的区别。注意看,标签里的 photo 就是 Photo 模型的实例,.image 是模型里定义的图片字段,.url 是字段中包含的图片路径。
  • 最后以 {% endfor %} 标志整个控制流的结束。

<img ...> 这个就是普通的 html 标签了,教程虽然只会用到最基础的 html/css/javascript 知识,但篇幅有限不会展开讲解。如果阅读非常吃力建议先看一些相关基础。

模板虽然写好了,但是还没告诉 Django 模板文件的路径。默认的模板路径在每个 App 自己的路径中,但笔者习惯把所有模板文件集中在一起,因此需要改一下全局配置:

# /album/settings.py ... # 注意是修改此配置 # 不是新增 TEMPLATES = [ { 'DIRS': [BASE_DIR / 'templates'] ... } ] ...

这就完工了。

运行服务器看看:(请确保已经在后台保存了一些图片数据)

django模型教程(Django搭建网络相册MTV模式)(1)

虽然没有任何样式,导致图片太大直接撑爆了屏幕,但整个 MTV 流程顺利打通了。

如果图片未正常显示,先打开浏览器的控制台看看有无 404 报错。有报错可能是前面章节有关媒体文件路径配置不正确(MEDIA_ROOT 等),无报错则可能是其他原因。

模板复用

模板文件实质上是 html 文件。 Django 会按照模板标签的规则,将里面的标签文本替换成对应的数据。

既然是普通的 html 文件,那么写的时候还是得按照其书写规范,不要乱来。

一个标准的 html 文档至少要包含下面的内容:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>My test page</title> </head> <body> <p>This is my page</p> </body> </html>

因此前面测试写的那个 list.html 得修改。

另一方面,html 文件与 Python 代码一样,很多地方是可以复用的。比如需要载入的资源啊、全局的基础样式啊、页眉页脚啊这些。因此模板也提供了办法来实现其复用,让我们实践看看。

基础模板

首先来写所有模板的“父类”,即全站的基础模板 /templates/base.html :

<!-- /templates/base.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- 预留页面标题位置 --> <title>{% block title %}{% endblock title %}</title> <!-- bootstrap.css --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <!-- 引入导航栏 --> {% include 'header.html' %} <!-- 预留具体页面的位置 --> {% block content %}{% endblock content %} <!-- 引入注脚 --> {% include 'footer.html' %} <!-- bootstrap.js --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP JcXn/tWtIaxVXM" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js" integrity="sha384-GNFwBvfVxBkLMJpYMOABq3c d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/ 7D" crossorigin="anonymous" async></script> <!-- 预留脚本的位置 --> {% block scripts %}{% endblock scripts %} <style> body { background-color:#212529; } </style> </body> </html>

有点长但不复杂,来分解一下:

  • 它是个规范的 html 文档。
  • {% block ... %} 给“继承”它的“模板子类”预留出空间,表示这个位置的内容将由“子类”来填充。
  • {% include '...' %} 表示在这个位置,插入另外一个模板文件。也就是页眉和页脚了。
  • 它远程引用了 Bootstrap 的 css/js 文件。 Bootstrap 是非常流行的前端响应式框架,上手极其简单(直接在官网抄示例代码),用它可以非常高效写出屏幕自适应的现代化页面。
  • 引入了后续卡片效果要用的瀑布流插件 masonry.js 。
  • 将全局背景设置为深灰色。
页眉和页脚

理论上页眉和页脚也是全站点共用的,也可以直接写在 base.html 里。不过为了保持干净,还是独立出来好了。

首先是新建页眉模板文件:

<!-- /templates/header.html --> <!-- 导航栏 --> <nav class="navbar navbar-dark bg-dark"> <div class="container"> <!-- 标志 --> <a class="navbar-brand" href="#"> <h2>Awesome Album</h2> </a> </div> </nav>

非常简单,就是一个普通的 Bootstrap 导航栏标签。

注意此文件的路径,和 base.html 里的 {% include 'header.html' %} 要能够对应。

接着是页脚

<!-- /templates/footer.html --> <!-- Footer --> <div><br><br><br></div> <footer class="py-3 bg-dark fixed-bottom"> <div class="container"> <p class="m-0 text-center text-white"> Copyright © www.dusaiphoto.com 2021 </p> </div> </footer>

也很简单,是一个固定在底部的横幅。

图片列表

最后才是正儿八经的图片列表模板。

修改 list.html 文件如下:

<!-- /templates/photo/list.html --> {% extends "base.html" %} {% block title %}首页{% endblock title %} {% block content %} {% for photo in photos %} <img src="{{ photo.image.url }}" alt=""> {% endfor %} {% endblock content %}

  • {% extends "base.html" %} 表示此模板“继承”自 base.html 。
  • 注意看 {% block title %} 等标签和 base.html 的对应关系。

重启服务器看看效果:

django模型教程(Django搭建网络相册MTV模式)(2)

绕了一圈,除了页眉页脚,看上去似乎没啥变化,但是模板文件的结构变清晰了。

模板布局

上面这种撑爆屏幕的图片效果肯定是没法用的。

我们按照 Bootstrap 官方给的卡片示例代码稍微改一下:

<!-- /templates/photo/list.html --> {% extends "base.html" %} {% block title %}首页{% endblock title %} {% block content %} <div class="container py-2"> <div class="row" data-masonry='{"percentPosition": true}'> {% for photo in photos %} <div class="col-4 py-2"> <div class="card"> <img src="{{ photo.image.url }}" alt="" class="card-img" > </div> </div> {% endfor %} </div> </div> {% endblock content %}

在后台中再多添加一些图片数据。

教程示例均来自pixabay免费商用图片,此致感谢。

刷新页面看看效果:

django模型教程(Django搭建网络相册MTV模式)(3)

Bootstrap 把复杂的布局技术隐藏起来,你只需要引入它并按照它的规则修改 class 等属性就可以获得非常漂亮、屏幕自适应的界面。

总结

目前为止,我们只写了非常少的 Python 代码(不到三十行),和非常简单的 html 代码,就获得了像模像样的相册网站了,说不定可以拿去交付(忽悠)甲方了。 Django 和 Bootstrap 的配合还不错吧?

下一章将通过照片细节展示功能,探讨模态与动画技术。

点赞和吐槽?评论区来告诉我!

django模型教程(Django搭建网络相册MTV模式)(4)

django模型教程(Django搭建网络相册MTV模式)(5)

猜您喜欢: