Django ModelForm - Creating Forms using Django Models

Django ModelForm – Creating Forms using Django Models

Django ModelForm is a class that converts a model into a Django form directly. If you’re creating a database-driven project, you’ll almost certainly have forms that correspond to Django models. ModelForms in Django is an utility class that lets you generate a Form class from an existing Django model.

It appears to be more difficult to implement than it actually is.

Create a Django Model Which ModelForm Will Use

Add a model to models.py

demosite > main > models.py

from django.db import models

# Create your models here.

class Movie(models.Model):
	movie_title = models.CharField(max_length=150)
	release_year = models.IntegerField()
	director = models.CharField(max_length=100)
	movie_poster = models.ImageField(upload_to='images/', None=True)
	movie_plot = models.TextField()
	

	def __str__(self):
		return self.movie_title

The preceding example comes from the book How to Use Django Models. There are CharFields, IntegerFields, ImageFields, and TextFields in the model.

The code at the bottom returns the movie’s title as the admin’s display name, making each model object easier to recognise.

Configure Django Website To Support Media Uploads

demosite > demosite > settings.py

MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')Code language: JavaScript (javascript)

If your models contain an ImageField or FileField, include a URL for Django media file uploads in the settings.

demosite > demosite > urls.py

from django.contrib import admin
from django.urls import path, include
from django.conf import settings #add this
from django.conf.urls.static import static #add this

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include ('main.urls')),
]

if settings.DEBUG: #add this
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)Code language: PHP (php)

Also, in the demosite > urls.py file, add a URL path for the media files. You’ll see that these settings are solely for testing.

To serve media files in production, follow these instructions

Install Pillow

pip install Pillow

For media uploading, you’ll also need to install Pillow.

Run Migrations

py manage.py makemigrations
py manage.py migrateCode language: CSS (css)

To develop the Movie model, you’ll also need to make migrations and migrate to apply the migrations to the database.

Register the model in the Django admin.py

demosite > main > admin.py

from django.contrib import admin
from .models import Movie

admin.site.register(Movie)Code language: JavaScript (javascript)

Now that the model has been uploaded to the database, you may see and change it via the Django administration interface by registering it in the admin.py file.

To access the admin page, you’ll need a Django superuser account.

Create a Django ModelForm

Create a forms.py

demosite > main > (New File) forms.py

from django import forms

# Create your forms here.Code language: PHP (php)

Because Django does not include a forms.py file, you must create one in the same directory as the models.py file, mysite > main.

Then, at the top of the model, you may import forms from Django.

Rather than declaring Django form fields like forms, we’ll do it now.

Let’s import our current Model, CharField.

Because, as you may have observed, the model fields are the exact fields that we require for the form.

Create a ModelForm

demosite > main > forms.py

from django import forms
from .models import Movie 


# Create your forms here.Code language: PHP (php)

Please notice that the official Django documentation imports ModelForm from django.forms and places ModelForms in the models.py file. Let’s simply add my ModelForms to the forms.py file instead.

I prefer this way since it’s easier for me to refer to the forms.py file whenever I need a form.

demosite > main > forms.py

from django import forms
from .models import Movie 


# Create your forms here.
class MovieForm(forms.ModelForm):

    class Meta:
        model = Movie
        fields = ('movie_title', 'release_year', 'director', 'movie_poster', 'movie_plot')

For your form, create a MovieForm class. The ModelForm’s functionality may be changed using the Meta class. Indicate the model that your fields are generated from, as well as the fields that you want to use from that model.

You may choose to include all of the fields or just a few.

Create a Django Template To Utilize The Form

Render the ModelForm and Model objects

demosite > demosite > views.py

from django.shortcuts import render, redirect
from .models import Movie
from .forms import MovieForm
from django.contrib import messages

# Create your views here.
def homepage(request):
	if request.method == "POST":
		movie_form = MovieForm(request.POST, request.FILES)
		if movie_form.is_valid():
			movie_form.save()
			messages.success(request, ('Your movie was successfully added!'))
		else:
			messages.error(request, 'Error saving form')
		
		
		return redirect("main:homepage")
	movie_form = MovieForm()
	movies = Movie.objects.all()
	return render(request=request, template_name="main/home.html", context={'movie_form':movie_form, 'movies':movies})Code language: PHP (php)

Add an if condition for the form submission to your views.py file. Make sure to include a request. If you choose FILES as the file data source, your picture will not be saved to the form.

Save the form if it is correct. If the form is both valid and incorrect, you may select to display a Django message.

Because the form is a MovieForm, saving it now creates a new model object in the Movie model. This makes rendering the form and model objects in the next stage a breeze.

Render the ModelForm and Model objects

demosite > main > (New Folder) templates > (New Folder) main > (New File) home.html

<!DOCTYPE html>
<html>
  <head>
       <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <title>Django ModelForms</title>
    </head>
    <body>

      {% load crispy_forms_tags %}  

        
        <div class="container">
          <!--Django Model Form-->
          <h2 class="my-4">Add a new movie</h2>
          <form method="post" enctype="multipart/form-data">
            {% csrf_token %}
                {{movie_form|crispy}}
                <button class="btn btn-primary my-4" type="submit">Submit</button>
          </form>
          <!--Django Model-->
          <h2 class="my-4">Movies</h2>
          <div class="row">
            {% for m in movies %}
            <div class="col-lg-4 col-md-6 col-sm-12 pb-4">
              <div class="card h-100 p-4">
                <img src="{{ m.movie_poster.url }}" class="card-img-top" alt="{{ m.movie_title}}">
                <h4>{{m.movie_title}}</h4>
                <p class="text-muted">{{m.release_year}} | {{m.director}}</p>
                <p>{{m.movie_plot}}</p>
              </div>
            </div>
            {% empty %}
            <p>No movies added.</p>
            {% endfor %}
          </div>
        </div>
    

    <!-- Option 1: Bootstrap Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    </body>
</html>Code language: HTML, XML (xml)

Let’s get started on the Django template. This template will render the MovieForm and the Movie model objects as cards, among other things.

The Bootstrap 5.0.2 CDN is used in this template.

IMPORTANT: enctype="multipart/form-data" must be included to form. This is done to guarantee that uploaded files, such ImageField and FileField, are encoded before being sent to the server.

I’d also want to note out that if the array is empty or not found, you may use the percent empty percent template element to show content.

Result

Conclusion

I believe ModelForm is a very powerful helper class provided to us by Django. Effectively utilizing the class can enable us to streamline our form development process, and make integrating forms with Django models extremely easy.

In this article, we took a look at how to work with ModelForms in Django. We took a look at creating, rendering and working with Django ModelForms. As always, If you have found this article useful do not forget to share it and leave a comment if you have any questions. Happy Coding


Posted

in

by

Tags:

Comments

Leave a Reply