Django'da ters () nedir


219

Bazen django kodunu okuduğumda, bazı şablonlarda görüyorum reverse(). Bunun ne olduğundan tam olarak emin değilim ama HttpResponseRedirect ile birlikte kullanılıyor. Bunun nasıl ve ne zaman reverse()kullanılması gerekiyor?

Birisi bazı örneklerle cevap verseydi iyi olur ...


26
Bir URL modeli verildiğinde, Django doğru görünümü seçmek ve bir sayfa oluşturmak için url () yöntemini kullanır. Yani url--> view name,. Ancak bazen, yeniden yönlendirirken olduğu gibi, ters yöne gitmeniz ve Django'ya bir görünümün adını vermeniz gerekir ve Django uygun URL'yi oluşturur. Başka bir deyişle view name --> url,. Yani, reverse()(url işlevinin tersidir). Sadece aramak daha şeffaf görünebilir, generateUrlFromViewNameancak bu çok uzun ve muhtemelen yeterince genel değil: docs.djangoproject.com/en/dev/topics/http/urls/…
eric

4
@neuronet Harika bir açıklama, teşekkürler. Bu isim benim için çok sezgisel görünüyordu (ve öyle görünüyor), ki bu büyük bir günahtı. Kim gereksiz şaşkınlıktan nefret etmez?
mike kemirgen

Bu, bağlamı göz önüne alındığında, programcının zihninde en başta gelen, ancak diğer herhangi bir geliştiricinin geniş bağlamında en yararlı seçenek olmayan bir varlığın (örneğin işlev) bir yönünü vurgulayan tipik bir adlandırma örneğidir. . Bu tuzağa programcılar olarak sık sık düşüyoruz - isimlendirme keşfedilebilirlik için çok önemlidir, farklı bağlamları durdurmaya ve düşünmeye ve en uygun olanı seçmeye değer.
Cornel Masson

Yanıtlar:


347

reverse()| Django belgeleri


Diyelim ki urls.pysizde bunu tanımladınız:

url(r'^foo$', some_view, name='url_name'),

Bir şablonda bu URL'ye şu şekilde başvurabilirsiniz:

<!-- django <= 1.4 -->
<a href="{% url url_name %}">link which calls some_view</a>

<!-- django >= 1.5 or with {% load url from future %} in your template -->
<a href="{% url 'url_name' %}">link which calls some_view</a>

Bu şu şekilde yapılacaktır:

<a href="/foo/">link which calls some_view</a>

Şimdi, benzer bir şey yapmak istediğinizi varsayalım views.py- örneğin, /foo/başka bir görünümde (değil some_view) başka bir URL kullanıyorsunuz (değil ) ve kullanıcıyı /foo/(genellikle başarılı form gönderimi durumunda) yönlendirmek istiyorsunuz .

Sadece şunları yapabilirsiniz:

return HttpResponseRedirect('/foo/')

Ancak, gelecekte URL'yi değiştirmek isterseniz ne olur? Eğer güncellemek zorunda kalacak urls.py ve kodunuzda tüm başvuruları. Bu , sadece bir yeri düzenleme fikri olan DRY'yi (Kendinizi Tekrarlama) ihlal eder , bu da çabalamak için bir şeydir.

Bunun yerine şunları söyleyebilirsiniz:

from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))

Bu, adınızla tanımlanan URL için projenizde tanımlanan tüm URL'leri inceler url_nameve gerçek URL'yi döndürür /foo/.

Bu, URL'ye yalnızca nameözelliğiyle atıfta bulunduğunuz anlamına gelir - URL'nin kendisini veya başvurduğu görünümü değiştirmek istiyorsanız, bunu yalnızca tek bir yeri düzenleyerek yapabilirsiniz - urls.py.


3
Bilginize, {{ url 'url_name' }}olmalıdır {% url url_name %}Django 1.4 veya daha önce. Bu, bir sonraki Django sürümünde (1.5) değişecek ve daha sonra olması gerekiyor {% url 'url_name' %}. İçin dokümanlar url templatetag vermek biraz iyi bilgi size "ileriye uyumluluk" bölümüne biraz aşağı kaydırma eğer
j_syk

