I have a django admin page which is for viewing purposes only and rather than displaying data from the model, it is displaying data for a table linked by a foreignkey to an intermediate table which is linked via a foreign key to my model. I want to apply a date range filter on the third 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)
I then created a change_form.html template in 'templates/admin/brand' which displays the data from DailyStat which I want for the Brand.
But I want to be able to filter this so I created a new form
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']
And within the BrandAdmin definition, referenced it
class BrandAdmin(admin.ModelAdmin):
list_display = ['name','get_page_views','cqc_brand_id']
ordering = ['name']
search_fields = ['name']
form = BrandAdminForm
These fields didn't automatically show in the detail page so I added the following within the form tags of {% block content %}
of the change_form.html
<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>
So the fields now show in the form (I haven't written the processing to use the fields yet) BUT, I am running django-cms and when I click the filter button, it isn't returning to the pages under the django-cms admin panel rather than returning to the admin view.
If there is a better approach, how can I get to filtering the data I require more effectively OR what am I doing wrong that it isn't returning to the correct view (the form tag shows action=""
)
Thanks
This is definitely doable, but there are a few things you should consider:
The modelAdmin.form
attribute, is meant to be a form which displays data from an instance of the relevant model, and which saves the returned POST data back to that same instance.
It isn't the form the view actually uses in the end. It is the form django-admin uses to build the form that is finally used though. The admin app does quite a bit of processing along the way, based off attributes that are set on modelAdmin
so adding (unrelated) fields to modelAdmin.form
won't necessarily correspond to fields on the finally rendered form.
If you want to add in to_date
and from_date
it should be done in a separate form. (For one thing, you otherwise wouldn't be able to change the dates without submitting your whole form).
You are far better to add a separate form, and use GET
query parameters to update your dates. Something like this:
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
)
Then in your change_form template
{% block content %}
<form method="get">
{{date_form}}
<input type="submit" value="Update dates">
</form>
{{ block.super }}
{% endblock %}
You will now have access to to_date
and from_date
in your template where you list your via request.GET
and you should then be able to filter using them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With