2009-08-30 21 views
25

Czy ktoś może wyjaśnić, w jaki sposób można zapisać wzór adresu URL i widok, który pozwala na opcjonalne parametry? Zrobiłem to z powodzeniem, ale zawsze łamam tag szablonu URL.Opcjonalne pobranie parametrów w django?

Oto co mam obecnie:

Wzór

(r'^so/(?P<required>\d+)/?(?P<optional>(.*))/?$', 'myapp.so') 

Zobacz

def so(request, required, optional): 

Jeśli używam szablon URL w tym przykładzie zapewniając zarówno argumenty, to działa w porządku; jednak jeśli pominąć opcjonalny argument, pojawia się błąd odwrócenia.

Jak mogę to zrobić?

Dzięki, Pete

+1

Znajduje się na mapie drogowej dla wersji 1.3: http://code.djangoproject.com/ticket/14772 –

Odpowiedz

37

ja generalnie dwa wzory z named url:

url(r'^so/(?P<required>\d+)/$', 'myapp.so', name='something'), 
url(r'^so/(?P<required>\d+)/(?P<optional>.*)/$', 'myapp.so', name='something_else'), 
+2

Tak, jest to zwyczajny sposób na zrobienie tego. Reverser URL ma tylko ograniczone spostrzeżenia dotyczące wyrażeń regularnych (nie implementuje pełnego analizatora składni regex) i nie obsługuje części opcjonalnych. Możesz używać pełnej mocy wyrażeń regularnych we wzorcach adresów URL, ale rezygnujesz z cofania adresów URL. –

+0

Dzięki, tego właśnie szukałem. Zaskoczyło mnie, że potrzebuję dwóch oddzielnych adresów URL. – slypete

+9

Dobra odpowiedź. Ale trochę przygnębiające ... – Joe

1

Dlaczego nie posiadają dwa wzory:

(r'^so/(?P<required>\d+)/(?P<optional>.*)/$', view='myapp.so', name='optional'), 
(r'^so/(?P<required>\d+)/$', view='myapp.so', kwargs={'optional':None}, name='required'), 
+0

Nie ma znaczenia, w jakiej kolejności umieścisz te wzorce adresów URL. Oba są ograniczone na końcu, więc nie może być żadnych niejednoznaczności.Są oczywiście podobne sytuacje, w których miałoby to znaczenie (gdyby na przykład krótszy wzór był nieograniczony). –

+0

Hmmmm. Dokona edycji. – hughdbrown

5

Inni wykazali sposób obsłużyć to z dwa oddzielne nazwane wzorce adresów URL. Jeśli powtórzenie części wzorca URL przeszkadza, to jest możliwe, aby pozbyć się go za pomocą include():

url(r'^so/(?P<required>\d+)/', include('myapp.required_urls')) 

a następnie dodaj plik required_urls.py z:

url(r'^$', 'myapp.so', name='something') 
url(r'^(?P<optional>.+)/$', 'myapp.so', name='something_else') 

Normalnie Nie uznałbym tego za warte, chyba że istnieje wspólny przedrostek dla wielu adresów URL (z pewnością więcej niż dwóch).

+0

Dzięki Carl, wygląda na to, że przyda się też. – slypete

+0

możesz użyć 'patterns', aby zapisać tworzenie nowego pliku:' url (r '...', include (patterns ('', url (...), url (...)))) . [Zobacz tutaj] (https://docs.djangoproject.com/en/dev/topics/http/urls/#including-other-urlconfs) – Patrick

-1

w views.py robisz proste rzeczy.

def so(request, required, optional=None): 

A kiedy nie dostać opcjonalnego w param url ciąg będzie None w kodzie.

prosty i elegancki :)

+0

W której wersji Django działa? I've 1.5 to nie działa bez zmian w url.py –

+0

Działa to dla metod views.py. I jest dość amortyzowany, ponieważ Django zmienił wiele rzeczy pod względem zarządzania URL i stosowania widoków. [na przykład. Widok oparty na klasach]; – Popara

+0

Nie możesz tego zrobić w django, najpierw przyjrzyj się "url.py" i nie znajdziesz żadnego wzoru pasującego do adresu URL. Ponieważ to jest w 'views.py' i nie będzie działać dopóki nie zostanie znaleziony wzór –

17

Django adresy URL są polimorficzne:

url(r'^so/(?P<required>\d+)/$', 'myapp.so', name='sample_view'), 
url(r'^so/(?P<required>\d+)/(?P<optional>.*)/$', 'myapp.so', name='sample_view'), 

jego obious że trzeba zrobić swoje poglądy tak:

def sample_view(request, required, optional = None): 

tak można nazwać to z ta sama nazwa i działałaby dobrze na rozwiązaniu url URL.Jednak należy pamiętać, że nie można przejść None jako wymaganego argumentu i oczekiwać, że będzie cię do regexp bez argumentu:

Źle:

{% url sample_view required optional %} 

Poprawnie:

{% if optional %} 
    {% url sample_view required optional %} 
{% else %} 
    {% url sample_view required %} 
{% endif %} 

Nie wiem, czy jest to udokumentowane w dowolnym miejscu - odkryłem to przez przypadek - zapomniałem przepisać nazwy URL i tak działało :)

1

Dla każdego, kto nadal ma ten problem. Używam Django 1.5 (zaktualizowano: używając 1.8) i nadal działa dobrze.

używam:

urls.py

url(r'^(?P<app_id>\d+)/start/+(?P<server_id>\d+)?', views.restart, name='restart') 

Potem, gdy chcę mieć dwa adresy URL

/1/start/2 

i

/1/start 

Używam:

{% url '<namespace>:start' app.id %} 
{% url '<namespace>:start' app.id server.id %} 

To stworzy adresy URL

/1/start/2 and 
/1/start/ <- notice the slash. 

Jeśli ręcznie utworzyć url trzeba zachować/w umyśle.

Obręcz to pomaga każdemu!

-2

zależności od przypadku użycia, może po prostu chcesz przekazać parametr url tak:

url/?parameter=foo 

nazywają to w widoku:

request.REQUEST.get('parameter') 

ten powróci 'foo'

+0

Moje pytanie dotyczyło przekazania opcjonalnego parametru do funkcji widoku, jak również użycia go z tagiem szablonu URL. – slypete