Django regroup标签传值异常:如何提取GroupedResult中的分类名称
问题
我有一个包含Productos和Categorias模型的网页,导航栏需按分类筛选Productos。为实现动态效果,我从Productos模型获取分类并使用regroup标签处理后传入导航栏。但在视图中接收regroup传递的参数时,得到的是字符串形式的GroupedResult(如GroupedResult(grouper=<Categorias: Guantes de Box>, list=[<Productos: Guantes Básico ADX>])),尝试用getattr获取grouper等属性时均报AttributeError(提示'str'对象无对应属性),索引取值也只能拿到字符串字符。我需要获取其中的分类名称(如Guantes de Box)来完成产品筛选,请问该如何解决?
相关代码
视图代码
class Categoria_Filter(ListView): model = Productos paginate_by = 10 template_name = 'mail/category-filter.html' def get_queryset(self): categoria = self.kwargs['slug'] print(categoria) if categoria == 'Todos': return Productos.objects.all() else: return Productos.objects.filter(categoria = categoria)
模板代码
{% regroup object_list by categoria as categoria_list %} {% for item in categoria_list%} <li class="nav-item"> <a class="nav-link text-white" href="{% url 'categoria-filter' item %}">{{ item.grouper }}</a> </li> {% endfor %}
解决方案
问题核心在于模板中传递给URL的是整个GroupedResult对象,Django生成URL时会把这个对象转换成字符串形式,导致视图接收到的是对象的字符串表示而非分类对象本身,自然无法读取属性。
步骤1:修改模板,传递分类的唯一标识
不要直接传递item,而是传递分类对象(item.grouper)的唯一标识,比如slug或ID。假设你的Categorias模型有slug字段(用于URL友好的字符串标识),修改模板中的URL生成部分:
{% regroup object_list by categoria as categoria_list %} {% for item in categoria_list%} <li class="nav-item"> <a class="nav-link text-white" href="{% url 'categoria-filter' item.grouper.slug %}">{{ item.grouper }}</a> </li> {% endfor %}
如果没有slug字段,也可以用ID:
<a class="nav-link text-white" href="{% url 'categoria-filter' item.grouper.id %}">{{ item.grouper }}</a>
注意要对应URL配置中的参数类型(比如<int:slug>或<str:slug>)。
步骤2:修改视图的过滤逻辑
视图中接收到的是分类的slug或ID字符串,不能直接用categoria = categoria筛选(这会把字符串和Categorias对象做比较,匹配失败),需要通过外键的对应字段筛选:
如果用slug:
def get_queryset(self): categoria = self.kwargs['slug'] print(categoria) if categoria == 'Todos': return Productos.objects.all() else: return Productos.objects.filter(categoria__slug=categoria)
如果用ID:
def get_queryset(self): categoria_id = self.kwargs['slug'] print(categoria_id) if categoria_id == 'Todos': return Productos.objects.all() else: return Productos.objects.filter(categoria__id=categoria_id)
额外提示
建议在Categorias模型中定义slug字段并配置自动生成规则,让URL更友好:
from django.utils.text import slugify class Categorias(models.Model): nombre = models.CharField(max_length=100) slug = models.SlugField(unique=True, blank=True) def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.nombre) super().save(*args, **kwargs) def __str__(self): return self.nombre
内容的提问来源于stack exchange,提问作者Jorge López

