Managing Backend Data and Models in Django with VS Code
Separating application logic into Models, Views, and Controllers provides distinct advantages:
- Identical business logic can drive multiple View layers.
- State changes within the Model automatically propagate to associated Views via the Controller.
- Business rules and data access remain decoupled from presentation and interaction flows, enhancing maintainability and standardization.
Django abstracts database interactions using an Object-Relational Mapper (ORM). A Django Model is a Python class inheriting from django.db.models.Model, defined within an app's models.py file, representing a database table.
Django handles schema synchronization through its migration system:
- Modify classes in
models.py. - Execute
python manage.py makemigrationsto generate migration scripts in themigrations/directory. - Execute
python manage.py migrateto apply the scripts to the database.
Always interact with the database through Model classes. Avoid direct modifications using tools like SQLite Browser, as this risks schema inconsistencies with the application models. If initial data seeding is necessary, use Django's loaddata command after migrations.
Database Selection
The default db.sqlite3 is suitable only for development. According to SQLite documentation, it is not intended for applications exceeding 100,000 daily hits or distributed multi-server architectures. For production environments, PostgreSQL, MySQL, or SQL Server are recommended.
Defining a Model
Model fields map to database columns, utilizing types like CharField, TextField, EmailField, IntegerField, DateTimeField, and relationships (ForeignKey, ManyToManyField). Field options include max_length, blank=True (optional in forms), and null=True (optional in the database).
from django.db import models
from django.utils import timezone
class UserNote(models.Model):
content = models.CharField(max_length=500)
created_at = models.DateTimeField("creation timestamp")
def __str__(self):
localized_time = timezone.localtime(self.created_at)
return f"'{self.content}' created at {localized_time.strftime('%Y-%m-%d %H:%M:%S')}"
Run python manage.py makemigrations and python manage.py migrate to apply the new schema.
Implementing a Data Entry Form
- Create
forms.pyin the app directory to bind a form to theUserNotemodel.
from django import forms
from .models import UserNote
class UserNoteForm(forms.ModelForm):
class Meta:
model = UserNote
fields = ['content']
- Create the template
templates/app_name/submit_note.html:
{% extends "app_name/base.html" %}
{% block title %}Submit Note{% endblock %}
{% block content %}
<form method="POST" class="note-form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="submit-btn">Save</button>
</form>
{% endblock %}
- Add styling in
static/app_name/style.css:
input[name=content] {
width: 85%;
}
- Add the route in
urls.py:
path("submit/", views.submit_note, name="submit_note"),
- Define the view in
views.py:
from django.shortcuts import redirect, render
from django.utils import timezone
from .forms import UserNoteForm
from .models import UserNote
def submit_note(request):
form = UserNoteForm(request.POST or None)
if request.method == "POST" and form.is_valid():
instance = form.save(commit=False)
instance.created_at = timezone.now()
instance.save()
return redirect("home")
return render(request, "app_name/submit_note.html", {"form": form})
- Update the base template navigation to include the new page:
<a href="{% url 'submit_note' %}" class="nav-link">Add Note</a>
Displaying Data with Class-Based Views
- Update
templates/app_name/home.htmlto render therecent_notescontext:
{% extends "app_name/base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h2>Recent Notes</h2>
{% if recent_notes %}
<table class="data-table">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Content</th>
</tr>
</thead>
<tbody>
{% for note in recent_notes %}
<tr>
<td>{{ note.created_at | date:'M d, Y' }}</td>
<td>{{ note.created_at | time:'H:i' }}</td>
<td>{{ note.content }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No notes found. <a href="{% url 'submit_note' %}">Create one</a>.</p>
{% endif %}
{% endblock %}
- Add table styling:
.data-table th, .data-table td {
text-align: left;
padding: 8px 12px;
}
- Replace the function-based home view with a
ListViewinviews.py:
from django.views.generic import ListView
from .models import UserNote
class NoteListView(ListView):
model = UserNote
template_name = "app_name/home.html"
context_object_name = "recent_notes"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
- Configure the URL in
urls.py:
from .views import NoteListView
from .models import UserNote
home_view = NoteListView.as_view(
queryset=UserNote.objects.order_by("-created_at")[:10],
context_object_name="recent_notes",
template_name="app_name/home.html",
)
path("", home_view, name="home"),
Template Debugging in VS Code
Django templates contain logic ({% if %}, {% for %}) which can introduce bugs. The VS Code Python extension supports template debugging when "django": true is configured in the launch configuration.
- Set breakpoints in
home.htmlon lines containing{% if recent_notes %}or{% for note in recent_notes %}. - Start the debugger. Execution pauses at the breakpoint, displaying context variables in the debug panel.
- Use Step Over (F10) to navigate through template logic and inspect variable states.
- The Debug Console allows evaluating expressions dynamically.
Dependency Management
Distribute project dependencies using requirements.txt rather than sharing the virtual environment.
- Activate the target environment.
- Execute
pip freeze > requirements.txt.
Collaborators can install dependencies using pip install -r requirements.txt.
Django Admin Setup
Django includes a built-in admin interface protected by authentication.
- Generate a superuser account:
python manage.py createsuperuser --username=<admin_user> --email=<admin@example.com>
- Ensure the route exists in the project's
urls.py:
path("admin/", admin.site.urls),
- Navigate to
/admin, authenticate, and manage data records.