Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 14

Function-Based Views in Django

Recommended resources

Hello! Welcome back to the course.

In our last lesson, you successfully configured URL patterns, acting as your application's traffic controller. You mapped specific URLs to placeholder view functions that returned simple text responses. This was a crucial step in understanding how Django directs requests.

Today, we're going to build the "brain" of those routes. This lesson focuses on the learning outcome: Create function-based views to handle HTTP requests and return responses. We'll move beyond simple text and write view functions that can process user input, prepare data, and use more sophisticated ways to respond, setting the stage for building fully-featured web pages.

1. What is a Django View?

At its core, a Django view is a Python function that does a specific job: it takes information about a web request and returns a web response. It's the central piece of logic that connects your data (Models) to your presentation (Templates).

Django MVT Architecture Diagram
This diagram shows the relationship between Models, Views, and Templates (MVT), which is Django's core architectural pattern. The View acts as the intermediary, processing logic and coordinating between the Model and the Template.

The entire flow, from the user's browser to your view and back again, looks like this:

Django Request-Response Cycle with Views
This diagram illustrates the request-response cycle. A user's request for a URL is routed to the correct View. The View processes the request (the "Process Data" step) and generates an HTTP Response, which is sent back to the user.

To see this concept in action, let's watch a short video that defines and creates a very simple view function.

Django Tutorial for Beginners – Build Powerful Backends

The video "Django Tutorial for Beginners" by Programming with Mosh provides a clear, concise explanation of what a view function is and how to create a basic one.

Watch the section from 25:27 to 27:14. Focus on the core definition: a view is just a Python function that takes a request and returns an HttpResponse.

As you saw, the basic structure is:

from django.http import HttpResponse

def my_view(request):
    # ... logic goes here ...
    return HttpResponse("Hello, world!")

2. The HttpRequest Object: Your View's Input

The request parameter in your view function is not just a placeholder. It's an HttpRequest object that Django creates automatically, and it's packed with useful information about the incoming request. For your web development background, you can think of it as a Python object that holds information similar to PHP's superglobals like $_SERVER, $_GET, and $_POST.

Here are a few of the most important attributes:

  • request.method: A string representing the HTTP method used, usually 'GET' or 'POST'. This is how you can tell if a user is just visiting a page or submitting a form.
  • request.POST: A dictionary-like object containing all data submitted from an HTML <form> using the POST method.
  • request.GET: A dictionary-like object containing all data passed in the URL's query string (e.g., in /search?q=django, request.GET['q'] would be 'django').

Being able to check request.method is fundamental to building interactive pages. The common pattern is:

  • If request.method is 'GET', the user is just requesting to see the page. Your view should prepare the necessary data and display the page.
  • If request.method is 'POST', the user has submitted a form. Your view should process the submitted data (e.g., save it to the database), and then usually redirect the user to another page.

Let's see this in a practical example. The following video demonstrates a view for a to-do list that handles both cases.

Django Todo App - Class Based Views vs Function Based Views

The video "Django Todo App" from Code With Stein shows a perfect example of a view that handles both displaying data (a GET request) and creating a new item (a POST request). This GET/POST pattern is one of the most important concepts you'll use.

Watch from 02:48 to 05:14. Pay close attention to the if request.method == 'POST': block. Notice how it gets data from request.POST, creates a new item, and then redirects. The code outside the if block handles the GET request by preparing a list of items to display.


3. The HttpResponse Object: Your View's Output

Just as every view receives a request, it must return a response. So far, we've only used the basic HttpResponse. Now, let's look at two more powerful and common ways to create a response.

For a clear explanation of this, let's turn to an article from the PyCharm blog.

An Introduction to Django Views | The PyCharm Blog

The article "An Introduction to Django Views" clearly explains the different ways a view can generate a response, focusing on the render() shortcut.

Read the sections titled "Rendering and passing data to templates" and "Function-based views". Focus on: How the render() function combines a template file with a context dictionary. The structure of a function-based view that uses render().

