Pobieranie adresu administratora Django dla obiektu

168

Przed Django 1.0 istniał łatwy sposób na uzyskanie adresu administratora obiektu, a ja napisałem mały filtr, którego użyłem w ten sposób: <a href="{{ object|admin_url }}" .... > ... </a>

Zasadniczo używałem funkcji odwracania adresu URL z nazwą widoku 'django.contrib.admin.views.main.change_stage'

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

aby uzyskać adres URL.

Jak można się domyślić, próbuję zaktualizować Django do najnowszej wersji i jest to jedna z przeszkód, na które się natknąłem, ta metoda uzyskiwania adresu administratora już nie działa.

Jak mogę to zrobić w django 1.0? (lub 1.1 w tej sprawie, ponieważ próbuję zaktualizować do najnowszej wersji w svn).

hasen
źródło

Odpowiedzi:

61

Miałem podobny problem, gdy próbowałem dzwonić reverse('admin_index')i ciągle otrzymywałem django.core.urlresolvers.NoReverseMatchbłędy.

Okazuje się, że w moim pliku urls.py miałem adresy URL administratora w starym formacie.

Miałem to w moich wzorach url:

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

który uruchamia ekrany administratora, ale jest przestarzałym sposobem robienia tego. Musiałem to zmienić na to:

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

Kiedy to zrobiłem, cała dobroć obiecana w dokumentach Reversing Admin URLs zaczęła działać.

bskinnersf
źródło
Niesamowite, to rozwiązało inny problem, który miałem z nie wywoływaniem metody get_urls () ModelAdmin. Dzięki!
Arnaud
8
najlepszy adres URL dla tego problemu: docs.djangoproject.com/en/dev/ref/contrib/admin/ ...
Dingo
4
Ta „odpowiedź” jest nieprawidłowa, pokazuje tylko, jak poprawnie dodać aplikację administratora do aplikacji, co rozwiązało inny problem, który miał autor. Prawdziwa odpowiedź na rzeczywiste pytanie znajduje się poniżej - od markmuetz
Declan Shanaghy.
Ponadto musisz mieć zarejestrowany interfejs administratora dla modelu, w przeciwnym razie adres URL nie będzie istniał.
Flimm
412

Możesz użyć narzędzia do rozpoznawania adresów URL bezpośrednio w szablonie, nie ma potrzeby pisania własnego filtra. Na przykład

{% url 'admin:index' %}

{% url 'admin:polls_choice_add' %}

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

{% url 'admin:polls_choice_changelist' %}

Ref: Dokumentacja

markmuetz
źródło
1
markmuetz - Czy to jest gdzieś w oficjalnych dokumentach Django? (jak używać odwrotnych adresów URL administratora w szablonach)? Jeśli nie, to powinno.
shacker
7
shacker - Wszystko jest w dokumentach ... tylko nie w jednym miejscu. „URL” szablon jest udokumentowane tutaj . W sekcji „Nowość w Django 1.1:” dokumenty mówią, że adresy URL w przestrzeni nazw są w porządku i kierują do sekcji poświęconej przestrzeniom nazw adresów URL . Sklejenie tego wszystkiego razem umożliwia łatwe odwoływanie się do aplikacji administratora w szablonach. NB Pamiętam, że doktorzy byli inni, kiedy pisałem odpowiedź.
markmuetz
3
Czy wiesz, jak uzyskać link do „listy” wyborów? Przykład: jeśli "{% url admin: polls_choice_add%}" daje "/ admin / polls / choice / add", jaki byłby odpowiednik, który dałby mi "/ admin / polls / choice"?
DarwinSurvivor
2
{% url admin: polls_choice_changelist%} zwraca adres URL „/ admin / polls / choice”
luc
35
Odwracanie adresu
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__())

Jest to podobne do rozwiązania hansen_j, z tym wyjątkiem, że używa przestrzeni nazw url , gdzie admin: jest domyślną przestrzenią nazw aplikacji administratora.

Mike Ramirez
źródło
3
Dzięki, to pomaga. Jedna rzecz, którą chciałbym zmienić: użyj args=[object.pk]zamiast args=[object.id]. Obejmuje bardziej powszechny przypadek, gdy pole klucza podstawowego ma inną nazwę niż id.
łodyga
5
Dobra odpowiedź. Do Twojej wiadomości każdy, kto używa nowszego django, będzie musiał zmienić object._meta.module_name na object._meta.model_name
Jagu
Wielkie podziękowania od początkującego django. object._meta.app_labelPozwól mi ostatecznie uzyskać nazwę własnej aplikacji uwierzytelniającej django. Chodzi authna przykład reverse(admin:auth_user_change, args=[object.id])o przeskok do strony zmiany użytkownika
Gret
2
Pamiętaj, aby zmienić obiekt na obj. Ten facet skończył pisać zarezerwowany wbudowany symbol.
Kevin Parker
17

Jest inny sposób na późniejsze wersje, na przykład w 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>

Gdzie optsjest coś takiego mymodelinstance._metalubMyModelClass._meta

Jednym z problemów jest to, że nie możesz uzyskać dostępu do atrybutów podkreślenia bezpośrednio w szablonach Django (takich jak {{ myinstance._meta }}), więc musisz przekazać optsobiekt z widoku jako kontekst szablonu.

Anentropowy
źródło
2
Adres URL dokumentów został zmieniony! Zobacz: docs.djangoproject.com/en/1.9/ref/contrib/admin/…
Wim Feijen
12

Zasadniczo to samo, co odpowiedź Mike'a Ramireza, ale prostsze i bliższe stylistyce do standardowej get_absolute_urlmetody 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
źródło
11

Dla django w wersji starszej niż 1.1 jest to proste (dla domyślnej instancji witryny administracyjnej):

reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,))
Alex Koshelev
źródło
8
Z nową przestrzenią nazw to admin:% s_% s_change
Teebes,
3

Jeśli używasz wersji 1.0, spróbuj utworzyć niestandardowy szablon szablonu, który wygląda następująco:

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

następnie po prostu użyj {% adminpageurl my_object%} w swoim szablonie (nie zapomnij najpierw załadować tagu szablonu)

DarwinSurvivor
źródło
1

Rozwiązałem to, zmieniając wyrażenie na:

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

To wymaga / zakłada, że ​​główny adres url conf ma nazwę dla programu obsługi url "admin", głównie ta nazwa to "django-admin",

tj. w głównym adresie URL conf:

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

Wygląda na to, że działa, ale nie jestem pewien jego czystości.

hasen
źródło
2
Działa to dla 1.0, ale nie będzie działać dla 1.1, co ma lepsze rozwiązanie: zobacz odpowiedź Alexa Kosheleva.
Carl Meyer
Właściwie to próbowałem i nie zadziałało, a on powiedział, że to dla 1.0, nie?
hasen
Składnia uległa zmianie w wersji 1.1 wraz z wprowadzeniem przestrzeni nazw adresów
sleepyjames
-1

Oto inna opcja, używając modeli:

Utwórz model podstawowy (lub po prostu dodaj metodę admin_link do konkretnego modelu)

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

Dziedzicz z tego modelu podstawowego

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

Użyj go w szablonie

{{ user.admin_link }}

Lub zobacz

user.admin_link()
Ian Cohen
źródło
2
Nie sądzę, żeby to było dobre rozwiązanie. Tworzenie adresu URL z formatowaniem ciągów to zły nawyk. Proszę użyć reverse ().
guettli