Captura de parámetros de URL en request.GET

458

Actualmente estoy definiendo expresiones regulares para capturar parámetros en una url, como se describe en el tutorial. ¿Cómo accedo a los parámetros desde la url como parte del HttpRequestobjeto? Mi HttpRequest.GETactualmente devuelve un QueryDictobjeto vacío .

Me gustaría aprender cómo hacer esto sin una biblioteca para poder conocer mejor a Django.

sutee
fuente

Respuestas:

662

Cuando url es como:,domain/search/?q=haha entonces usaríasrequest.GET.get('q', '') .

qes el parámetro que desea, y ''es el valor predeterminado si qno se encuentra.

Sin embargo, si solo está configurando suURLconf , entonces sus capturas de la regexpasan a la función como argumentos (o argumentos con nombre).

Como:

(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),

Entonces en tu views.pytendrías

def profile_page(request, username):
    # Rest of the method
camflan
fuente
10
¿Es '? Param =' la única forma en que Django reconoce los parámetros? ¿Hay alguna manera de usar URLconf con HTTP.GET? Me gustaría hacer / param / 2.
sutee
3
Verifique la segunda parte de mi respuesta con respecto a sus URLconf y capturas de expresiones regulares.
camflan
2
No hay problema. use request.GET si envía un formulario usando GET, use request.POST si envía un formulario usando POST y si solo desea configurar las URL para que tengan secciones variables, entonces es un argumento URLconf / view.
camflan
10
¿Qué pasa con las vistas basadas en clase?
Usuario
8
para vistas basadas en clase que puede usarself.kwargs['parameter']
Royendgel Silberie
336

Para aclarar la explicación de camflan, supongamos que tiene

  • la regla url(regex=r'^user/(?P<username>\w{1,50})/$', view='views.profile_page')
  • una solicitud entrante para http://domain/user/thaiyoshi/?message=Hi

La regla del despachador de URL capturará partes de la ruta de URL (aquí "user/thaiyoshi/") y las pasará a la función de visualización junto con el objeto de solicitud.

La cadena de consulta (en este caso message=Hi) se analiza y parámetros se almacenan como QueryDicten request.GET. No se realizan más coincidencias ni procesos para los parámetros HTTP GET.

Esta función de vista usaría ambas partes extraídas de la ruta URL y un parámetro de consulta:

def profile_page(request, username=None):
    user = User.objects.get(username=username)
    message = request.GET.get('message')

Como nota al margen, encontrará el método de solicitud (en este caso "GET", y para los formularios enviados generalmente "POST") en request.method. En algunos casos es útil verificar que coincida con lo que espera.

Actualización: Al decidir si usar la ruta URL o los parámetros de consulta para pasar información, lo siguiente puede ayudar:

  • use la ruta URL para identificar recursos de manera única, por ejemplo /blog/post/15/(no /blog/posts/?id=15)
  • use parámetros de consulta para cambiar la forma en que se muestra el recurso, por ejemplo, /blog/post/15/?show_comments=1o/blog/posts/2008/?sort_by=date&direction=desc
  • para hacer URL amigables para los humanos, evite usar números de identificación y use, por ejemplo, fechas, categorías y / o babosas: /blog/post/2008/09/30/django-urls/
akaihola
fuente
17
Esta es una respuesta muy bien escrita. Seguro que me ayudó a entender Django un poco mejor.
Mark
2
¿Cómo podemos obtener todos los valores de los parámetros sin mencionar nombres?
numerah
@numerah request.GET es un diccionario de Python. Puede, por ejemplo, iterar a través de request.GET.items ().
akaihola
Respuesta perfecta.
Jay Geeth
1
¿Alguna razón por la cual se prefiere seguir los hábitos escritos en la actualización? (cuándo usar la ruta URL frente a los parámetros GET)
m0etaz
55

Usando GET

request.GET["id"]

Usando POST

request.POST["id"]
Dadaso Zanzane
fuente
27
Si bien esto funciona para las claves existentes, las respuestas de camflan y akaihola han utilizado .get () para evitar KeyErrorexcepciones en el caso de que falte una clave. Sería prudente hacer lo mismo (por ejemplo request.POST.get('id', '')).
vastlysuperiorman
25
def some_view(request, *args, **kwargs):
    if kwargs.get('q', None):
        # Do something here ..
Kevin
fuente
21

