Django的get_absolute_url方法的使用
作者:大江东流 发布时间:2023-05-28 02:38:14
本文主要的目的是通过一个简单的例子,展示`get_absolute_url`的用法,抛砖引玉,理解实例方法的本质,能够在不同的业务场景下,灵活多变,完成需求。
环境:Python3.8 + Django3.0
我们都知道,在反向解析url的时候,Django提供了三种方法,帮我们替代硬编码的方式,也就是:
在模板中:使用
url
模板标签。在Python代码中:使用
reverse()
函数。在更高层的与处理Django模型实例相关的代码中:使用
get_absolute_url
方法。
前面两种方式比较常见,我们也很熟悉,但是最后的get_absolute_url
方法,可能很多人就不明白具体如何使用了。下面我们通过一个简单易懂的例子,来搞懂它的具体使用方法。
一、创建模型
首先,假设我们有下面的学生模型:
class Student(models.Model):
sex_choice = [
('man', '男性'),
('woman', '女性'),
]
name = models.CharField(max_length=128)
sex = models.CharField(max_length=8, choices=sex_choice)
tel = models.PositiveIntegerField()
def __str__(self):
return self.name
学生包含姓名、性别和电话。
不要忘记makemigrations和migrate。
然后我们接入admin后台,随意手动创建一些学生实例:
from django.contrib import admin
from app.models import Student
class StudentAdmin(admin.ModelAdmin):
list_display = ['name', 'sex', 'tel']
admin.site.register(Student, StudentAdmin)
二、设计urls
我们编写了下面的urls:
from django.contrib import admin
from django.urls import path
from app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('students/', views.students),
path('man/<int:id>/', views.man, name='man'),
path('woman/<int:id>/', views.woman, name='woman'),
]
这里的students比较好理解,查看所有的学生列表。但是man和woman两条路由的设计就属于特殊需求了,按理说应该直接一条路由即可,不就是查看某个具体学生的信息嘛。
但如果业务需求是这样的:男生和女生必须使用不同的url进行访问!
那就只能这么分开编写成两条路由了。
注意url中的name属性,用于后面的反向路由解析。
三、编写视图
我们编写了下面的视图,很简单:
from django.shortcuts import render
from app import models
def students(request):
s = models.Student.objects.all()
return render(request, 'students.html', locals())
def man(request, id):
student = models.Student.objects.get(id=id)
return render(request, 'student.html', locals())
def woman(request, id):
student = models.Student.objects.get(id=id)
return render(request, 'student.html', locals())
四、HTML模板
首先看看student.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>name: {{ student.name }}</p>
<p>sex: {{ student.sex }}</p>
<p>tel: {{ student.tel }}</p>
</body>
</html>
很简单,就是展示学生的信息,没有需要关注的,仅仅用于表示运行正常,信息显示正确。
重点是students.html
(多了个s,复数形式):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h4>欢迎访问liujiangblog.com, 学习更多Django教程</h4>
{% for student in s %}
{% if student.sex == 'man' %}
<p>
姓名:{{ student.name }}
详情:<a href="{% url 'man' student.id %}" rel="external nofollow" >{% url 'man' student.id %}</a>
</p>
{% else %}
<p>
姓名:{{ student.name }}
详情:<a href="{% url 'woman' student.id %}" rel="external nofollow" >{% url 'woman' student.id %}</a>
</p>
{% endif %}
{% endfor %}
</body>
</html>
通过if标签的判断,决定最终生成的url是哪种。这里使用了Django内置的url模板标签语法。
访问students/
页面显示结果:
点击任何一条学生链接都可以正常跳转到详情页面。
五、使用get_absolute_url方法
上面的代码实现了业务需求,男生和女生自动生成了不一样的url,而不是我们惯例的/student/
,整个过程也很简单,比较好理解。
但是,这里有个不足之处,那就是区分男女生的逻辑放在了HTML模板文件中,这不是个好的做法,也不优雅。
实际上我们可以使用get_absolute_url
方法,在Python代码中实现这一功能。
首先,修改Student模型,添加get_absolute_url
方法:
class Student(models.Model):
sex_choice = [
('man', '男性'),
('woman', '女性'),
]
name = models.CharField(max_length=128)
sex = models.CharField(max_length=8, choices=sex_choice)
tel = models.PositiveIntegerField()
def __str__(self):
return self.name
def get_absolute_url(self):
from django.urls import reverse
if self.sex == 'man':
return reverse('man', args=(self.id,))
else:
return reverse('woman', args=(self.id,))
在get_absolute_url
方法中,我们导入了reverse,这是Django提供的反向解析功能。
reverse能避免我们对url进行硬编码,它接收多种类型的参数,可以是一个视图名,也可以是一个url的name。相关的参数通过args传递,这是一个元组,有顺序。
上面的代码中,通过if/else判断,根据性别的不同,解析出男女生对应的url。
然后,在students.html
中,我们就可以修改成下面的样子:
<body>
<h4>欢迎访问liujiangblog.com, 学习更多Django教程</h4>
{% for student in s %}
<p>
姓名:{{ student.name }}
详情:<a href="{{ student.get_absolute_url }}" rel="external nofollow" >{{ student.get_absolute_url }}</a>
</p>
{% endfor %}
</body>
首先,没有if/else模板标签了。其次使用{{ student.get_absolute_url }}
来代替url模板标签。
student是Student模型类的一个实例,它可以访问类中定义的get_absolute_url方法,从而进入if/else判断,然后根据性别的不同,reverse出不同的url字符串,并在HTML模板中展示出来。
整个HTML模板显得更加简洁优雅,最后的页面结果也是完全一样的。实际上,这里也体现出了Django的模型层和模板层的高度配合。
六、总结思考
例子很简单,无非就是在Student模型中添加了一个get_absolute_url
方法。但是如果仔细思考一下我们会发现这里面有很多体现语言特点的东西:
Django本身没有实现一个基本的get_absolute_url
方法,在models.Model
中也没有get_absolute_url
方法的影子,所以这个方法其实只是个思路,没有实质。
get_absolute_url
方法本质上只是一个类的实例方法,既然Django内部的代码没有实现它,那么实际上我们可以给它任意命名,比如改成get_url
。你可以试试,它绝对能正常工作。但要小心的是,Django核心源码虽然没有定义get_absolute_url
方法,在admin后台和feed框架等地方却可能使用了这个get_absolute_url
方法,所以在非必须时,不要修改这个方法名。
继续拓展思维,既然可以自定义get_absolute_url
方法,那我可不可以在模型中添加任何我需要的实例方法呢?当然可以!并且这是最强大最灵活的方式!比如根据用户的不同,为模型添加一个user_control
方法,提供不同的信息,控制访问权限,切换页面主题等等。
来源:https://www.cnblogs.com/django-dev/p/13507986.html
猜你喜欢
- 目录一、jieba库概述二、jieba库安装三、jieba分词的原理四、jieba分词的3种模式五、jieba库常用函数六、文本词频示例七、
- 希望这是window.open()打开fullscreen全屏窗口时无提示关闭父窗口的完美解决方案:我们通常都是用控件法,在父窗口文件里放一
- python3字符串操作 x = 'abc' y = 'defgh' print(x + y)
- 在 Python 中,我们可以使用基本的索引操作来获取数组中的元素。然而,有时候我们需要获取一个数组的子数组,也就是只获取数组中的一部分元素
- 引言使用python进行接口测试时常常需要接口用例测试数据、断言接口功能、验证接口响应状态等,如果大量的接口测试用例脚本都将接口测试用例数据
- 基于smtplib包制作而成,但在实践中发现一个不知道算不算是smtplib留的一个坑,在网络断开的情况下发送邮件时会抛出一个socket.
- 以下是几个文件操作过程,创建文件,删除文件,修改文件:
- 本文实例讲述了Python多进程原理与用法。分享给大家供大家参考,具体如下:进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了
- 在平时的需求开发中涉及到将多列值合并为一列值的操作,通过查阅相关资料特此记录以下方法,方便日后学习复盘 import pandas
- 下边的函数,实现了象数组一样去处理字符串。 一,用临时表作为数组 create function f_split(@c varchar(20
- #常用的几个代码--查询临时表空间select name from v$tempfile;--查询表空间select name from v
- transforms.Resize()的简单使用简单来说就是调整PILImage对象的尺寸,注意不能是用io.imread或者cv2.imr
- 一、手动创建添加my.ini文件# CLIENT SECTION# ------------------------------------
- 安装selenium打开命令控制符输入:pip install -U selenium火狐浏览器安装firebug:www.firebug.
- 自从腾讯微博上线以来,基本上就开始用了,一直到现在,作为一个开发人员,也看到了腾讯微博一直在不停的改变,也不知道大家有没有发现,腾讯微博提供
- 递归函数及递归次数受到限制一个函数在内部调用自己,那么这个函数是递归函数。递归会反复使用本身,每递归一次,越接近最终的值。当一个问题可以由许
- K-Means聚类算法演示及可视化展示#导入包from sklearn.cluster import KMeansX = [[0.0888,
- 如何在本地机器上创建缓存?用法到是很简单,只需先创建Stream对象的实例,然后开始写入数据即可: Dim str&n
- 问题:python spyder先出现dos窗口,然后后面就什么都没有了。解决方法:C:\用户\Administrator\.spyder3
- 如果仅仅是定义表格的边框为1(border="1")和边框颜色值(如borderC