Mendapatkan Django admin url untuk suatu objek

168

Sebelum Django 1.0 ada cara mudah untuk mendapatkan url admin suatu objek, dan saya telah menulis filter kecil yang saya gunakan seperti ini: <a href="{{ object|admin_url }}" .... > ... </a>

Pada dasarnya saya menggunakan fungsi url reverse dengan nama tampilan sedang 'django.contrib.admin.views.main.change_stage'

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

untuk mendapatkan url.

Seperti yang mungkin sudah Anda duga, saya mencoba memperbarui ke versi terbaru Django, dan ini adalah salah satu kendala yang saya temui, metode untuk mendapatkan url admin tidak berfungsi lagi.

Bagaimana saya bisa melakukan ini di Django 1.0? (atau 1.1 dalam hal ini, karena saya mencoba memperbarui ke versi terbaru di svn).

Hasen
sumber

Jawaban:

61

Saya memiliki masalah serupa di mana saya akan mencoba menelepon reverse('admin_index')dan terus mendapatkan django.core.urlresolvers.NoReverseMatchkesalahan.

Ternyata saya memiliki url admin format lama di file urls.py saya.

Saya memiliki ini di urlpatterns saya:

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

yang membuat layar admin berfungsi tetapi merupakan cara usang untuk melakukannya. Saya perlu mengubahnya ke ini:

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

Setelah saya melakukan itu, semua kebaikan yang dijanjikan dalam Reversing Admin URLs docs mulai berfungsi.

bskinnersf
sumber
Luar biasa, ini memperbaiki masalah lain yang saya alami dengan metode get_urls () dari ModelAdmin tidak dipanggil. Terima kasih!
Arnaud
8
url terbaik untuk masalah ini: docs.djangoproject.com/en/dev/ref/contrib/admin/…
Dingo
4
"Jawaban" ini tidak benar, hanya menunjukkan cara menambahkan aplikasi admin dengan benar ke aplikasi Anda, yang memecahkan masalah berbeda yang dimiliki penulis. Jawaban sebenarnya untuk pertanyaan yang sebenarnya ada di bawah ini - dari markmuetz
Declan Shanaghy
Anda juga harus memiliki antarmuka admin terdaftar untuk model, jika tidak URL tidak akan ada.
Flimm
412

Anda dapat menggunakan penyelesai URL secara langsung dalam templat, tidak perlu menulis filter Anda sendiri. Misalnya

{% url 'admin:index' %}

{% url 'admin:polls_choice_add' %}

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

{% url 'admin:polls_choice_changelist' %}

Ref: Dokumentasi

markmuetz
sumber
1
markmuetz - Apakah ini dalam dokumen resmi Django di mana saja? (cara menggunakan admin membalikkan URL di templat)? Jika tidak, seharusnya begitu.
shacker
7
shacker - Semuanya ada di dokumen ... tidak di satu tempat. The "url" tag template didokumentasikan di sini . Di bagian "Baru di Django 1.1:" dokumen mengatakan bahwa URL ruang nama baik-baik saja, dan mengarahkan Anda ke bagian ruang URL . Menyatukan semuanya memungkinkan Anda mereferensikan aplikasi admin dengan mudah di templat. NB Saya ingat dokumen berbeda ketika saya menulis balasan.
markmuetz 3-10
3
Apakah Anda tahu cara mendapatkan tautan ke "daftar" pilihan? Contoh: jika "{% url admin: polls_choice_add%}" memberikan "/ admin / polls / choice / add" apa yang akan setara dengan yang akan memberi saya "/ admin / polls / choice"?
DarwinSurvivor
2
{% url admin: polls_choice_changelist%} mengembalikan url '/ admin / polls / choice'
luc
35
Membalik url admin saat ini sepenuhnya didokumentasikan di sini 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__())

Ini mirip dengan solusi hansen_j kecuali bahwa ia menggunakan ruang nama url , admin: menjadi namespace aplikasi default admin.

Mike Ramirez
sumber
3
Terima kasih, ini membantu. Satu hal yang saya akan ubah: gunakan args=[object.pk]sebagai ganti args=[object.id]. Ini mencakup kasus yang lebih umum, ketika bidang kunci utama memiliki nama lain dari id.
tangkai
5
Jawaban yang bagus. FYI siapa pun yang menggunakan Django yang lebih baru perlu mengubah object._meta.module_name menjadi object._meta.model_name
Jagu
Terima kasih banyak dari seorang pemula Django. object._meta.app_labelbiarkan saya akhirnya mendapatkan nama untuk aplikasi otentikasi django sendiri. Ini auth, misalnya reverse(admin:auth_user_change, args=[object.id])untuk melompat ke halaman perubahan pengguna
Gret
2
Pastikan untuk mengubah objek menjadi keberatan. Orang ini sudah selesai menulis simbol bawaan yang dicadangkan.
Kevin Parker
17

Ada cara lain untuk versi yang lebih baru, misalnya di 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>

Di mana optssesuatu seperti mymodelinstance._metaatauMyModelClass._meta

Salah satu Gotcha adalah Anda tidak dapat mengakses atribut garis bawah langsung di templat Django (seperti {{ myinstance._meta }}) sehingga Anda harus meneruskan optsobjek dari tampilan sebagai konteks templat.

Anentropik
sumber
2
Url dokumen telah berubah! Lihat: docs.djangoproject.com/en/1.9/ref/contrib/admin/…
Wim Feijen
12

Pada dasarnya sama dengan jawaban Mike Ramirez, tetapi lebih sederhana dan lebih dekat dalam gaya bahasa untuk get_absolute_urlmetode standar 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
sumber
11

Untuk pre 1.1 django itu sederhana (untuk instance situs admin default):

reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,))
Alex Koshelev
sumber
8
Dengan namespace baru admin itu:% s_% s_change
Teebes
3

Jika Anda menggunakan 1.0, cobalah membuat templatetag khusus yang terlihat seperti ini:

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

maka cukup gunakan {% adminpageurl my_object%} di templat Anda (jangan lupa memuat templatetag terlebih dahulu)

Penyelamat Darwin
sumber
1

Saya memecahkan masalah ini dengan mengubah ekspresi menjadi:

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

Ini mensyaratkan / mengasumsikan bahwa root url conf memiliki nama untuk url handler "admin", terutama nama itu adalah "django-admin",

yaitu di root url conf:

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

Tampaknya berfungsi, tapi saya tidak yakin dengan kebersihannya.

Hasen
sumber
2
Ini berfungsi untuk 1.0, tetapi tidak akan berfungsi untuk 1.1, yang memiliki solusi yang lebih baik: lihat jawaban Alex Koshelev.
Carl Meyer
Sebenarnya saya mencobanya dan tidak berhasil, dan dia bilang itu untuk 1.0, bukan?
hasen
Sintaks telah berubah di 1.1 dengan pengenalan url namespacing: docs.djangoproject.com/en/dev/topics/http/urls/…
sleepyjames
-1

Berikut opsi lain, menggunakan model:

Buat model dasar (atau cukup tambahkan metode admin_link ke model tertentu)

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

Mewarisi dari model dasar itu

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

Gunakan itu dalam templat

{{ user.admin_link }}

Atau lihat

user.admin_link()
Ian Cohen
sumber
2
Saya rasa ini bukan solusi yang baik. Membangun URL dengan pemformatan string adalah kebiasaan buruk. Silakan gunakan terbalik ().
guettli