1
j_syk teşekkürler - 1.3 çıktı beri gelecekteki @ @ url yük @ yapıyorum ve henüz varsayılan olmadığını unuttum. Yanıtımı güncelleyeceğim, böylece deneyimsiz olanı açmayacak.
scytale

2
sabit - Sanırım diğer insanların cevaplarında aptal yazım hatalarını kendiniz düzenlemenin tamamen kabul edilebilir olduğunu düşünüyorum, bu yüzden daha fazlasını görürseniz :-)
scytale

3
Bu sitede bulabileceğiniz en ince cevaplardan biri.
Manas Chaturvedi

1
">>> ama gelecekte URL'yi değiştirmek isterseniz", Zamanın% .0001'inde yararlı olan bu tür incelikler ve çözüm yararlı bir özellik gibi gönderilir ve insanlar onu sanki ' iyi uygulamalar 've karışıklık bırakın. TBH, gelecekte URL'leri değiştirdiğinde, yalnızca global bir bul-değiştir işlemi yaparsanız. Bu çözüm bile (url_name kullanın) 'gelecekte url_name'i değiştirmek isterseniz ne olur?' Sorununa eğilimlidir. Django'da 5 yılı aşkın bir süredir kodlama yapıyor ve ihtiyacını henüz karşılamıyor url_reverse. Bu tür tuhaflıklarla başa çıkmanın en iyi yolu, bunları kullanmayı reddetmektir.
nehem

10

Bu eski bir soru, ama burada birine yardım edebilecek bir şey var.

Resmi dokümanlardan:

Django, URL'lerin gerekli olduğu farklı katmanlarla eşleşen URL tersine çevirme gerçekleştirmek için araçlar sağlar: Şablonlarda: URL şablonu etiketini kullanma. Python kodunda: reverse () işlevini kullanma. Django model örneklerinin URL'lerinin işlenmesiyle ilgili daha üst düzey kodda: get_absolute_url () yöntemi.

Örneğin. şablonlarda (url etiketi)

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>

Örneğin. Python kodunda ( reverseişlevi kullanarak )

return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

1
tam açıklama gerekir patron
giveJob

OP özellikle dokümanları okuduğunu belirtti, sadece dokümanlardan kopyalayıp yapıştırmak için değil, açıklamaya ihtiyacı vardı.
RusI

8

Mevcut cevaplar, Django'daki bu fonksiyonun ne olduğunu açıklamakta çok başarılı oldu reverse().

Ancak, ben cevabım farklı bir ışık tutacak o umduğumuz neden : Kullanım neden reverse()şablon görünümdeki diğer daha dolaysız, belki daha pythonic yaklaşımların yerine bağlayıcı, ve bu "yeniden yönlendirme popülaritesi için bazı meşru nedenleri nelerdir aracılığı reverse() yönlendirme mantığında.

Bir diğer önemli fayda, diğerlerinin de belirttiği gibi, bir url'nin tersine yapılandırılmasıdır. Tıpkı {% url "profile" profile.id %}uygulamanızın url yapılandırma dosyasından url'yi nasıl oluşturacağınız gibi : ör path('<int:profile.id>/profile', views.profile, name="profile").

Ancak OP'nin belirttiği gibi, kullanımı reverse()da yaygın olarak kullanımı ile birleştirilir HttpResponseRedirect. Ama neden?

Bunun ne olduğundan tam emin değilim ama HttpResponseRedirect ile birlikte kullanılıyor. Bu reverse () nasıl ve ne zaman kullanılacak?

Aşağıdakileri düşünün views.py:

from django.http import HttpResponseRedirect
from django.urls import reverse

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected = question.choice_set.get(pk=request.POST['choice'])
    except KeyError:
        # handle exception
        pass
    else:
        selected.votes += 1
        selected.save()
        return HttpResponseRedirect(reverse('polls:polls-results',
                                    args=(question.id)
        ))

Ve minimalimiz urls.py:

