2008-10-30 20 views
16

Tengo un modelo Django con una gran cantidad de campos y más de 200 filas de tablas. Para facilitar la URL legibles por humanos y la capacidad de romper la gran lista en sublistas arbitrarias, me gustaría tener una URL que tiene este aspecto:Django: número arbitrario de parámetros urls.py sin nombre

/browse/<name1>/<value1>/<name2>/<value2>/ .... etc .... 

donde los mapas 'nombre' a un atributo del modelo y de 'valor' es el criterio de búsqueda para ese atributo. Cada "nombre" se tratará como una categoría para devolver subconjuntos de las instancias del modelo donde coinciden las categorías.

Ahora, esto podría manejarse con parámetros GET, pero prefiero URL más legibles tanto para el usuario como para los motores de búsqueda. Estos subconjuntos de URL se integrarán en cada página que muestre este modelo, por lo que parece que vale la pena el esfuerzo para crear URL bonitas.

Lo ideal sería que cada par nombre/valor se pasa a la función vista como un parámetro llamado name1, name2, etc. Sin embargo, no creo que sea posible a los patrones definidos nombrados a través de texto coincidente de una expresión regular. ¿Me equivoco allí?

Por lo tanto, parece que tengo que hacer algo como esto:

urlpatterns = patterns('', 
    url(r'^browse/(?:([\w]+)/([\w]+)/)+$', 'app.views.view', name="model_browse"), 
) 

Parece que este debe coincidir con cualquier conjunto de dos pares de nombre/valor. Mientras coincide con éxito, solo pasa el último par de nombre/valor como parámetros a la función de vista. Creo que cada partido está sobrescribiendo el partido anterior. Bajo la suposición de que la contiene (?: ...) + está causando, probé un patrón de repetición simple en su lugar:

urlpatterns = patterns('', 
    url(r'^browse/([\w]+/)+$', 'app.views.view', name="model_browse"), 
) 

... y tengo el mismo problema, pero esta vez *args sólo incluye la última patrón combinado

¿Es esto una limitación del distribuidor de urls de Django, y/o el soporte de expresiones regulares de Python? Parece que cualquiera de estos métodos debería funcionar. ¿Hay alguna forma de lograr esto sin codificar cada atributo de modelo posible en la URL como un patrón opcional (. *)?

+0

creo que implementan "GET consulta como" params de valores clave usando url en sí es un poco feo y no "verdadera". –

+0

@alex: además de que la URL no es legible, es probable que los motores de búsqueda no indexen todo tu contenido si tienes más de un par de parámetros (si es así). –

Respuesta

11

Una posibilidad que podría considerar es hacer coincidir toda la cadena de posibles valores dentro de la porción del patrón de url y extraer las piezas específicas dentro de su vista. A modo de ejemplo:

urlpatterns = patterns('', 
    url(r'^browse/(?P<match>.+)/$', 'app.views.view', name='model_browse'), 
) 

def view(request, match): 
    pieces = match.split('/') 
    # even indexed pieces are the names, odd are values 
    ... 

No hay promesas sobre la expresión regular que usé, pero creo que se entiende lo que quiero decir.

(Editado para tratar de solucionar la expresión regular.)

+0

Gracias, estoy de acuerdo que esta es probablemente la forma más fácil de manejar el problema. –

+1

Solo para poner algo de texto aquí para otros en mi situación, esta es la única solución que he encontrado para analizar un número arbitrario de elementos de matriz en un [URI de matriz] (http://www.w3.org/DesignIssues/MatrixURIs .html). Haga coincidir todos los elementos de la matriz y luego analice en la vista. – KobeJohn

+1

mismo aquí, y es 2016 – benzkji

3

Estoy de acuerdo con Adam, pero creo que el patrón en urls.py debe ser:

... r'^browse/(?P<match>.+)/$' ... 

El '\ w' voluntad único partido personajes de 'palabra', pero el '.' coincidirá con cualquier cosa.

+0

Soy terrible en expresiones regulares y solo adiviné, je. – Adam

0

Me llegó la misma respuesta al leer la pregunta.

Creo que la vista model_browse es la mejor manera de ordenar los parámetros de consulta y utilizarlo como un enrutador genérico.

0

Creo que la respuesta de Adán es más genérico que mi solución, pero si te gusta usar un número fijo de argumentos en la url, también se puede hacer algo como esto:

El siguiente ejemplo muestra cómo obtenga todas las ventas de un día para una ubicación ingresando el nombre store y year, month y day.

urls.py:

urlpatterns = patterns('', 
    url(r'^baseurl/location/(?P<store>.+)/sales/(?P<year>[0-9][0-9][0-9][0-9])-(?P<month>[0-9][0-9])-(?P<day>[0-9][0-9])/$', views.DailySalesAtLocationListAPIView.as_view(), name='daily-sales-at-location'), 
) 

Alternativly, también se podría utilizar el ID de la tienda cambiando (?P<store>.+)-(?P<store>[0-9]+). Tenga en cuenta que location y sales no son palabras clave, solo mejoran la legibilidad de la url.

views.py

class DailySalesAtLocationListAPIView(generics.ListAPIView): 
    def get(self, request, store, year, month, day): 
     # here you can start using the values from the url 
     print store 
     print year 
     print month 
     print date 

     # now start filtering your model 

creo que sirve a nadie!

Saludos,

Michael

0

He una solución alternativa, que no es muy diferente de la anterior, pero es más refinado:

url(r'^my_app/(((list\/)((\w{1,})\/(\w{1,})\/(\w{1,3})\/){1,10})+)$'

que he usado unnamed url parameters y una expresión regular repetitiva. Para no obtener "no es una expresión regular válida: repetición múltiple" coloco una palabra al comienzo de la lista.

Todavía estoy trabajando en la vista que recibe la lista. Pero creo que voy a pasar por los args o kwargs ... Todavía no puedo decirlo exactamente.

Mis 2 centavos

Cuestiones relacionadas