我正在尝试通过将外键的值设置为url slug来过滤查询集。
class Parent(models.Model):
parent_name = models.CharField(unique=True, max_length=40)
parent_slug = models.SlugField(unique=True)
class Child(models.Model):
child_name = models.CharField(unique=True, max_length=40, default=1)
child_slug = models.SlugField(unique=True, default=1)
parent_slug = models.ForeignKey(Parent, on_delete=models.CASCADE,default = 1)
from .views import ChildListView
urlpatterns = [
...
path('<parent_slug>/children/', ChildListView.as_view(), name='child_list'),
...
]
class ChildListView(ListView):
template_name = 'child_list.html'
context_object_name = 'child'
def get_queryset(self):
slug_param = self.kwargs['parent_slug']
qs = Child.objects.filter(parent_slug = slug_param)
return qs
这是错误结果:
异常值:
无法将关键字“父级”解析为字段。
答案 0 :(得分:1)
您需要过滤parent_slug
对象(简称为Parent
)的parent_slug
,因此您可以使用以下方法进行过滤:
class ChildListView(ListView):
template_name = 'child_list.html'
context_object_name = 'child'
def get_queryset(self):
return Child.objects.filter(parent_slug__parent_slug=self.kwargs['parent_slug'])
话虽这么说,建模中的术语有点 odd 。通常,字段 not 都以模型名称为前缀,并且ForeignKey
是指该字段所引用的模型对象,而不是其子对象。此外,为default=1
设置ForeignKey
可能没有多大意义,因为以后可能引用与您持有的对象不同的对象。最后将default=1
设置为SlugField
绝对没有多大意义。
定义模型的更好方法是:
class Parent(models.Model):
name = models.CharField(unique=True, max_length=40)
slug = models.SlugField(unique=True)
class Child(models.Model):
name = models.CharField(unique=True, max_length=40)
slug models.SlugField(unique=True)
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
我们甚至可以将name
和slug
提取成抽象的基本模型(例如NameSlugModel
),例如:
class NameSlugModel(models.Model):
name = models.CharField(unique=True, max_length=40)
slug = models.SlugField(unique=True)
class Meta:
abstract = True
class Parent(NameSlugModel):
pass
class Child(NameSlugModel):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
在这种情况下,您可以使用:
class ChildListView(ListView):
template_name = 'child_list.html'
context_object_name = 'child'
def get_queryset(self):
return Child.objects.filter(parent__slug=self.kwargs['parent_slug'])