from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('<int:question_id>/results/', views.results, name='polls-results'),
    path('<int:question_id>/vote/', views.vote, name='polls-vote')
]

İşlevde, vote()bloğumuzdaki kod aşağıdaki desenle birlikte elsekullanır :reverseHttpResponseRedirect

HttpResponseRedirect(reverse('polls:polls-results',
                                        args=(question.id)

Bu ilk ve en önemlisi, URL'yi sabit kodlamak zorunda olmadığımız anlamına gelir (DRY ilkesine uygun), daha da önemlisi, reverse()bağımsız değişkenlerden açılmış değerleri args=(question.id)işleyerek ( URLConfig tarafından işlenir) URL dizeleri oluşturmak için zarif bir yol sağlar . Sözde değeri içeren questionbir özniteliği varsayalım, bundan oluşturulan URL :id5reverse()

'/polls/5/results/'

Normal şablon görünümü bağlama kodunda, HttpResponse()veya render()genellikle daha az soyutlamayı içerdiklerinden kullanırız : bir şablon döndüren bir görünüm işlevi:

def index(request):
    return render(request, 'polls/index.html') 

Ancak birçok yasal yeniden yönlendirme durumunda, tipik olarak URL'yi bir parametre listesinden oluşturmayı önemsiyoruz. Bunlar aşağıdakileri içerir:

  • POSTİstek yoluyla HTML formu gönderme
  • Kullanıcı girişi doğrulama sonrası
  • JSON web belirteçleriyle parolayı sıfırlayın

Bunların çoğu bir tür yönlendirme ve bir dizi parametre aracılığıyla oluşturulan bir URL içerir. Umarım bu zaten yararlı cevaplar iş parçacığı ekler!


4

İşlev kuru ilkesini destekler - uygulamanız boyunca URL'leri sabit kodlamamanızı sağlar. Bir url tek bir yerde ve yalnızca bir yerde tanımlanmalıdır - url conf. Bundan sonra gerçekten bu bilgilere atıfta bulunuyorsunuz.

reverse()Görünüme giden yol ya da url conf'inizdeki page_name parametresi verildiğinde bir sayfanın URL'sini vermek için kullanın . Bunu şablonda yapmanın mantıklı olmadığı durumlarda kullanırsınız {% url 'my-page' %}.

Bu işlevi kullanabileceğiniz birçok olası yer vardır. Kullandığım bir yer, kullanıcıları bir görünümde yeniden yönlendirirken (genellikle bir formun başarıyla işlenmesinden sonra) -

return HttpResponseRedirect(reverse('thanks-we-got-your-form-page'))

Bunu şablon etiketleri yazarken de kullanabilirsiniz.

Başka kullandığım zaman reverse()model mirasıydı. Bir üst modelde bir ListView vardı, ancak ilişkili alt nesnenin DetailView bu üst nesnelerin herhangi birini almak istedim. Bir bağlı get__child_url()bir çocuğun varlığını tespit ve kullanma 's DetailView url döndü ebeveyne işlevi reverse().



2

Mevcut cevaplar oldukça açık. Neden çağrıldığını bilmiyorsanız reverse: Bir url adının bir girişini alır ve önce bir url'ye sahip olmak ve sonra bir ad vermek için gerçek bir url verir.


1
Sadece bir öğreticiden Django öğrenme (Django Kızlar). Dik bir öğrenme eğrisi. Bu işlevin adı korkunç olduğunu düşünüyorum: herhangi bir nitelik olmadan "rezerv" ÇOK GÜÇLÜ bir liste veya dize, açıkça bir şey yapmak zorunda hiçbir şey rezerve öneriyor.
mike rodent

@mikerodent Sana tamamen katılıyorum. Ayrıca, bu cevapların hiçbiri işlevin neden tersine çağrıldığını açıklamaz . Bu çok kötü bir isim imo.
Soham Dongargaonkar

1

Reverse (), django DRY ilkesine uymak için kullanılır, yani gelecekte url'yi değiştirirseniz, tersine (urlname) kullanarak bu url'ye başvurabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.