SyntaxStudy
Sign Up
Django Rendering Forms and Handling File Uploads
Django Beginner 1 min read

Rendering Forms and Handling File Uploads

Django forms can be rendered in templates in several ways. The simplest is {{ form.as_p }}, {{ form.as_ul }}, or {{ form.as_table }}, which render all fields wrapped in the corresponding HTML elements. For full control you can render each field individually: {{ form.title }} renders the widget, {{ form.title.label_tag }} renders the label, and {{ form.title.errors }} renders validation errors for that field. For file uploads you must add enctype="multipart/form-data" to the HTML form element. On the server side, the view must pass both request.POST and request.FILES to the form constructor. The model must have a FileField or ImageField, and Django handles storing the file and saving the file path to the database. The MEDIA_ROOT and MEDIA_URL settings control where uploaded files are stored and how they are served. Formsets let you work with multiple instances of the same form on a single page — for example editing all comments on a post at once, or uploading multiple files. Django provides formset_factory, modelformset_factory, and inlineformset_factory. Inline formsets are particularly useful for editing related objects on the same page as their parent, such as editing post images while editing the post.
Example
# blog/models.py — model with image upload
from django.db import models

class Post(models.Model):
    title     = models.CharField(max_length=200)
    body      = models.TextField()
    cover_img = models.ImageField(upload_to='posts/%Y/%m/', blank=True, null=True)


# blog/forms.py — form with file field
from django import forms
from .models import Post

class PostWithImageForm(forms.ModelForm):
    class Meta:
        model  = Post
        fields = ['title', 'body', 'cover_img']


# blog/views.py — handling file upload
from django.shortcuts import render, redirect
from .forms import PostWithImageForm

def post_create(request):
    if request.method == 'POST':
        # Must pass request.FILES for file uploads
        form = PostWithImageForm(request.POST, request.FILES)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.save()
            return redirect('blog:post-detail', pk=post.pk)
    else:
        form = PostWithImageForm()
    return render(request, 'blog/post_form.html', {'form': form})


# mysite/settings.py — media file settings
# MEDIA_ROOT = BASE_DIR / 'media'
# MEDIA_URL  = '/media/'

# mysite/urls.py — serve media in development
# from django.conf import settings
# from django.conf.urls.static import static
# urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)