djangoformssqlitedjango-modelsdjango-views

Why isn't my form data inserted into the database?


My form data won't save to the database. I don't want to add libraries or change code too much. The post request comes through in the terminal but no data is stored:

views.py:

from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpRequest
from . models import Activity

# Create your views here.
def index(request: HttpRequest):
    return render(request, "activity/index.html")

def new_activity(request: HttpRequest):
    return render(request, "activity/new_activity.html")

def create_new_activity(request: HttpRequest):
    params = request.POST
    activity = Activity(
        activity_name = params.get("activity_name")

    )
    activity.save()
    return redirect("/")

new_activity.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>New Activity</h1>

    <form action="/new_activity/" method="post">
        <input type="text" name="activity_name" id="activity_name">
        <button type="submit">Add Activity</button>
    </form>
</body>
</html>

urls.pf:

from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("new_activity/", views.new_activity, name="new_activity"),
]

The model I tried migrating:

from django.db import models

# Create your models here.
class Activity(models.Model):
    id = models.BigAutoField(primary_key=True)
    activity_name = models.TextField()

class TimeLog(models.Model):
    id = models.BigAutoField(primary_key=True)
    start_time = models.TimeField()
    end_time = models.TimeField()
    activity = models.ForeignKey("Activity", on_delete=models.CASCADE)

Solution

  • You submit the form to the new_activity view, so it does not do anything with the data, and just re-renders the template.

    Add logic to handle the POST request to the new_activity view:

    def new_activity(request: HttpRequest):
        if request.method == 'POST':
            params = request.POST
            activity = Activity.objects.create(
                activity_name=params.get('activity_name')
            )
            return redirect('index')
        return render(request, 'activity/new_activity.html')

    Note: It is better to use a Form [Django-doc] than to perform manual validation and cleaning of the data. A Form will not only simplify rendering a form in HTML, but it also makes it more convenient to validate the input, and clean the data to a more convenient type.


    Note: It is usually better to use .create(…) [Django-doc] to create a record in the database, than to instantiate a model object and .save(…) [Django-doc] it: when you save a model instance, it first looks if there is already a record, so this can increase the number of queries on the database.


    Note: Typically you better use the name of the view where you redirect to, that way, Django can determine the path, making it less likely that the path contains mistakes, and will automatically adapt if you change/move the path.