首页 > 解决方案 > 如何为孩子使用通用视图

问题描述

我开始学习如何使用通用视图。考虑到我们有一个外键到父级。如何使用通用视图创建子视图?这与我们创建父视图的方式相同吗?

意见?.py

class ChildCreateView(generic.CreateView):
    template_name = "app/create_child.html"
    model = Child
    form_class = ChildForm
    success_url = reverse_lazy("app:index_child")

模型.py

class Parent(models.Model):
    pass

class Child(models.Model):
    parent = models.ForeignKey(Parent, on_delete=models.CASCADE)

意见1.py

class ParentCreateView(generic.CreateView):
    template_name = "app/create_parent.html"
    model = Parent
    form_class = ParentForm
    success_url = reverse_lazy("app:index_parent")

标签: djangodjango-generic-views

解决方案


您需要向子视图传达父视图是什么。常见的解决方案是使用嵌套 url:

urlpatterns = [
    path("/app/parents/", ParentListView.as_view()),
    path("/app/parents/<int:parent_id>/", ParentDetailView.as_view()),
    path("/app/parents/<int:parent_id>/children/", ChildListView.as_view()),
    path("/app/parents/<int:parent_id>/children/<int:child_id>/", ChildDetailView.as_view()),
]

现在您可以在 ChildDetailView 中将子级限制为特定的父级:

class ChildDetailView(generic.DetailView):
    model = Child
    pk_url_kwarg = 'child_id'

    def get_queryset(self, queryset):
        qs = super().get_queryset(queryset)
        return qs.filter(parent__pk=self.kwargs['parent_id'])

class ChildCreateView(generic.CreateView):
    model = Child
    pk_url_kwarg = 'child_id'

    def get_queryset(self, queryset):
        qs = super().get_queryset(queryset)
        return qs.filter(parent__pk=self.kwargs['parent_id'])

class ChildUpdate...

等等,这会重复:

class NestedParentMixin(generic.base.SingleObjectMixin):
    parent_lookup = 'parent__pk'
    parent_url_kwarg = 'parent_id'

    def get_queryset(self, queryset):
        qs = super().get_queryset(queryset)
        filter_kwargs = {self.parent_lookup: self.kwargs[self.parent_url_kwarg]}
        return qs.filter(**filter_kwargs)


class ChildDetailView(NestedParentMixin, generic.DetailView):
    model = Child
    pk_url_kwarg = 'child_id'

class ChildUpdateView(NestedParentMixin, generic.UpdateView):
    model = Child
    pk_url_kwarg = 'child_id'

class SiblingDetailView(NestedParentMixin, generic.DetailView):
    model = Sibling
    pk_url_kwarg = 'sibling_id'

推荐阅读