Para situaciones en las que solo tiene el requestobjeto que puede usarrequest.parser_context['kwargs']['your_param']

Ole Henrik Skogstrøm
fuente
2
Exactamente lo que necesitaba. Gracias.
user4052054
20

Me gustaría agregar alguna opción de mí mismo aquí. Alguien se preguntaría cómo establecer la ruta en urls.py, como

domain/search/?q=CA

para que podamos invocar la consulta.

El hecho es que NO es necesario establecer dicha ruta en urls.py. Lo que necesita establecer es solo la ruta en urls.py

urlpatterns = [
    path('domain/search/', views.CityListView.as_view()),
]

y cuando se introduce http: // servidor: puerto / Dominio / Búsqueda / q = CA . La parte de consulta '? Q = CA' se reservará automáticamente en la tabla hash a la que puede hacer referencia

request.GET.get('q', None).

Aquí hay un ejemplo (views.py)

class CityListView(generics.ListAPIView):
    serializer_class = CityNameSerializer

    def get_queryset(self):
        if self.request.method == 'GET':
            queryset = City.objects.all()
            state_name = self.request.GET.get('q', None)
            if state_name is not None:
                queryset = queryset.filter(state__name=state_name)
            return queryset

Además, cuando escribe una cadena de consulta en la URL

http://servername:port/domain/search/?q=CA

No ajuste la cadena de consulta entre comillas, p. Ej.

http://servername:port/domain/search/?q="CA"
Eric Andrews
fuente
¡Hola Eric! Soy nuevo en Django. ¿Puede arrojar más luz sobre "queryset = queryset.filter (state__name = state_name)". ¿Qué significa el guión bajo doble en state__name?
Subbu
1
Aquí "estado" es una tabla y "nombre" se archiva en esta tabla. En el filtro de Django, state__name hará referencia al valor del campo "nombre" en la tabla "estado".
Eric Andrews
este funcionó en comparación con los demás.
Sibish
17

Me gustaría compartir un consejo que puede ahorrarle algo de tiempo.
Si planea usar algo como esto en su urls.pyarchivo:

url(r'^(?P<username>\w+)/$', views.profile_page,),

Lo que básicamente significa www.example.com/<username>. Asegúrese de colocarlo al final de sus entradas de URL, porque de lo contrario, es probable que cause conflictos con las entradas de URL que siguen a continuación, es decir, acceder a una de ellas le dará el bonito error: User matching query does not exist.

acabo de experimentarlo yo mismo; ¡Espero eso ayude!

DrKaoliN
fuente
2
Además, en este caso es posible que desee comprobar que los nombres de usuario no colisionan con otras entradas de URL.
DrKaoliN
13

Tiene dos formas comunes de hacerlo en caso de que su URL se vea así:

https://domain/method/?a=x&b=y

v1:

Si la clave específica es obligatoria, puede usar:

key_a = request.GET['a']

Esto devolverá un valor de a si la clave existe y una excepción si no.

v2:

Si sus llaves son opcionales:

request.GET.get('a')

Puede intentarlo sin ningún argumento, esto no se bloqueará. Para que pueda envolverlo try: except:y volver, HttpResponseBadRequest()por ejemplo. Esta es una manera simple de hacer que su código sea menos complejo, sin usar el manejo de Excepciones especiales.

Bartłomiej
fuente
¿Cómo puedo detectar el parámetro de consulta desde la plantilla?
Akin Hwan
8

Esto no es exactamente lo que pidieron, pero este fragmento es útil para la gestión query_stringsde templates.

atascamiento
fuente
5

Estas consultas se realizan actualmente de dos maneras. Si desea acceder a los parámetros de consulta (GET), puede consultar lo siguiente:

http://myserver:port/resource/?status=1
request.query_params.get('status', None) => 1

Si desea acceder a los parámetros pasados ​​por POST, debe acceder de esta manera:

request.data.get('role', None)

Accediendo al diccionario (QueryDict) con 'get ()', puede establecer un valor predeterminado. En los casos anteriores, si no se informa el "estado" o el "rol", los valores son Ninguno.

mdcg
fuente
0

Esta es otra solución alternativa que se puede implementar:

en la url config. :

urlpatterns = [path('runreport/<str:queryparams>', views.get)]

en las vistas:

list2 = queryparams.split("&")
sachi
fuente