Obtendo o URL de administração do Django para um objeto

168

Antes do Django 1.0, havia uma maneira fácil de obter o URL de administração de um objeto, e eu havia escrito um pequeno filtro que usaria assim: <a href="{{ object|admin_url }}" .... > ... </a>

Basicamente, eu estava usando a função reversa de URL com o nome da exibição sendo 'django.contrib.admin.views.main.change_stage'

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

para obter o URL.

Como você deve ter adivinhado, estou tentando atualizar para a versão mais recente do Django, e este é um dos obstáculos que encontrei, esse método para obter o URL do administrador não funciona mais.

Como posso fazer isso no django 1.0? (ou 1.1 nesse caso, pois estou tentando atualizar para a versão mais recente no svn).

hasen
fonte

Respostas:

61

Eu tive um problema semelhante em que tentava ligar reverse('admin_index')e estava constantemente recebendo django.core.urlresolvers.NoReverseMatcherros.

Acontece que eu tinha os URLs de administrador de formato antigo no meu arquivo urls.py.

Eu tinha isso nos meus padrões de URL:

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

que faz com que as telas de administração funcionem, mas é a maneira obsoleta de fazê-lo. Eu precisava mudar para isso:

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

Depois disso, toda a bondade prometida nos documentos dos URLs de administrador reverso começou a funcionar.

bskinnersf
fonte
Impressionante, isso corrigiu outro problema que eu estava tendo com o método get_urls () do ModelAdmin que não estava sendo chamado. Obrigado!
Arnaud
8
melhor URL para este problema: docs.djangoproject.com/en/dev/ref/contrib/admin/…
Dingo
4
Esta "resposta" não está correta, apenas mostra como adicionar corretamente o aplicativo de administrador ao seu aplicativo, o que resolveu um problema diferente que o autor tinha. A verdadeira resposta para a pergunta real é abaixo - de markmuetz
Declan Shanaghy
Além disso, você precisa ter uma interface administrativa registrada para o modelo, caso contrário, o URL não existirá.
Flimm 03/02
412

Você pode usar o resolvedor de URL diretamente em um modelo, não há necessidade de escrever seu próprio filtro. Por exemplo

{% url 'admin:index' %}

{% url 'admin:polls_choice_add' %}

{% url 'admin:polls_choice_change' choice.id %}

{% url 'admin:polls_choice_changelist' %}

Ref: Documentação

markmuetz
fonte
1
markmuetz - Isso está nos documentos oficiais do Django em algum lugar? (como usar URLs de administrador reverso em modelos)? Se não, deveria ser.
shacker 29/07/10
7
shacker - Está tudo na documentação ... mas não em um só lugar. A tag do modelo "url" está documentada aqui . Na seção "Novo no Django 1.1:", os documentos dizem que os URLs com espaço para nome são bons e apontam para a seção sobre espaços para nome de URL . Ao juntar tudo isso, você pode fazer referência ao aplicativo de administração facilmente nos modelos. NB: Lembro que os documentos eram diferentes quando escrevi a resposta.
MarkMuetz
3
Você sabe como obter um link para a "lista" de opções? Exemplo: se "{% url admin: polls_choice_add%}" der "/ admin / polls / choice / add" qual seria o equivalente que me daria "/ admin / polls / choice"?
DarwinSurvivor
2
{% url admin: polls_choice_changelist%} retorna o URL '/ admin / polls / choice'
luc
35
Reverter uma url de administração está totalmente documentado aqui https://docs.djangoproject.com/en/dev/ref/contrib/admin/#reversing-admin-urls
Josh Russo
101
from django.core.urlresolvers import reverse
def url_to_edit_object(obj):
  url = reverse('admin:%s_%s_change' % (obj._meta.app_label,  obj._meta.model_name),  args=[obj.id] )
  return u'<a href="%s">Edit %s</a>' % (url,  obj.__unicode__())

Isso é semelhante à solução do hansen_j, exceto pelo uso de namespaces de URL , admin: sendo o namespace do aplicativo padrão do admin.

Mike Ramirez
fonte
3
Obrigado, isso ajuda. Uma coisa que eu mudaria: use em args=[object.pk]vez de args=[object.id]. Abrange casos mais comuns, quando o campo de chave primária tiver outro nome que não id.
talo
5
Boa resposta. Para sua informação, qualquer pessoa que utilize um django mais recente precisará alterar object._meta.module_name para object._meta.model_name
Jagu
Muito obrigado de um novato django. object._meta.app_labeldeixe-me finalmente obter o nome do próprio aplicativo de autenticação do django. É auth, por exemplo, reverse(admin:auth_user_change, args=[object.id])para ir para a página de alteração de usuário
Gret 29/09
2
Certifique-se de alterar o objeto para obj. Esse cara acabou de escrever um símbolo interno incorporado.
Kevin Parker
17

Existe outra maneira para as versões posteriores, por exemplo, na 1.10 :

{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

Onde optsé algo como mymodelinstance._metaouMyModelClass._meta

Uma dica é que você não pode acessar atributos de sublinhado diretamente nos modelos do Django (como {{ myinstance._meta }}), então você precisa passar o optsobjeto da visualização como contexto do modelo.

Anentrópico
fonte
2
O URL dos documentos mudou! Veja: docs.djangoproject.com/en/1.9/ref/contrib/admin/…
Wim Feijen
12

Essencialmente o mesmo que a resposta de Mike Ramirez, mas mais simples e mais próxima da estilística ao get_absolute_urlmétodo padrão do django :

def get_admin_url(self):
    return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name),
                   args=[self.id])
Antony Hatchkins
fonte
11

Para o 1.1 django anterior, é simples (para a instância padrão do site de administração):

reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,))
Alex Koshelev
fonte
8
Com o novo namespacing é admin:% s_% s_change
Teebes
3

Se você estiver usando o 1.0, tente criar uma etiqueta de modelo personalizada semelhante a esta:

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

use apenas {% adminpageurl my_object%} no seu modelo (não se esqueça de carregar primeiro a etiqueta de modelo)

DarwinSurvivor
fonte
1

Resolvi isso alterando a expressão para:

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

Isso requer / supõe que o URL ur conf tenha um nome para o manipulador de URL "admin", principalmente esse nome é "django-admin",

ou seja, no URL raiz conf:

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

Parece estar funcionando, mas não tenho certeza de sua limpeza.

hasen
fonte
2
Isso funciona para 1.0, mas não para 1.1, que tem uma solução melhor: veja a resposta de Alex Koshelev.
3011 Carl Meyer
Na verdade, eu tentei e não funcionou, e ele disse que é para 1.0, não?
hasen
Sintaxe mudou em 1.1 com a introdução de namespacing url: docs.djangoproject.com/en/dev/topics/http/urls/...
sleepyjames
-1

Aqui está outra opção, usando modelos:

Crie um modelo base (ou apenas adicione o método admin_link a um modelo específico)

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

Herdar desse modelo base

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

Use-o em um modelo

{{ user.admin_link }}

Ou veja

user.admin_link()
Ian Cohen
fonte
2
Não acho que seja uma boa solução. Construir um URL com formatação de string é um mau hábito. Por favor, use reverse ().
guettli