You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django类视图无法将变量传递至模板的问题求助

相关代码

views.py

from django.shortcuts import render
from .models import CombatEngraving, ClassEngraving, AllClass, Archetype
from django.views import generic
from django.shortcuts import HttpResponse, Http404

def index(request):
    return render(request, 'index.html')

class AllClassListView(generic.ListView):
    model = AllClass
    paginate_by = 5
    context_object_name = 'class_list'
    template_name = 'catalog/class_list.html'

class AllClassDetailView(generic.DetailView):
    model = AllClass

    def all_class_detail_view(request, primary_key):
        try:
            the_class = AllClass.objects.get(pk=primary_key)
        except AllClass.DoesNotExist:
            raise Http404('Class does not exist')
        return render(request, 'catalog/allclass_detail.html', context={'class': the_class})

class CombatEngravingListView(generic.ListView):
    model = CombatEngraving
    paginate_by = 10
    context_object_name = 'combat_engraving_list'
    template_name = 'catalog/combat-engraving.html'

class CombatEngravingDetailView(generic.DetailView):
    model = CombatEngraving

    def combat_engraving_detail_view(request, primary_key):
        try:
            combat_engraving = CombatEngraving.objects.get(pk=primary_key)
        except CombatEngraving.DoesNotExist:
            raise Http404('Combat Engraving does not exist')
        return render(request, 'catalog/combatengraving_detail.html', context={'combat_engraving': combat_engraving})

class_list.html

{% extends "base_generic.html" %}

{% block content %}
  <h1>Class List</h1>
  {% if class_list %}
    <ul>
      {% for class in class_list %}
      <li>
        <a href="{{ class.get_absolute_url }}">{{ class.name }}</a>
        &emsp;|{{class.archetype}}|
        &emsp;{{class.first_class_engraving}}&emsp;
        {{class.second_class_engraving}}
      </li>
      {% endfor %}
    </ul>
  {% else %}
    <p>There are no class in Trixion.</p>
  {% endif %}
{% endblock %}

allclass_detail.html

{% extends "base_generic.html" %}

{% block content %}
  <h1>{{ class.name }}</h1>

  <p><strong>Name:</strong> {{ class.name }}</p>
  <p><strong>Archetype:</strong> {{ class.archetype }}</p>
  <p><strong>First Class Engraving:</strong> {{ class.first_class_engraving }}</p>
  <p><strong>Second Class Engraving:</strong> {{ class.second_class_engraving }}</p>
{% endblock %}

models.py

from django.urls import reverse
from django.db import models
from django.db.models import UniqueConstraint
from django.db.models.functions import Lower

class Archetype(models.Model):
    name = models.CharField(max_length=40, unique=True,help_text="Name of this archetype(e.g. Martial Artist)")

    class Meta:
        ordering = ['name']

    def get_absolute_url(self):
        return reverse('archetype-detail', args=[str(self.id)])

    def __str__(self):
        return self.name

class AllClass(models.Model):
    name = models.CharField(max_length=40, unique=True,help_text="Name of this class(e.g. Wardancer)")
    archetype = models.ForeignKey('Archetype', on_delete=models.RESTRICT, null=True)
    first_class_engraving = models.ForeignKey('ClassEngraving', on_delete=models.RESTRICT, null=True, related_name='first_eng')
    second_class_engraving = models.ForeignKey('ClassEngraving', on_delete=models.RESTRICT, null=True, related_name='second_eng')

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('class-detail', args=[str(self.id)])

    class Meta:
        ordering = ['name']
        constraints = [
            UniqueConstraint(
                Lower('name'),
                name='genre_name_case_insensitive_unique',
                violation_error_message="Class already exists (case insensitive match)"
            ),
        ]

class CombatEngraving(models.Model):
    name = models.CharField(max_length=40, unique=True)
    description = models.TextField(max_length=1000, unique=True)

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('combat-engraving-detail', args=[str(self.id)])

class ClassEngraving(models.Model):
    name = models.CharField(max_length=40, unique=True)
    description = models.TextField(max_length=1000)

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('class-engraving-detail', args=[str(self.id)])

解决方法

问题核心是你继承了Django的generic.DetailView类视图,但在类内部定义的自定义方法(如all_class_detail_view)不会被类视图自动调用,导致模板无法获取到数据。以下是两种可行的修正方案:

方案1:使用DetailView自带功能(推荐)

DetailView已经封装了获取单条模型数据、传递上下文到模板的逻辑,只需指定必要参数即可:

修改views.py中的两个详情视图:

class AllClassDetailView(generic.DetailView):
    model = AllClass
    context_object_name = 'class'  # 指定模板中使用的变量名,默认是小写模型名`allclass`
    template_name = 'catalog/allclass_detail.html'  # 若模板符合<app>/<model>_detail.html命名规则,可省略此行

class CombatEngravingDetailView(generic.DetailView):
    model = CombatEngraving
    context_object_name = 'combat_engraving'
    template_name = 'catalog/combatengraving_detail.html'

方案2:改为函数视图

如果更习惯函数式写法,可移除类视图,改用独立的函数视图,并调整路由配置:

修改views.py

# 移除原类视图,替换为以下函数视图
def all_class_detail_view(request, primary_key):
    try:
        the_class = AllClass.objects.get(pk=primary_key)
    except AllClass.DoesNotExist:
        raise Http404('Class does not exist')
    return render(request, 'catalog/allclass_detail.html', context={'class': the_class})

def combat_engraving_detail_view(request, primary_key):
    try:
        combat_engraving = CombatEngraving.objects.get(pk=primary_key)
    except CombatEngraving.DoesNotExist:
        raise Http404('Combat Engraving does not exist')
    return render(request, 'catalog/combatengraving_detail.html', context={'combat_engraving': combat_engraving})

修改urls.py

将对应路由改为指向函数视图:

path('class/<int:primary_key>/', views.all_class_detail_view, name='class-detail'),
path('combat-engraving/<int:primary_key>/', views.combat_engraving_detail_view, name='combat-engraving-detail'),

补充:类视图自定义逻辑的正确方式

若需在类视图中添加自定义逻辑,应重写get_object()或get_context_data()方法,而非定义新的自定义方法。例如:

class AllClassDetailView(generic.DetailView):
    model = AllClass
    context_object_name = 'class'
    template_name = 'catalog/allclass_detail.html'

    def get_object(self, queryset=None):
        # 自定义获取对象的逻辑,比如额外过滤或处理
        obj = super().get_object(queryset=queryset)
        # 可在此对obj进行额外操作
        return obj

内容的提问来源于stack exchange,提问作者Trantor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:21:01