DEV Community

Cover image for Building a Basic Django App: A Hands-On MVT Example with Attachee Data
obonyodorice
obonyodorice

Posted on

Building a Basic Django App: A Hands-On MVT Example with Attachee Data

As a developer, one of the most rewarding experiences is seeing your data come to life on a web page. Recently, I set out to build a simple Django application to demonstrate the fundamental concepts of the Model-View-Template (MVT) architecture. My goal was straightforward: define a model for student attachee, populate it with some data, retrieve that data using a Django view, and then elegantly display it in an HTML table using Django's templating engine. This exercise perfectly illustrates how Django structures web applications and handles the flow of data from the database to the user's browser.

Let's break down each step of the process.

1. The Model: Defining Our Data Structure (The 'M' in MVT)
The 'M' in MVT stands for Model. In Django, a Model is a Python class that inherits from django.db.models.Model. It defines the structure of your data, essentially mapping to a table in your database. Each attribute of the Model class represents a field (a column) in that database table.

For our attachés application, I needed to store information such as their name, email, phone number, the department they are attached to, and their university. Here's how I defined the Attachee model in first_app/models.py:

from django.db import models

class Attache(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True) 
    phone = models.CharField(max_length=20, blank=True, null=True) 
    department = models.CharField(max_length=100)
    university = models.CharField(max_length=100)
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):

        return f"{self.name} from {self.university}"

Enter fullscreen mode Exit fullscreen mode

After defining the model, I ran the standard Django commands to create the database table:

python manage.py makemigrations
python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

These commands translate the Python model definition into database schema changes and apply them. Then, I accessed the Django admin (after creating a superuser) to quickly add a few sample Attachee records to the database for testing.

2. The View: Retrieving and Preparing Data (The 'V' in MVT)
The 'V' in MVT refers to the View. In Django's context, the View is a Python function or class that receives a web request, interacts with the Model to fetch or manipulate data, and then prepares a context dictionary (data) to be passed to a template. It's the brain that orchestrates what data is needed and how it's presented.

My goal was to display all attachés. So, my view needed to query the Attachee model and retrieve every record.

from django.shortcuts import render
from .models import Attachee

def attache_list(request):
    all_attachees = Attachee.objects.all()

    context = {
        'attachees': all_attachees,
        'page_title': 'List of All Attachees' 
    }

    return render(request, 'myapp/attache_list.html', context)
Enter fullscreen mode Exit fullscreen mode

3. The Template: Presenting the Data (The 'T' in MVT)
The 'T' in MVT stands for Template. This is the presentation layer, typically an HTML file with Django's powerful template language embedded within it. Its job is to display the data received from the view in a user-friendly format. I chose a simple HTML table to showcase the attaché data.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ page_title }} - Attache Management</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        h1 { color: #333; }
        .no-data { text-align: center; color: #888; margin-top: 30px; }
    </style>
</head>
<body>
    <h1>{{ page_title }}</h1>

    {% if attaches %} 
    <table>
        <thead>
            <tr>
                <th>Name</th>
                <th>Email</th>
                <th>Phone</th>
                <th>Department</th>
                <th>University</th>
                <th>Date Added</th>
            </tr>
        </thead>
        <tbody>
            {% for attachee in attachees %}
            <tr>
                <td>{{ attachee.name }}</td> {# Accessing attributes of the current 'attache' object #}
                <td>{{ attachee.email }}</td>
                <td>{{ attachee.phone|default:"N/A" }}</td> 
                <td>{{ attachee.department }}</td>
                <td>{{ attachee.university }}</td>
                <td>{{ attachee.date_added|date:"F d, Y P" }}</td> 
            </tr>
            {% endfor %}
        </tbody>
    </table>
    {% else %} 
        <p class="no-data">No attachee records found.</p>
    {% endif %}

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

4. The URL: Mapping Requests to Views (The Router)
The URL configuration, or URLconf, acts as the router for our application. It's responsible for mapping specific URL patterns to the correct view functions or classes.

Since I had configured the project's main urls.py to include the URLs from my myapp:

Next, I defined the specific URL pattern within first_app/urls.py to point to our attachee_list view:

from django.urls import path
from . import views 

urlpatterns = [
    path('attachee_list/', views.attachee_list, name='attachee_list'),
]
Enter fullscreen mode Exit fullscreen mode

The Final Result: Data on Display
With these pieces in place, when I navigated my browser to http://127.0.0.1:8000/first_app/attachee_list/ (assuming Django's development server is running), the following happened:

  • The browser sent an HTTP GET request to /first_app/attachee/.
  • Django's URL dispatcher in my_project/urls.py matched first_app/attachee/ and directed the request to first_app.urls.
  • In first_app/urls.py, the path('attachee_list/') pattern matched the remaining empty string and called the attachee_list view function.
  • The attachee_list view queried the database (Attachee.objects.all()) to fetch all attaché records.
  • It then rendered the first_app/attachee_list.html template, passing the all_attachee data in the context.
  • The template engine iterated over the attachee data, populated the HTML table rows, and applied any specified filters.

Finally, the rendered HTML was sent back to the browser, displaying a clean, organized table of all our attachee data.

This simple example perfectly encapsulates the power and elegance of Django's MVT architecture. The clear separation of concerns—data definition in the Model, business logic and data preparation in the View, and presentation in the Template—makes the application easy to understand, maintain, and extend. It's a foundational concept that every Django developer masters, paving the way for building more complex and dynamic web applications.

Top comments (0)