【问题标题】:Show a paginated ListView and an UpdateView on the same template page在同一模板页面上显示分页 ListView 和 UpdateView
【发布时间】:2018-04-13 16:50:42
【问题描述】:

我正在尝试创建一个Django 页面,其中可以更新某些内容并可以在分页表中查看某些内容。模型如下所示:

class CostGroup(models.Model):
    name = models.CharField(max_length=200)
    description = models.CharField(max_length=200)

    def get_absolute_url(self):
        return reverse(
            'costgroup_detail', 
            kwargs={
                'costgroup_pk': self.pk,
            }
        )


class Cost(models.Model):
    cost_group = models.ForeignKey(CostGroup)
    amount = models.DecimalField(max_digits=50, decimal_places=2)

    def get_absolute_url(self):
        return reverse(
            'cost_detail', 
            kwargs={
                'cost_pk': self.pk,
            }
        )

因此,编辑表单适用于CostGroup 模型的name 和description 字段,表格应显示“金额”列表

我之前只为表单和表单模板中包含的表格添加了UpdateView。但是现在,由于我想在表格中包含分页,我需要在同一页面上使用两个视图。我设计的页面最终应该是这样的:

我现在并不担心样式,我目前的主要关注点是将表单和表格放在同一页面上。在当前状态下,我唯一没有的是表格的分页:

当前视图如下所示:

class CostDetail(UpdateView):
    model = models.Cost
    pk_url_kwarg = 'cost_pk'
    template_name = 'main/cost_detail.html'
    form_class = forms.CostDetailEditForm
    success_url = reverse_lazy('cost_list')

我觉得利用 Django CBV 使用的底层 mixin 可能是可行的方法,但我不知道如何开始。

任何帮助将不胜感激

感谢您的宝贵时间

【问题讨论】:

    标签: django pagination django-class-based-views


    【解决方案1】:

    我现在正在开发的一个应用程序使用了类似的方法。我从 ListView 开始,引入 FormMixin,然后从 FormView 引入 post()。

    class LinkListView(FormMixin, ListView):
        model = Link
        ordering =  ['-created_on']
        paginate_by = 10
        template_name = 'links/link_list.html'
    
        form_class = OtherUserInputForm
    
        #=============================================================================#
        #
        #     Handle form input
        #
    
        def post(self, request, *args, **kwargs):
            """
            Handles POST requests, instantiating a form instance with the passed
            POST variables and then checked for validity.
            """
            form = self.get_form()
            self.form = form
            if form.is_valid():
                return self.form_valid(form)
            else:
                return self.form_invalid(form)
    
        def put(self, *args, **kwargs):
            return self.post(*args, **kwargs)
    
        def get_success_url(self):
            return reverse('links')
    

    您可能还希望覆盖 get_object()、get_queryset() 和 get_context()。

    【讨论】:

    • 谢谢。我不太确定覆盖。目前页面正在呈现没有数据,所以显然我需要它们,但我真的不知道在这种情况下如何使用它们?我以前只真正使用过 get_context_data() 。您能否详细说明您的建议?
    【解决方案2】:

    (这个澄清作为一个新的答案似乎效果更好)

    看起来您正在处理这两个表。对象级别使用 CostGroup,而列表视图显示链接到 CostGroup 的 Cost 中的子记录。假设这是真的,我会这样做:

    class CostDetail(ModelFormMixin, ListView):
    
        model = CostGroup   # Using the model of the record to be updated
        form_class = YourFormName  # If this isn't declared, get_form_class() will
                                   # generate a model form 
    
    
        ordering =  ['id']
        paginate_by = 10
        template_name = 'main/cost_detail.html' # Must be declared
    
        def get_queryset(self):
            # Set the queryset to use the Cost objects that match the selected CostGroup
            self.queryset = Cost.objects.filter(cost_group = get_object())
            # Use super to add the ordering needed for pagination
            return super(CostDetail,self).get_queryset()
    
        # We want to override get_object to avoid using the redefined get_queryset above
        def get_object(self,queryset=None):  
            queryset = CostGroup.objects.all()
            return super(CostDetail,self).get_object(queryset))
    
        # Include the setting of self.object in get()
        def get(self, request, *args, **kwargs):
    
            # from BaseUpdateView
            self.object = self.get_object()
    
            return super(CostDetail,self).get(request, *args, **kwargs)
    
        # Include the contexts from both
        def get_context_data(self, **kwargs):
    
            context = ModelFormMixin.get_context_data(**kwargs)
            context = ListView.get_context_data(**context)
            return context
    
        # This is the post method found in the Update View
        def post(self, request, *args, **kwargs):
    
            # From BaseUpdateView
            self.object = self.get_object()
    
            # From ProcessFormView
            form = self.get_form()
            self.form = form
            if form.is_valid():
                return self.form_valid(form)
            else:
                return self.form_invalid(form)
    
        def put(self, *args, **kwargs):
            return self.post(*args, **kwargs)
    

    我没有尝试运行这个,所以可能会有错误。祝你好运!

    (记住 ccbv.co.uk 是您深入研究基于类的视图时的朋友)

    【讨论】:

    • 是的,感谢您为我解决这个问题!设法使它与一些调整一起工作。感谢您的帮助
    • @BeeNag 你愿意发布你需要做的调整吗?
    • @hlongmore 据我所知,我使用的代码现在已经更改,我使用 Dashdrum 的答案作为起点,但最后我所做的只是使用我原来的我为 get_queryset、get_context_data 和 get_form 编写了自定义方法(这是表单方法之一,我不记得是哪一个了)。然后我从视图中删除了 form_class。由于在这两种情况下数据都来自同一个查询集,因此我用所需的数据和表格填充表单相对简单。我希望这是有道理的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 2012-10-08
    相关资源
    最近更新 更多