2009-08-30 17 views
25

Qualcuno può spiegare come è possibile scrivere un modello di URL e visualizzare che consente parametri opzionali? L'ho fatto con successo, ma interrompo sempre il tag del modello di URL.Parametri di acquisizione facoltativi in ​​django?

Ecco quello che ho attualmente:

modello

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

View

def so(request, required, optional): 

Se uso il tag modello di URL in questo esempio fornitura di entrambi gli argomenti, funziona va bene; tuttavia, se ometto l'argomento facoltativo, ottengo un errore di inversione.

Come posso realizzare questo?

Grazie, Pete

+1

È sulla roadmap per 1.3: http://code.djopoproject.com/ticket/14772 –

risposta

37

Io in genere fare due modelli con un 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

Sì, questo è il solito modo di farlo. L'inversore di URL ha solo un minor grado di intelligenza sulle espressioni regolari (non implementa un parser di espressioni regolari completo) e non può gestire parti opzionali. Sei libero di utilizzare tutta la potenza delle regex nei tuoi pattern URL, ma poi rinunci all'URL. –

+0

Grazie, questo è quello che stavo cercando. Sono stato sorpreso di apprendere che avevo bisogno di due URL separati. – slypete

+9

Bella risposta. Ma un po 'deprimente ... – Joe

1

Perché non hanno due modelli:

(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

Non importa in quale ordine si inseriscono questi pattern URL. Entrambi sono delimitati da $ alla fine, quindi non può esserci ambiguità.Ci sono, naturalmente, situazioni simili in cui sarebbe importante (se il modello più breve fosse illimitato, ad esempio). –

+0

Hmmmm. Modificherà. – hughdbrown

5

Altri hanno dimostrato il modo per gestire questa situazione con due modelli URL con nome separati. Se la ripetizione di una parte del modello di URL ti dà fastidio, è possibile sbarazzarsi di esso utilizzando include():

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

E poi aggiungere un file required_urls.py con:

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

Normalmente Non ritengo che ne valga la pena a meno che non ci sia un prefisso comune per un numero piuttosto elevato di URL (sicuramente più di due).

+0

Grazie Carl, sembra che possa tornare utile. – slypete

+0

puoi usare 'patterns' per salvare dover creare un nuovo file:' url (r '...', include (patterns ('', url (...), url (...))) ' . [Vedi qui] (https://docs.djangoproject.com/en/dev/topics/http/urls/#including-other-urlconfs) – Patrick

-1

in views.py fai la cosa semplice.

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

E quando non si ottengono opzionale param nella stringa URL sarà None nel codice.

Semplice ed elegante :)

+0

In quale versione di Django funziona? Ho 1.5 questo non funziona senza modifiche in url.py –

+0

Questo funziona per i metodi views.py. Ed è abbastanza deprezzato dal momento che Django ha cambiato molte cose in termini di gestione degli URL e di visualizzazione delle visualizzazioni. [per esempio. Viste basate sulla classe]; – Popara

+0

Non puoi farlo in django, prima guardi su 'url.py' e non troverai nessun pattern che corrisponda all'URL. Poiché è attivo in 'views.py' e non verrà eseguito fino a quando non verrà trovato uno schema –

17

Django gli URL sono polimorfici:

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

sua obious che dovete fare le vostre opinioni in questo modo:

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

così si può chiamare con lo stesso nome e funzionerebbe correttamente con il resolver url.Tuttavia essere consapevoli del fatto che non puoi passare Nessuno come argomento obbligatorio e si aspettano che ti porterà alla regexp senza discutere:

Sbagliato:

{% url sample_view required optional %} 

corretta:

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

Non so se questo è documentato ovunque - l'ho scoperto per caso - Ho dimenticato di riscrivere i nomi dell'URL e funzionava comunque :)

1

Per chi ha ancora questo problema. Io uso Django 1.5 (aggiornato: usando 1.8) e funziona ancora bene.

io uso:

urls.py

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

Poi quando voglio avere i due URL

/1/start/2 

e

/1/start 

Io uso:

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

Questo creerà gli URL

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

Se si crea un URL manualmente devi tenere il/a mente.

Cerchio che questo aiuta chiunque!

-2

A seconda del caso d'uso, si può semplicemente voler passare un parametro URL in questo modo:

url/?parameter=foo 

chiamano questo a suo avviso:

request.REQUEST.get('parameter') 

questo tornerà 'pippo'

+0

La mia domanda riguardava il passaggio del parametro facoltativo alla funzione di visualizzazione e il suo utilizzo con il tag del modello di URL. – slypete

Problemi correlati