Based on what you just read, here are the key response types:

  1. HttpResponse("..."): You've used this. It's great for simple text, testing, or returning non-HTML content like JSON or CSV data.

  2. redirect("url-name"): As you saw in the "Code With Stein" video, redirect is used to send the user to a different page. This is essential after successfully processing a form with a POST request. It prevents the user from accidentally resubmitting the form by refreshing the page (a pattern known as Post/Redirect/Get).

  3. render(request, "template_name.html", context): This is the most common and powerful one. It's a shortcut that does two things: it loads an HTML template file and fills it with data you provide in a context dictionary. It then returns a fully rendered HttpResponse. This is how you separate your Python logic from your HTML presentation.

Test your understanding!

A user fills out a "Create New Task" form and clicks "Submit". In your view, after you successfully save the new task, which type of response (HttpResponse, redirect, or render) should you generally return, and why?

Show answer

You should return a redirect. After a successful POST request that changes data, redirecting the user (e.g., back to the main task list) prevents them from accidentally resubmitting the same form if they refresh the page.


4. Let's Build a View

Now, let's apply these concepts to our tasks app. We will replace the simple index view with a more realistic one that prepares a list of tasks to be displayed. We won't connect to a database just yet (that's for the next module), so we'll use a hardcoded Python list for now.

  1. Open tasks/views.py.
  2. Modify your index view to look like this. We are replacing the old HttpResponse with render.
# tasks/views.py

from django.shortcuts import render # Import render
# We no longer need HttpResponse for this view, but you might need it for others.

# Dummy data - we'll replace this with a real database query later
dummy_tasks = [
    {'id': 1, 'title': 'Learn Django Views', 'completed': True},
    {'id': 2, 'title': 'Create a Template', 'completed': False},
    {'id': 3, 'title': 'Connect to a Database', 'completed': False},
]

def index(request):
    # Create a context dictionary to pass data to the template
    context = {
        'tasks': dummy_tasks
    }
    # Use the render shortcut to generate the response
    return render(request, 'tasks/task_list.html', context)

# You can keep your 'about' view as it is for now
def about(request):
    from django.http import HttpResponse
    return HttpResponse("This is the about page.")

Let's break this down:

  • We've created a list of dictionaries called dummy_tasks to simulate data from a database.
  • Inside the index view, we create a context dictionary. The keys of this dictionary (e.g., 'tasks') will become variables you can use in your HTML template.
  • We then call render(), telling it to use an HTML file located at tasks/task_list.html and to pass our context dictionary to it.
  1. Check your server. Make sure your development server is running (python manage.py runserver). Now, open your browser and navigate to http://127.0.0.1:8000/.

You will see an error page with a big, red message: TemplateDoesNotExist.

This is expected! Don't worry, you haven't done anything wrong. Your view function is working perfectly. It prepared the data and tried to find the template file tasks/task_list.html, but that file doesn't exist yet. We've successfully separated our logic (in the view) from our presentation (the non-existent template).


Conclusion

In this lesson, you took a major step forward in building real web applications. You moved from simple text responses to writing views that handle different HTTP methods and prepare dynamic data for presentation.

Key Takeaways:

  • A function-based view is a Python function that takes an HttpRequest object and returns an HttpResponse object.
  • The request object gives you access to crucial information, including request.method (GET/POST) and request.POST (form data).
  • A common pattern is to check if request.method == 'POST' to handle form submissions separately from page loads.
  • render() is the primary tool for generating HTML responses by combining a template file with a context dictionary.
  • redirect() is used to send the user to a new URL, typically after a successful form submission.

Preview of the Next Lesson:
We've ended on a TemplateDoesNotExist error. In our next lesson, "Use the Django Template Language to render dynamic HTML pages," we will fix this error. You will create the task_list.html file and learn how to use Django's template tags and variables to display the list of tasks we prepared in our view.