FullStack之Django(3)视图和模板

FullStack之Django(3)视图和模板

author:Once Day date:2022年2月13日/2024年1月30日

漫漫长路,才刚刚开始…

全系列文档请查看专栏:

参考文档如下:

1.视图

Django 中的视图的概念是一类具有相同功能和模板的网页的集合。一个视图通常对应一个页面,提供特定的功能,使用特定的模板。例如,在登入界面中,

  • 登入主界面,输入账号和密码
  • 找回密码界面
  • 注册新用户界面
  • 用户协议界面

在Django中,网页和其它的一些内容都是通过视图来处理的。视图其实就是一个简单的Python函数(在基于类的视图中称为方法)。Django通过对比请求的URL地址来选择对应的视图,也就是路由。

在login/views.py里面就可以编写视图,

#login/views.py
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
#定义一个函数,或者说一个网页
def user_login(request):#浏览器送出 HTTP Request
    return HttpResponse("欢迎来到Once Day的个人网站!")
def information(request,account_id):
    return HttpResponse("你正在查看账号id:{:d}的详细用户信息。".format(account_id))
def reset_password(request,account_id):
    return HttpResponse("你正在重置账号id:{:d}的密码。".format(account_id))

然后修改login/urls.py文件,

#login/urls.py
from django.urls import path
#导入编写的视图函数
from login.views import user_login,information,reset_password

urlpatterns = [
    path('', user_login,name="index"),#index是默认的主页面
    #访问/login/id/inf获取账户详细信息
    path("<int:account_id>/inf",information,name="inf"),
    #访问/login/id/reset重置账户密码
    path("<int:account_id>/reset",reset_password,name="reset"),
]

使用了二级路由后,url中都要添加字符串polls前缀,比如访问/20200213/inf,它将调用information()函数,然后在页面中显示你在url里提供的ID。保存更改,命令行先check检查错误再runserver运行服务器。

在这里插入图片描述

上面访问的路由过程如下:当有人访问/login/20220213/inf地址时,Django将首先加载mysite.urls模块,因为它是settings文件里设置的根URL配置文件。在该文件里,Django发现了urlpatterns变量,于是在其内按顺序进行匹配。当它匹配上了login/,就裁去url中匹配的文本login/,然后将剩下的文本“20220213/inf”,传递给login.urls进行下一步的处理。在login.urls中,又匹配到了<int:question_id>/inf,最终结果就是调用该模式对应的information视图,也就是下面的函数:

def information(request,account_id):
    return HttpResponse("你正在查看账号id:{:d}的详细用户信息。".format(account_id))

<int:question_id>/使用尖括号“捕获”这部分 URL,且以关键字参数的形式发送给视图函数。上述字符串的question_id部分定义了将被用于区分匹配的变量名,而int则是一个转换器决定了应该以什么变量类型匹配这部分的 URL 路径。

2.模板

之前视图中的HTML页面都是硬编码的。 如果想改变页面的显示内容,就必须修改这里的Python代码。为了解决这个问题,需要使用Django提供的模板系统,解耦视图和模板之间的硬连接。

项目settings.py文件中的 TEMPLATES配置项描述了 Django 如何载入和渲染模板。默认的设置文件设置了 DjangoTemplates 后端作为模板引擎,并将 APP_DIRS设置成了 True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 “templates” 子目录。

在login文件内新建templates目录,再创建一个新的子目录名叫login,进入该子目录,创建一个新的HTML文件inf.html。换句话说,模板文件应该是login/templates/login/inf.html。因为 Django 会寻找到对应的app_directories ,所以只需要使用login/inf.html就可以引用到这一模板了。

模板命名空间:

你也许会想,为什么不把模板文件直接放在login/templates目录下,而是费劲的再建个子目录login呢?设想这么个情况,有另外一个app,它也有一个名叫inf.html的文件,当Django在搜索模板时,有可能就找到它,然后退出搜索,这就命中了错误的目标,不是我们想要的结果。解决这个问题的最好办法就是在templates目录下再建立一个与app同名的子目录,将自己所属的模板都放到里面,从而达到独立命名空间的作用,不会再出现引用错误。

这里推荐阅读参考文档:django Part 3:视图和模板 - 刘江的django教程 (liujiangblog.com)

模板语言(Django模板语言)简称DTL。模板变量名是由数字,字母,下划线和点组成,不能以下划线开头。

语法可参考:Django 模板_w3cschool

{% 代码段 %}
#for循环:
#遍历列表:
{% for i in 列表 %}
#列表不为空时执行
{% empty %}
#列表为空时执行
{% endfor %}
#若加上关键字reversed则倒序遍历:
{% for x in 列表 reversed %}
{% endfor %}
#在for循环中可以通过{{ forloop.counter }}得到for循环遍历到几次
#判断语句:
{% if %}
{% elif %}
{% else %}
{% endif %}  

关系比较操作符\ > < >= <= == !=,在使用关系比较操作符的时候,比较符两边必须有空格。

过滤器用于对模板变量进行操作:

  • add:将值的值增加2。使用形式为:{{value | add:“ 2”}}
  • cut:从给定值中删除所有arg的值。使用形式为:{{value | cut:arg}}
  • date:格式化时间格式。使用形式为:{{value| date:“ Ymd H:M:S”}}
  • default:如果value是False,那么输出给定的默认值。使用形式:{{value | default:“ nothing”}}。例如,如果值是“”,那么输出将是nothing
  • first:返回列表/字符串中的第一个元素。使用形式:{{value | first}}
  • length:返回值的长度。使用形式:{{value | length}}

