get_context_object_name()
函数是一个在 Django 视图中定义的方法,它的主要作用是将一个 QuerySet 对象中的数据传递到模板中,并且将该对象在模板中使用的变量名定义为一个字符串。该函数必须在视图中使用。
在 Django 官网提供的解释中,get_context_object_name()
函数将一个 QuerySet 或其他类似对象通过这个函数传递到模板中来,并将其加入模板上下文的字典中,以便模板能够访问它。该函数被视图类中的 MultipleObjectMixin
所使用。
下面分为几个部分来详细讲解 get_context_object_name()
的使用方法和作用:
一、基本用法
使用该函数的前提条件是需要了解 Django 中的查询集(QuerySet),查询集是从 Django 对象数据库中获得的一组记录,该组记录可以根据各种选择进行筛选、排序、限制等操作。
在视图函数使用 get_context_object_name()
时,需要将 QuerySet 对象的数据传递进来,通过该函数将其解析成字典类型,并指定模板中所使用的变量名,下面是一个例子:
from django.views.generic import ListView
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = 'home.html'
context_object_name = 'articles'
在这个例子中,我们从 Listview
中继承了 ArticleListView
,并指定了对应的模型(model)、模板(template) 和上下文变量名(context_object_name)。当我们访问这个视图函数时,它将会返回一个字典,该字典中的关键字就是该视图所处理的 QuerySet 对象中的所有数据值,而变量 articles
则是该 QuerySet 在模板中被使用的变量名。
当模板文件 home.html
中使用以下代码时:
{% for article in articles %}
<h2>{{ article.title }}</h2>
{% endfor %}
模板上下文中的字典就会解析为:
{ 'articles': Queryset([ <Article: title 1>, <Article: title 2> ]) }
解析之后,数据值就会被传递到模板当中,并且通过变量名 articles
被引用。因此,该函数的使用方法就是将查询集传递给视图,打包成字典,制定变量名,方便在模板中使用。
二、实例一
举个更加具体的例子,比如我要定义一个查找特定分类文章的视图函数。对于这个视图函数,我们必须获取该分类下的所有文章数据并将其传递到模板文件中。
第一步,首先我们需要定义类似下面的模型,该模型定义了文章和分类的关系:
from django.db import models
class Category(models.Model):
name = models.CharField(max_lenght=100, unique=True)
class Article(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCAD)
title = models.CharField(max_lenght=100, unique=True)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
第二步,我们需要定义一个视图类,其中视图类中用到的 Article 对象 category_articles
通过使用 query_set 方法获取该视图中定义的 category
对象下的所有文章数据。 为了解决覆盖上下文变量名的问题,我们将自定义 get_context_object_name()
函数,代码如下:
from django.views.generic import ListView
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = 'article_list.html'
context_object_name = 'articles'
def get_queryset(self):
self.category = get_object_or_404(Category, name=self.kwargs['category'])
queryset = Article.objects.filter(category=self.category)
return queryset
def get_context_object_name(self, **kwargs):
context = super().get_context_object_name(**kwargs)
context['category'] = self.category
return context
然后我们将 Category 作为可选请求字典中的键值对传递到视图函数中,并搭配上面定义的get_context_object_name()
函数,最后我们就可以在模板文件 article_list.html
中使用以下代码:
<h1>Category: {{ category.name }} </h1>
{% for article in articles %}
<h2>{{ article.title }}</h2>
{% endfor %}
这样,我们就能从 Category 对象获取到 query_set 中的数据集,通过指定具体的上下文变量名,在模板中引用该变量。
三、实例二
再举一个例子,比如我们要实现带有评论发布功能的博客。在模型中我们可以这样定义:
class Post(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(User, on_delete=models.CASCADE)
published = models.DateTimeField('date published', auto_now_add=True)
content = models.TextField()
class Comment(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
created = models.DateTimeField(auto_now_add=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
这里我们注意到评论与文章之间的关系是多对一(即一篇文章可以拥有多个评论),我们使用 related_query_name 消除了这种关系,并将 post 中的所有评论查询集定位为 'comments'
。
然后我们定义一个视图函数显示带评论的文章内容:
from django.views.generic.detail import DetailView
from .models import Post
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post_detail.html'
context_object_name = 'post'
def get_context_object_name(self, **kwargs):
context = super().get_context_object_name(**kwargs)
add_context = {
'comments': self.object.comments.all(),
}
context.update(add_context)
return context
使用这个视图函数,我们在模板文件中可以得到查询集中的所有数据。在模板文件 blog/post_detail.html
中使用以下代码:
<h1>{{ post.title }}</h1>
{{ post.content|safe }}
{% for comment in comments %}
<p>{{ comment.content }}</p>
{% endfor %}
这个例子中,get_context_object_name()
函数中的相应部分使用了 super()
函数并更新了相应查询集 dict,新的 dict( {'commments': QuerySet[ ] }
)与原本结果并集但是在模板中直接可用。
总结
在以上的例子中,我们清晰地看到了 get_context_object_name()
函数在视图中起到的作用——将查询集中解出 QuerySet 对象并使用该函数打包在字典中,并指定了模板使用该数据的变量名,最终以合适的格式呈现到模板中。在实际应用中,我们可以自定义这个函数,为每一个多继承的视图类定制它的上下文变量名,制造快速模板、视图和模型展示的桥梁。