Django Tutorial

Django Create A Complete Project

Django Template

Django Database Query

Django Form

Django Authentication and Permission Management

Django unittest

Django Advanced

Django Defines A Form Based On Model

Django Define a Form Based on Model Tutorial

In this tutorial, we'll learn how to create a form based on a model in Django. Model forms make it easy to create forms that interact with your database models, streamlining form rendering, validation, and data processing.

Prerequisites:

  • Basic knowledge of Python
  • Familiarity with Django framework
  • A Django project set up and running
  • A Django app with at least one model

Assuming we have an app named 'myapp' with the following models.py:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    publication_date = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)

Step 1: Create a model form

1.1. In your Django app, create a new file called forms.py. Inside the file, import the necessary modules and create a form based on the Book model:

from django import forms
from .models import Book

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['title', 'author', 'publication_date', 'price']

The Meta class inside the form specifies the model and the fields to be included in the form. You can customize the form further by adding additional fields, modifying form field attributes, and adding validation methods.

Step 2: Use the form in a view

2.1. In your app's views.py, import the form and create a view to handle form rendering and submission:

from django.shortcuts import render, redirect
from .models import Book
from .forms import BookForm

def create_book(request):
    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('myapp:book_list')
    else:
        form = BookForm()
    return render(request, 'myapp/create_book.html', {'form': form})

This view handles both GET and POST requests. When the user submits the form (POST request), the view validates the form data and saves it to the database if it's valid. If the form is not valid, it displays the form with error messages. When the user visits the page initially (GET request), the view renders an empty form.

Don't forget to replace 'myapp:book_list' with the appropriate URL name for your app.

Step 3: Create a template to display the form

3.1. In your app's templates folder, create a new template called create_book.html and use the following code to display the form:

{% extends "base.html" %}

{% block content %}
  <h2>Create a new book</h2>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Save</button>
  </form>
{% endblock %}

This template extends a base template and renders the form inside a form element. The {{ form.as_p }} tag renders the form as a series of paragraphs, with each field enclosed in a <p> tag.

Step 4: Add URL pattern

4.1. In your app's urls.py, add a new URL pattern for the create_book view:

from django.urls import path
from . import views

app_name = 'myapp'
urlpatterns = [
    # Other URL patterns...
    path('create_book/', views.create_book, name='create_book'),
]

Here, we define a new URL pattern that maps to the create_book view in our views.py file. We assign a name 'create_book' to this URL pattern, which can be used for reverse URL resolution in templates and views.

Step 5: Include the app's URLs in the project URLs

5.1. In your project's urls.py file, make sure you include your app's URLs:

from django.contrib import admin
from django.urls import path, include

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

Replace 'myapp/' with the desired URL prefix for your app, and 'myapp.urls' with the appropriate path to your app's urls.py file.

