Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Managing Backend Data and Models in Django with VS Code

Tech 1

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:

  1. Modify classes in models.py.
  2. Execute python manage.py makemigrations to generate migration scripts in the migrations/ directory.
  3. Execute python manage.py migrate to 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

  1. Create forms.py in the app directory to bind a form to the UserNote model.
from django import forms
from .models import UserNote

class UserNoteForm(forms.ModelForm):
    class Meta:
        model = UserNote
        fields = ['content']
  1. 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 %}
  1. Add styling in static/app_name/style.css:
input[name=content] {
    width: 85%;
}
  1. Add the route in urls.py:
path("submit/", views.submit_note, name="submit_note"),
  1. 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})
  1. 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

  1. Update templates/app_name/home.html to render the recent_notes context:
{% 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 %}
  1. Add table styling:
.data-table th, .data-table td {
    text-align: left;
    padding: 8px 12px;
}
  1. Replace the function-based home view with a ListView in views.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
  1. 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.

  1. Set breakpoints in home.html on lines containing {% if recent_notes %} or {% for note in recent_notes %}.
  2. Start the debugger. Execution pauses at the breakpoint, displaying context variables in the debug panel.
  3. Use Step Over (F10) to navigate through template logic and inspect variable states.
  4. The Debug Console allows evaluating expressions dynamically.

Dependency Management

Distribute project dependencies using requirements.txt rather than sharing the virtual environment.

  1. Activate the target environment.
  2. 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.

  1. Generate a superuser account:
python manage.py createsuperuser --username=<admin_user> --email=<admin@example.com>
  1. Ensure the route exists in the project's urls.py:
path("admin/", admin.site.urls),
  1. Navigate to /admin, authenticate, and manage data records.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.