2009-09-23 8 views
3

J'ai deux types d'objets différents que j'aimerais vivre sous la même URL. Un groupe d'objets doit être passé à la fonction de vue 'foo' et un autre groupe doit être passé à 'bar'.Ranger le répartiteur d'URL complexe

Je fais actuellement cela avec une grande liste d'URL codées en dur, comme si ...

urlpatterns = patterns('project.views', 
    (r'^a/$', 'foo'), 
    (r'^b/$', 'foo'), 
    (r'^c/$', 'foo'), 
    #...and so on until... 
    (r'^x/$', 'bar'), 
    (r'^y/$', 'bar'), 
    (r'^z/$', 'bar'), 
) 

Est-il possible de définir une liste de chaque type d'URL comme ...

foo_urls = ['a', 'b', 'c'] #... 
bar_urls = ['x', 'y', 'z'] #... 

... puis de vérifier l'URL entrante par rapport à ces listes? (Si c'est dans 'foo_urls', envoyez à 'project.views.foo', si c'est dans 'bar_urls', envoyez à 'project.views.bar')?

Je suis limité à garder cette structure pour maintenir la compatibilité avec les URL du site précédent, mais tous les conseils sur les moyens de simplifier mon urls.py seraient très appréciés.

Répondre

5

Les cartes url sont généralement exprimées explicitement, mais ils ne doivent être pas. Que diriez-vous de construire votre carte URL à partir de vos listes?

foo_urls = ['a', 'b', 'c'] #... 
bar_urls = ['x', 'y', 'z'] #... 

# A first pattern to get urlpatterns started. 
urlpatterns = pattern('project.views', 
    ('blah', 'blah') 
    ) 

# Append all the foo urls. 
for foo_url in foo_urls: 
    urlpatterns += patterns('project.views', 
     ('^' + foo_url + '/$', 'foo') 
     ) 

# Append all the bar urls. 
for bar_url in bar_urls: 
    urlpatterns += patterns('project.views', 
     ('^' + bar_url + '/$', 'bar') 
     ) 
4

modèles url de Django sont des expressions régulières, donc c'est en effet possible:

urlpatterns = patterns('project.views', 
    (r'^[abc]/$', 'foo'), 
    (r'^[xyz]/$', 'bar'), 
) 

Si vous utilisez a, b, c comme exemple des espaces réservés pour un caractère non unique, vous pouvez utiliser pleinement chaînes à la place, mais faites attention à vous assurer qu'ils suivent les règles de correspondance regex:

urlpatterns = patterns('project.views', 
    (r'^(foo|slithy|toves)/$', 'foo'), 
    (r'^(bar|twas|brillig)/$', 'bar'), 
) 
3

Vous pouvez remplacer les urlpatterns avec celui qui attire toutes les urls, déplacez alors la logique de choisir entre foo et bar urls à la vue.

urlpatterns = patterns('project.views', 
    (r'^(?P<letter>[a-z])/$', 'foobar'), 
) 

Puis écrire une fonction foobar dans views.py

def foobar(request, letter): 

    foo_urls = ['a', 'b', 'c'] #... 
    bar_urls = ['x', 'y', 'z'] #... 
    if slug in foo_urls: 
     return foo(request) 
    if slug in bar_urls: 
     return bar(request) 
    else: 
     #oh dear, you've caught a 
     #url that isn't foo or bar 
     #return 404? 

Comme alternative, vous pouvez explorer le django redirects app, redessiner la structure url, puis mis en place pour les anciens réoriente urls.

1

Si vous avez Apache en face de votre application:

<LocationMatch "^[a-w]/$"> 
    ... 
</LocationMatch> 

<LocationMatch "^[x-z]/$"> 
    ... 
</LocationMatch> 

Le ... peut être des directives de configuration dont vous avez besoin, y compris SetEnv si vous souhaitez une variable d'environnement pour vous dire si vous voulez aller à foo vs barre, ou peut-être ProxyPass pour envoyer la demande à un couple de différentes URL du serveur backend.

Vous pouvez également utiliser la réécriture d'URL ou un certain nombre d'autres paramètres de configuration Apache acceptant les arguments regex.