python - tutorial - django views
Django: nĂºmero arbitrario de parĂ¡metros urls.py sin nombre (5)
Tengo un modelo de Django con una gran cantidad de campos y más de 200 filas de tablas. Para facilitar las URL legibles por personas y la capacidad de dividir la lista grande en sublistas arbitrarias, me gustaría tener una URL que se parezca a esta:
/browse/<name1>/<value1>/<name2>/<value2>/ .... etc ....
donde ''nombre'' se asigna a un atributo de modelo y ''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.
Idealmente, cada par de nombre / valor se pasará a la función de vista como un parámetro llamado name1
, name2
, etc. Sin embargo, no creo que sea posible definir patrones con nombre a través del texto coincidente de una expresión regular. ¿Me equivoco allí?
Entonces, parece que necesito hacer algo como esto:
urlpatterns = patterns('''',
url(r''^browse/(?:([/w]+)/([/w]+)/)+$'', ''app.views.view'', name="model_browse"),
)
Parece que esto debería 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 el contenido (?: ...) + lo está causando, intenté un patrón de repetición simple en su lugar:
urlpatterns = patterns('''',
url(r''^browse/([/w]+/)+$'', ''app.views.view'', name="model_browse"),
)
... y tiene el mismo problema, pero esta vez *args
solo incluye el último patrón coincidente.
¿Es esto una limitación del distribuidor de urls de Django y / o del 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 (. *)?
Estoy de acuerdo con Adam, pero creo que el patrón en urls.py debería ser:
... r''^browse/(?P<match>.+)/$'' ...
El ''/ w'' solo coincidirá con los caracteres de ''palabra'', pero el ''.'' coincidirá con cualquier cosa.
Una posibilidad que podría considerar es hacer coincidir toda la cadena de valores posibles dentro de la porción de patrón de url y extraer las piezas específicas dentro de su vista. Como 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 utilicé, pero creo que entiendes lo que quiero decir.
(Editado para intentar y corregir la expresión regular).
La misma respuesta vino a mí mientras leía la pregunta.
Creo que la vista model_browse es la mejor manera de ordenar los parámetros de consulta y usarlo como un enrutador genérico.
Creo que la respuesta de Adam es más genérica que mi solución, pero si te gusta usar una cantidad fija de argumentos en la url, también puedes hacer algo como esto:
El siguiente ejemplo muestra cómo obtener todas las ventas de un día para una ubicación ingresando el nombre de la store
y el 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''),
)
Alternativamente, también puede usar la identificación de la tienda cambiando (?P<store>.+)
(?P<store>[0-9]+)
. Tenga en cuenta que la location
y las 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
Espero que ayude a cualquiera!
Atentamente,
Miguel
Tengo una solución alternativa, que no es muy diferente a la anterior, pero es más refinada:
url(r''^my_app/(((list//)((/w{1,})//(/w{1,})//(/w{1,3})//){1,10})+)$''
He usado parámetros de URL sin nombre 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