Now, when you run your Django development server, you should be able to access the create_book view by visiting the URL that corresponds to the URL pattern you defined, such as http://127.0.0.1:8000/myapp/create_book/.

  1. Creating forms from models in Django:

    • Description: Django allows you to create forms directly from models, simplifying the process of handling form data that corresponds to database models.

    • Code Example:

      # models.py
      from django.db import models
      
      class MyModel(models.Model):
          name = models.CharField(max_length=100)
          email = models.EmailField()
      
      # forms.py
      from django import forms
      from .models import MyModel
      
      class MyModelForm(forms.ModelForm):
          class Meta:
              model = MyModel
              fields = ['name', 'email']
      
  2. Django model form example:

    • Description: A simple example demonstrating how to create a ModelForm for a Django model.

    • Code Example:

      # models.py
      from django.db import models
      
      class Product(models.Model):
          name = models.CharField(max_length=100)
          price = models.DecimalField(max_digits=5, decimal_places=2)
      
      # forms.py
      from django import forms
      from .models import Product
      
      class ProductForm(forms.ModelForm):
          class Meta:
              model = Product
              fields = ['name', 'price']
      
  3. How to use ModelForm in Django:

    • Description: ModelForms simplify the creation of forms for models by automatically generating form fields based on the model's fields.
    • Code Example:
      # views.py
      from django.shortcuts import render
      from .forms import ProductForm
      
      def create_product(request):
          if request.method == 'POST':
              form = ProductForm(request.POST)
              if form.is_valid():
                  form.save()
          else:
              form = ProductForm()
      
          return render(request, 'create_product.html', {'form': form})
      
  4. Django forms for model instances:

    • Description: ModelForms can be used not only for creating new model instances but also for updating existing ones.
    • Code Example:
      # views.py
      from django.shortcuts import render, get_object_or_404
      from .forms import ProductForm
      from .models import Product
      
      def edit_product(request, product_id):
          product = get_object_or_404(Product, pk=product_id)
      
          if request.method == 'POST':
              form = ProductForm(request.POST, instance=product)
              if form.is_valid():
                  form.save()
          else:
              form = ProductForm(instance=product)
      
          return render(request, 'edit_product.html', {'form': form})
      
  5. ModelForm vs. regular forms in Django:

    • Description: ModelForms automatically generate form fields based on the model, while regular forms require manual definition of fields.
    • Code Example:
      # Regular form
      class MyForm(forms.Form):
          name = forms.CharField(max_length=100)
          email = forms.EmailField()
      
  6. Django form fields for model fields:

    • Description: ModelForm fields are automatically generated based on model fields, but you can also customize them or add extra fields.
    • Code Example:
      # forms.py
      from django import forms
      from .models import MyModel
      
      class MyModelForm(forms.ModelForm):
          custom_field = forms.CharField()
      
          class Meta:
              model = MyModel
              fields = ['name', 'email']
      
  7. Customizing Django ModelForm behavior:

    • Description: Customize ModelForm behavior by overriding methods such as clean, save, or defining custom validation logic.
    • Code Example:
      # forms.py
      from django import forms
      from .models import MyModel
      
      class MyModelForm(forms.ModelForm):
          class Meta:
              model = MyModel
              fields = ['name', 'email']
      
          def clean_name(self):
              # Custom validation logic for the 'name' field
              name = self.cleaned_data['name']
              if name.startswith('X'):
                  raise forms.ValidationError("Name cannot start with 'X'")
              return name
      
  8. Django ModelForm initial data:

    • Description: Set initial data for a ModelForm to prepopulate form fields when rendering the form.
    • Code Example:
      # views.py
      from .forms import ProductForm
      from .models import Product
      
      def edit_product(request, product_id):
          product = get_object_or_404(Product, pk=product_id)
      
          if request.method == 'POST':
              form = ProductForm(request.POST, instance=product)
              if form.is_valid():
                  form.save()
          else:
              form = ProductForm(instance=product, initial={'name': 'Initial Name'})
      
          return render(request, 'edit_product.html', {'form': form})
      
  9. Django dynamic forms with ModelForm:

    • Description: Dynamically modify ModelForm behavior or fields based on certain conditions or user inputs.
    • Code Example:
      # forms.py
      from django import forms
      from .models import MyModel
      
      class MyDynamicForm(forms.ModelForm):
          class Meta:
              model = MyModel
              fields = ['name', 'email']
      
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
              if some_condition:
                  self.fields['additional_field'] = forms.CharField()
      
  10. Django formsets with ModelForm:

    • Description: Use formsets to handle multiple forms for model instances in a single view.
    • Code Example:
      # views.py
      from django.forms import modelformset_factory
      from .forms import ProductForm
      from .models import Product
      
      ProductFormSet = modelformset_factory(Product, form=ProductForm, extra=3)
      
      def manage_products(request):
          if request.method == 'POST':
              formset = ProductFormSet(request.POST, queryset=Product.objects.all())
              if formset.is_valid():
                  formset.save()
          else:
              formset = ProductFormSet(queryset=Product.objects.all())
      
          return render(request, 'manage_products.html', {'formset': formset})
      
  11. Django form rendering for model forms:

    • Description: Render ModelForms in templates using the {% for field in form %} loop to display form fields.
    • Code Example:
      <!-- templates/manage_products.html -->
      <form method="post" action="{% url 'manage_products' %}">
          {% csrf_token %}
          {{ formset.management_form }}
          {% for form in formset %}
              {{ form.as_p }}
          {% endfor %}
          <input type="submit" value="Submit">
      </form>