模板注释的内容浏览器看不到,html注释的内容浏览器可以看到:

  • 单行注释:{#注释内容#}
  • 多行注释:{%comment%}

了解完基本语法,就可以开始写一个简单的模板网页了。

HTML5的基础知识可以参考:基础HTML5网页知识

下面写出了可以显示账号信息的模板:

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Once Day 登入界面</title>
        <meta name="author" content="Once Day">
    </head>
    <body>
        {% if account_exist %}
        {#如果存在账号#}
            <p>用户名字: {{user.user_name}}</p>
            <p>用户出生日期: {{user.user_birthday}}</p>
            <p>用户金钱: {{user.user_money}}</p>
        {% else %}
            <p>没有这个账号!!!</p>
        {% endif %}
    </body>
</html>

user和account_exist都是将从views中传递进去的变量。

在模板系统中圆点.是万能的魔法师,你可以用它访问对象的属性。在例子{{ user.user_name }}中,Django首先会在user对象中尝试查找一个字典,如果失败,则尝试查找属性,如果再失败,则尝试作为列表的索引进行查询。

然后修改一下login/views.py文件,使得其生效:

from django.shortcuts import render
from django.http import HttpResponse
#导入账户模型
from login.models import account
# Create your views here.
#定义一个函数,或者说一个网页
def information(request,account_id):
    try:
        my_account=account.objects.get(account_name=str(account_id))#查找账户
  	    user=my_account.user#获取关联的用户信息
        account_exist=True
    except:
        my_account=[]
        user=[]
        account_exist=False
    context = {'user': user,'account_exist':account_exist}
    return render(request,'login/inf.html',context)

在实际运用中,加载模板、传递参数,返回HttpResponse对象是一整套再常见不过的操作了,为了节省力气,Django提供了一个快捷方式:render函数,一步到位!

render()函数的第一个位置参数是请求对象(就是view函数的第一个参数),这个参数是固定写法,不需要变动。第二个位置参数是模板文件。还可以有一个可选的第三参数,一个字典,包含需要传递给模板的数据。最后render函数返回一个经过字典数据渲染过的模板封装而成的HttpResponse对象。

再在命令行输入一下指令,更改原来的账户为数字账户名。

PS E:\django\mysite> python manage.py shell
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from login.models import user_information,account # 导入我们写的模型类
>>> a1=account.objects.get(id=1)
>>> a1.account_name
'onceday'
>>> a1.account_name='20220213'
>>> a1.save()
>>> a1
<account: 20220213>
>>>exit()

然后保存所有文件,先check再runserver。浏览器访问(http://127.0.0.1:8000/login/20220213/inf),即可看到账户信息:

在这里插入图片描述

当账户id错误时,则会提示没有这个账户!
在这里插入图片描述

3.返回404错误

一个网站如果不能返回404错误,则毫无灵魂可言!

修改login/views.py文件:

from django.shortcuts import render
from django.http import HttpResponse,Http404
#导入账户模型
from login.models import account
# Create your views here.
#定义一个函数,或者说一个网页
def information(request,account_id):
    try:
        my_account=account.objects.get(account_name=str(account_id))
        user=my_account.user#获取关联的用户信息)
        account_exist=True
    context = {'user': user,'account_exist':account_exist}
    except account.DoesNotExist:
        context = {'user': [],'account_exist':False}
        raise Http404("该账号不存在!!!")
    return render(request,'login/inf.html',context)

运行服务器后浏览器访问(http://127.0.0.1:8000/login/20220313/inf),可看到404页面:

在这里插入图片描述

可以使用以下函数代替上面的多段代码,如,

object = get_object_or_404(...)#替代get函数
object = get_list_or_404(...)#替代filter函数

注意filter返回是对象的列表!

4.模板中使用动态编码的URLs

链接标签一般如下所示:

<li><a href="/login/{{ account_id }}/">{{ user.user_name }}</a></li>

关键在于/login/这块路径也是可能被更改的,所以这个需要采取点措施。

<li><a href="{% url 'inf' account_id%}">{{ user.user_name }}</a></li>

Django会在login.urls文件中查找name=inf的路由,具体的就是下面这行:

path("<int:account_id>/inf",information,name="inf"),

这样,即使更改url,Django也能根据name去找到合适的路径。

在大工程里面,还需要使用**URLconf的命名空间。**如下

#login/urls.py
from django.urls import path
#导入编写的视图函数
from login.views import user_login,information,reset_password
app_name = 'login'   # 重点是这一行
urlpatterns = [
    path('', user_login,name="index"),#index是默认的主页面
    #访问/login/id/inf获取账户详细信息
    path("<int:account_id>/inf",information,name="inf"),
    #访问/login/id/reset重置账户密码
    path("<int:account_id>/reset",reset_password,name="reset"),
]

然后模板里面链接可以改成以下样式:

<li><a href="{% url 'login:detail' account_id%}">{{ user.user_name }}</a></li>

这样,就不用担心名字冲突了!

推荐参考文档:

注:本文章内容收集总结于互联网,仅供学习之用!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值