如何将非字段相关的日期范围添加到 Django 管理表单

How do I add non-field related date range to Django admin form

我有一个 django 管理页面,它仅用于查看目的,而不是显示来自模型的数据,它显示由外键链接到中间 table 的 table 的数据通过外键链接到我的模型。我想在第三个 table.

上应用日期范围过滤器
class Brand(models.Model):
   data ...

class Organisation (models.Model):
   data ...
   brand = models.ForeignKey(Brand, on_delete=models.CASCADE)

class DailyStat (models.Model):
   stat_type = model.CharField(max_lenth=11, choices=STAT_TYPE_CHOICES
   date = models.DateField()
   organisation = models.ForeignKey(Organisation, on_delete=models.CASCADE)

然后我在 'templates/admin/brand' 中创建了一个 change_form.html 模板,它显示了我想要用于品牌的 DailyStat 数据。

但我希望能够对此进行过滤,所以我创建了一个新表单

class BrandAdminForm(forms.ModelForm):
    from_date = forms.DateField(widget=admin.widgets.AdminDateWidget())
    to_date = forms.DateField(widget=admin.widgets.AdminDateWidget())
    class Meta:
        model = Brand
        fields = ['id','from_date','to_date']

并在 BrandAdmin 定义中引用它

class BrandAdmin(admin.ModelAdmin):
    list_display = ['name','get_page_views','cqc_brand_id']
    ordering = ['name']
    search_fields = ['name']
    form = BrandAdminForm

这些字段不会自动显示在详细信息页面中,因此我在 change_form.html

{% block content %} 的表单标签中添加了以下内容
<table style="width:60%">
    <tr>
        <td>From: </td>
        <td>{{ adminform.form.from_date }}</td>
        <td rowspan=2><button type="submit" value="Save and continue editing" class="btn viewsitelink">Filter</button></td>
    </tr>
    <tr>
        <td>To: </td>
        <td>{{ adminform.form.to_date }}</td>
    </tr>
</table>

所以字段现在显示在表单中(我还没有编写使用字段的处理)但是,我是 运行 django-cms,当我点击过滤器按钮时,它不是' t 返回到 django-cms 管理面板下的页面,而不是返回到管理视图。

如果有更好的方法,我怎样才能更有效地过滤我需要的数据,或者我做错了什么,它没有返回到正确的视图(表单标签显示 action="" )

谢谢

这绝对可行,但您应该考虑以下几点:

  • 这并不是改变视图的真正目的。从用户体验的角度来看,(在本质上是一个大表单的页面上)与您提交的表单无关的表单元素感觉很奇怪。
  • django admin 并不是一个面向用户的生产就绪环境。如果你想让它做一些不容易做的事情,这通常是一个好兆头,你应该在这里发表自己的观点。

你的方法有问题

modelAdmin.form 属性是一种显示来自相关模型实例的数据并将返回的 POST 数据保存回同一实例的表单。

这不是视图最终实际使用的形式。它是 django-admin 用来构建最终使用的表单的表单。管理应用程序在此过程中做了相当多的处理,基于在 modelAdmin 上设置的属性,因此将(不相关的)字段添加到 modelAdmin.form 不一定与最终呈现的表单上的字段相对应。

如果要添加 to_datefrom_date,则应以单独的形式完成。 (一方面,如果不提交整个表格,您将无法更改日期)。

解决方案

您最好添加一个单独的表单,并使用 GET 查询参数来更新您的日期。像这样:

class DateForm(forms.Form):
    from_date = forms.DateField(widget=admin.widgets.AdminDateWidget())
    to_date = forms.DateField(widget=admin.widgets.AdminDateWidget())

class BrandAdmin(admin.ModelAdmin):
    ...
    def change_view(self, request, object_id, form_url="", extra_context=None):
        date_form = DateForm(request.GET)
        if extra_context is None:
            extra_context = {}
        extra_context['date_form'] = date_form
        return super().change_view(
            request, object_id, form_url="", extra_context=extra_context
        )

然后在您的 change_form 模板中

{% block content %}
<form method="get">
    {{date_form}}
    <input type="submit" value="Update dates">
</form>
{{ block.super }}
{% endblock %}

您现在可以在您的模板中访问 to_datefrom_date,您可以在其中列出您的通过 request.GET,然后您应该能够使用它们进行过滤。