views:

3873

answers:

9

Before Django 1.0 there was an easy way to get the admin url of an object, and I had written a small filter that I'd use like this: <a href="{{ object|admin_url }}" .... > ... </a>

Basically I was using the url reverse function with the view name being 'django.contrib.admin.views.main.change_stage'

reverse( 'django.contrib.admin.views.main.change_stage', args=[app_label, model_name, object_id] )

to get the url.

As you might have guessed, I'm trying to update to the latest version of Django, and this is one of the obstacles I came across, that method for getting the admin url doesn't work anymore.

How can I do this in django 1.0? (or 1.1 for that matter, as I'm trying to update to the latest version in the svn).

+1  A: 

I solved this by changing the expression to:

reverse( 'django-admin', args=["%s/%s/%s/" % (app_label, model_name, object_id)] )

This requires/assumes that the root url conf has a name for the "admin" url handler, mainly that name is "django-admin",

i.e. in the root url conf:

url(r'^admin/(.*)', admin.site.root, name='django-admin'),

It seems to be working, but I'm not sure of its cleanness.

hasen j
This works for 1.0, but will not work for 1.1, which has a better solution: see Alex Koshelev's answer.
Carl Meyer
Actually I tried it and it didn't work, and he said it's for 1.0, no?
hasen j
Syntax has changed in 1.1 with the introduction of url namespacing: http://docs.djangoproject.com/en/dev/topics/http/urls/#topics-http-reversing-url-namespaces
sleepyjames
+3  A: 

For pre 1.1 django it is simple (for default admin site instance):

reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,))
Alex Koshelev
A: 

I have the same problem. For some reason, reverse("admin_index") won't work with 1.1 beta 1 SVN-10645, and neither will Alex's solution. Does anyone have a clue on this?

Stavros Korokithakis
checkout bskinner's solution.
hasen j
That worked, thank you.
Stavros Korokithakis
+12  A: 

I had a similar issue where I would try to call reverse('admin_index') and was constantly getting django.core.urlresolvers.NoReverseMatch errors.

Turns out I had the old format admin urls in my urls.py file.

I had this in my urlpatterns:

(r'^admin/(.*)', admin.site.root),

which gets the admin screens working but is the deprecated way of doing it. I needed to change it to this:

(r'^admin/', include(admin.site.urls) ),

Once I did that, all the goodness that was promised in the Reversing Admin URLs docs started working.

bskinner
nice, thanks for the update!
hasen j
Awesome, this fixed another issue I was having with the get_urls() method of ModelAdmin not being called. Thanks!
Arnaud
Thank you, so very, very much. This is one of those things where, in the docs, I didn't see any mention of the regex string, only that it should point to the admin.site.urls instead of admin.site.root. It would have taken me a very long time to figure this one out.
jnadro52
A: 

None of the solutions work in Django 1.0.2

DataGreed
+2  A: 

If you are using 1.0, try making a custom templatetag that looks like this:

def adminpageurl(object, link=None):
    if link is None:
        link = object
    return "<a href=\"/admin/%s/%s/%d\">%s</a>" % (
        instance._meta.app_label,
        instance._meta.module_name,
        instance.id,
        link,
    )

then just use {% adminpageurl my_object %} in your template (don't forget to load the templatetag first)

DarwinSurvivor
+3  A: 
from django.core.urlresolvers import reverse
def url_to_edit_object(object):
  url = reverse('admin:%s_%s_change' %(object._meta.app_label,  object._meta.module_name),  args=[object.id] )
  return u'<a href="%s">Edit %s</a>' %(url,  object.__unicode__())

This is similar to hansen_j's solution except that it uses url namespaces, admin: being the admin's default application namespace.

GufyMike
+6  A: 

You can use the URL resolver directly in a template, there's no need to write your own filter. E.g.

{% url admin:index %}

{% url admin:polls_choice_add %}

{% url admin:polls_choice_change choice.id %}

markmuetz
markmuetz - Is this in the official Django docs anywhere? (how to use admin reverse URLs in templates)? If not, it should be.
shacker
shacker - It's all in the docs... just not in one place. The "url" template tag is documented [here](http://docs.djangoproject.com/en/1.2/ref/templates/builtins/#url). In the section "New in Django 1.1:" the docs say that namespaced URLs are fine, and points you to [the section on URL namespaces](http://docs.djangoproject.com/en/1.2/topics/http/urls/#topics-http-reversing-url-namespaces). Sticking it all together lets you reference the admin application easily in templates.N.B I remember the docs being different when I wrote the reply.
markmuetz
A: 

Here's another option, using models:

Create a base model (or just add the admin_link method to a particular model)

class CommonModel(models.Model):
    def admin_link(self):
        if self.pk:
            return mark_safe(u'<a target="_blank" href="../../../%s/%s/%s/">%s</a>' % (self._meta.app_label,
                    self._meta.object_name.lower(), self.pk, self))
        else:
            return mark_safe(u'')
    class Meta:
        abstract = True

Inherit from that base model

   class User(CommonModel):
        username = models.CharField(max_length=765)
        password = models.CharField(max_length=192)

Use it in a template

{{ user.admin_link }}

Or view

user.admin_link()
Ian Cohen