Keeping filters in Django Admin

前端 未结 7 972
走了就别回头了
走了就别回头了 2021-02-04 20:23

What I would like to achive is:

  • I go to admin site, apply some filters to the list of objects
  • I click and object edit, edit, edit, hit \'Save\'
相关标签:
7条回答
  • 2021-02-04 20:33

    There is a change request at the Django project asking for exactly this functionality.

    All it's waiting for to be checked in is some tests and documentation. You could write those, and help the whole project, or you could just take the proposed patch (near the bottom of the page) and try it out.

    https://code.djangoproject.com/ticket/6903

    0 讨论(0)
  • 2021-02-04 20:39

    There's a simple hack to do this, but it's not a general solution and requires modifying every ModelAdmin which you want to support this. Maybe there is a general way to do this, but I've not spent the time to solve it on a general level.

    The first step is to write a custom FilterSpec for the filter (see Harley's post for links that will help) which saves the chosen filter value in the session (and deletes it when no longer wanted).

    # in cust_admin/filterspecs.py
    from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec
    
    class MyFilterSpec(ChoicesFilterSpec):
    
        def __init__(self, f, request, params, model, model_admin):
            super(MyFilterSpec, self).__init__(f, request, params, model,
                                               model_admin)
            if self.lookup_val is not None:
                request.session[self.lookup_kwarg] = self.lookup_val
            elif self.lookup_kwarg in request.session:
                del(request.session[self.lookup_kwarg])
    
    # Register the filter with a test function which will apply it to any field
    # with a my_filter attribute equal to True
    FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'my_filter', False),
                                   MyFilterSpec))
    

    You must import the module this is in somewhere, for example your urls.py:

    # in urls.py
    from cust_admin import filterspecs
    

    Set a property on the field you want to apply the filter to:

    # in models.py
    class MyModel(models.Model):
        my_field = Models.IntegerField(choices=MY_CHOICES)
        my_field.my_filter = True
    

    In a custom ModelAdmin class, override the change_view method, so that after the user clicks save, they are returned to the list view with their filter field value added to the URL.

    class MyModelAdmin(admin.ModelAdmin):
        def change_view(self, request, object_id, extra_context=None):
            result = super(MyModelAdmin, self).change_view(request, object_id,
                                                           extra_context)
            if '_save' in request.POST:
                if 'my_field__exact' in request.session:
                    result['Location'] = '/admin/myapp/mymodel/?my_field__exact=%s' \
                                         % request.session['my_field__exact']
            return result
    
    0 讨论(0)
  • 2021-02-04 20:39

    Another way to do this is to embed the filter in the queryset.

    You can dynamically create a proxy model with a manager that filters the way you want, then call admin.site.register() to create a new model admin. All the links would then be relative to this view.

    0 讨论(0)
  • 2021-02-04 20:46

    In my opinion its better to override methods from ModelAdmin changelist_view and change_view:

    Like so:

    class FakturaAdmin(admin.ModelAdmin):
    
    [...]
    
    def changelist_view(self, request, extra_context=None):
        result = super(FakturaAdmin, self).changelist_view(request, extra_context=None)
        request.session['qdict'] = request.GET
        return result
    
    def change_view(self, request, object_id, extra_context=None):
        result = super(FakturaAdmin, self).change_view(request, object_id, extra_context)
        try:
            result['location'] = result['location']+"?"+request.session['qdict'].urlencode()
        except:
            pass
        return result
    

    As you wish, after save object you go back to list of objects with active filters.

    0 讨论(0)
  • 2021-02-04 20:50

    Unfortunately there's no easy way to do this. The filtering does not seem to be saved in any session variable.

    Clicking back twice is the normal method, but it can be unweildy and annoying if you've just changed an object so that it should no longer be shown using your filter.

    If it's just a one-off, click back twice or go through the filtering again, it's the easiest way.

    If you're going to be filtering more often, or you just want to learn about hacking the admin (which is pretty open and easy), you'll want to write a FilterSpec.

    Have a look here and here for examples of people writing their own.

    A really, really terrible way to do this would be to edit the admin interface so that after you click "Save", you are redirected to you filtered URL. I wouldn't recommend this at all, but it's an option.

    Another fairly simple way to do this would be to write a generic view to show your filtered objects, then use Django forms to edit the items from there. I'd have a look at this, you'll be stunned just how little code you have to write to get a simple view/edit page going.

    0 讨论(0)
  • 2021-02-04 20:53

    Click 2 times "Back"?

    0 讨论(0)
提交回复
热议问题