views:

1670

answers:

3

In django admin I wanted to set up a custom filter by tags (tags are introduced with django-tagging)

I've made the ModelAdmin for this and it used to work fine, by appending custom urlconf and modifying the changelist view. It should work with URLs like: http://127.0.0.1:8000/admin/reviews/review/only-tagged-vista/

But now I get 'invalid literal for int() with base 10: 'only-tagged-vista', error which means it keeps matching the review edit page instead of the custom filter page, and I cannot figure out why since it used to work and I can't find what change might have affected this.

Any help appreciated.

Relevant code:

class ReviewAdmin(VersionAdmin):

    def changelist_view(self, request, extra_context=None, **kwargs): 
        from django.contrib.admin.views.main import ChangeList 
        cl = ChangeList(request, self.model, list(self.list_display), 
                        self.list_display_links, self.list_filter, 
                        self.date_hierarchy, self.search_fields,  
                        self.list_select_related, 
                        self.list_per_page, 
                        self.list_editable, 
                        self) 
        cl.formset = None

        if extra_context is None: 
            extra_context = {}

        if kwargs.get('only_tagged'): 
            tag = kwargs.get('tag')
            cl.result_list = cl.result_list.filter(tags__icontains=tag) 
            extra_context['extra_filter'] = "Only tagged %s" % tag

        extra_context['cl'] = cl
        return super(ReviewAdmin, self).changelist_view(request, extra_context=extra_context)

    def get_urls(self): 
        from django.conf.urls.defaults import patterns, url 
        urls = super(ReviewAdmin, self).get_urls()

        def wrap(view):
            def wrapper(*args, **kwargs):
                return self.admin_site.admin_view(view)(*args, **kwargs)
            return update_wrapper(wrapper, view)

        info = self.model._meta.app_label, self.model._meta.module_name 
        my_urls = patterns('', 
                # make edit work from tagged filter list view
                # redirect to normal edit view
                url(r'^only-tagged-\w+/(?P<id>.+)/$',
                    redirect_to,
                    {'url': "/admin/"+self.model._meta.app_label+"/"+self.model._meta.module_name+"/%(id)s"}
                    ),
                # tagged filter list view
                url(r'^only-tagged-(P<tag>\w+)/$',  
                    self.admin_site.admin_view(self.changelist_view), 
                     {'only_tagged':True}, name="changelist_view"), 
        ) 

        return my_urls + urls

Edit: Original issue fixed.

I now receive 'Cannot filter a query once a slice has been taken.' for line:

cl.result_list = cl.result_list.filter(tags__icontains=tag)

I'm not sure where this result list is sliced, before tag filter is applied.

Edit2: It's because of the self.list_per_page in ChangeList declaration. However didn't find a proper solution yet. Temp fix:

        if kwargs.get('only_tagged'):
            list_per_page = 1000000
        else:
            list_per_page = self.list_per_page 
        cl = ChangeList(request, self.model, list(self.list_display), 
                        self.list_display_links, self.list_filter, 
                        self.date_hierarchy, self.search_fields,  
                        self.list_select_related, 
                        list_per_page, 
                        self.list_editable, 
                        self)
A: 

In code sample above, get_urls() is aligned so that it is not part of ReviewAdmin class but rather a separate function. I guess that can cause your problem if you have it the same way in real source.

che
That is just a problem with formatting, when posting here.
Béres Botond
+2  A: 

You're missing a question mark in before the P in '^only-tagged-(P<tag>\w+)/$', so the expression won't match.

Daniel Roseman
Indeed, I've missed that, thanks.Now I'm getting a further issue though.
Béres Botond
A: 

The error apears on multi-word tags because you match just one word tags. this works: r'^only-tagged-(?P[^/]+)/$'

myneur
...and if you urlencode instead of slugify, it will search even tags with unicode characters...
myneur