Skip to main content
Bounty Ended with 50 reputation awarded by CommunityBot
deleted 4 characters in body
Source Link
tim-mccurrach
  • 6.7k
  • 4
  • 25
  • 42

This is definitely doable, but there are a few things you should consider:

  • This isn't really what a change-view is meant for. It feels weird from a UX perspective to have (on a page which is essentially one big form) form-elements unrelated to the form you are submitting.
  • django admin is not meant to be a user-facing production ready environment. If you're trying to make it do things it's not easy to do, it's normally a good sign you should be making your own views here.

The problem with your approach

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 you wouldn't be able to change the dates without submitting your whole form).

Solution

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.

This is definitely doable, but there are a few things you should consider:

  • This isn't really what a change-view is meant for. It feels weird from a UX perspective to have (on a page which is essentially one big form) form-elements unrelated to the form you are submitting.
  • django admin is not meant to be a user-facing production ready environment. If you're trying to make it do things it's not easy to do, it's normally a good sign you should be making your own views here.

The problem with your approach

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 you wouldn't be able to change the dates without submitting your whole form).

Solution

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.

This is definitely doable, but there are a few things you should consider:

  • This isn't really what a change-view is meant for. It feels weird from a UX perspective to have (on a page which is essentially one big form) form-elements unrelated to the form you are submitting.
  • django admin is not meant to be a user-facing production ready environment. If you're trying to make it do things it's not easy to do, it's normally a good sign you should be making your own views here.

The problem with your approach

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).

Solution

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.

Source Link
tim-mccurrach
  • 6.7k
  • 4
  • 25
  • 42

This is definitely doable, but there are a few things you should consider:

  • This isn't really what a change-view is meant for. It feels weird from a UX perspective to have (on a page which is essentially one big form) form-elements unrelated to the form you are submitting.
  • django admin is not meant to be a user-facing production ready environment. If you're trying to make it do things it's not easy to do, it's normally a good sign you should be making your own views here.

The problem with your approach

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 you wouldn't be able to change the dates without submitting your whole form).

Solution

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.