Recommended preparation: set up a Django project and read the Django tutorial overview before trying the code.
A query string appears after the ? in a URL, such as /students/search/?id=10&name=Alex. Django makes these values available through request.GET.
views.py — read two optional query parameters
from django.http import HttpResponse
def my_data(request):
student_id = request.GET.get("id", "Not available")
name = request.GET.get("name", "Not available")
return HttpResponse(f"ID: {student_id}; Name: {name}")
Try http://127.0.0.1:8000/my_app/student/my_data/?id=10&name=Alex%20Ron after configuring the URL. The %20 represents a space in the query string.
my_app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("student/my_data/", views.my_data, name="my_data"),
]
The browser URL should match the project/app prefixes you configure in urls.py. Query parameters are not part of the route pattern; Django separates them automatically.
my_app/views.py
from django.shortcuts import render
def my_data(request):
context = {
"student_id": request.GET.get("id", "Not available"),
"name": request.GET.get("name", "Not available"),
}
return render(request, "my_data.html", context)
my_app/templates/my_data.html
<!DOCTYPE html>
<html lang="en"><body>
<p>Student ID: {{ student_id }}</p>
<p>Student name: {{ name }}</p>
</body></html>
Django automatically HTML-escapes ordinary template variables. Avoid returning unchecked query input inside an HTML string built with mark_safe() or unsafe formatting.
Reject non-numeric id values before using them
from django.http import HttpResponseBadRequest
from django.shortcuts import render
def my_data(request):
raw_id = request.GET.get("id", "")
try:
student_id = int(raw_id)
except ValueError:
return HttpResponseBadRequest("Provide a numeric id")
return render(request, "my_data.html", {"student_id": student_id})
For database records, prefer the ID as a typed URL path parameter and call get_object_or_404. An integer query value does not by itself prove the record exists or that the current user may view it.
getlist() returns all values for a repeated key
# Example URL: /search/?tag=python&tag=django
from django.http import JsonResponse
def tags(request):
selected = request.GET.getlist("tag")
return JsonResponse({"tags": selected})
Expected output
{"tags": ["python", "django"]}
Python standard library
from urllib.parse import urlencode
params = {"id": 10, "name": "Alex Ron"}
print(urlencode(params))
Expected output
id=10&name=Alex+Ron
Do not manually concatenate user-entered values to build URLs. urlencode() escapes spaces and reserved characters correctly.
.get() for an optional parameter instead of indexing directly..getlist() when the same name may appear more than once.Convert an optional page number safely
# Query string: ?page=3
raw_page = request.GET.get("page", "1")
try:
page = max(1, int(raw_page))
except ValueError:
page = 1
Whitelist a database sort field
# Query string: ?sort=name
allowed = {"name", "mark", "id"}
requested = request.GET.get("sort", "id")
sort_field = requested if requested in allowed else "id"
students = Student.objects.order_by(sort_field)
QueryDict.urlencode() uses correct escaping
from django.http import QueryDict
params = QueryDict(mutable=True)
params["name"] = "Alex Ron"
params["id"] = "10"
print(params.urlencode())
Expected output
name=Alex+Ron&id=10
A template can read GET only when the request context processor is enabled
{% if request.GET.name %}
<p>Searching for: {{ request.GET.name }}</p>
{% endif %}
For reusable code and explicit validation, prefer passing a controlled value from the view rather than relying on template access to the entire request.
GET contains decoded query-string parameters; POST contains ordinary HTML form body fields. Both expose QueryDict objects.
Yes. Treat all query-string content as untrusted and validate it before use.
Use a route such as students/
Previous: Form classes and validation
Next: Template for loops
Browse the complete Django tutorial series.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.