No Time Dad

A blog about web development written by a busy dad

Django Submit Form Without a Model

In Django, forms and models are usually tightly coupled. And for good reason. It’s not common that I’ll have a form without a model, so Django does tries to make it easy for them to work together. This does make things a little tricky if I need to de-couple them, though.

Once in a while though I find myself in the situation where I need a form without a model. This is generally when I need the server to do some one off task like call a script on the host machine or kick-off an asynchronous background task.

>>> import django
>>> django.__version__
'3.2.8'
# forms.py
from django import forms

class MyForm(forms.Form):
    generic_input = forms.CharField()
# views.py
from django.shortcuts import render
from django.urls import reverse
from django.views.generic import View

class MyView(View):
    template_name = "my-template.html"

    def get(self, request):
        form = MyForm()
        return render(request, self.template_name, {"form": form})

    def post(self, request):
        form = MyForm(request.POST)
        if form.is_valid():
            # Do something with the form data
            print(form.cleaned_data)
            return HttpResponseRedirect(reverse("home"))
        return render(request, self.template_name, {"form": form})
<!-- my-template.html -->
<form action="{% url 'my-view' %}" method="POST">
  {% csrf_token %} {{ form.as_p }}
  <input type="submit" value="Save" />
</form>

The basic idea here is that I’m creating a simple input form in my forms.py file, and creating a class-based view in my views.py. In the view I’ll override the default get and post methods. This’ll allow me to have Django do something else with the POST request from the html form instead of saving to the database. Then, in the template I just need to map the form action to the named url in my urls.py for the application.

It’s important to note here that if I don’t override the get method and create the form instance than my form will not show up in the template. In fact, what I’ll likely see in the terminal where the server is running is an error that looks something like this:

Method Not Allowed (GET): <url>