import magic
from django import forms
from django.core.exceptions import ValidationError
from django.template.defaultfilters import filesizeformat
class RestrictedFileField(forms.FileField):
def __init__(self, *args, **kwargs):
self.max_size = kwargs.pop("max_size", None)
self.content_types = kwargs.pop("content_types", None)
self.read_bytes = kwargs.pop("read_bytes", 2048)
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
file = super().clean(data, initial)
if not file:
return file
if self.max_size is not None and file.size > self.max_size:
raise ValidationError(
"File is too large (%(size)s). Maximum size is %(max)s.",
code="file_too_large",
params={
"size": filesizeformat(file.size),
"max": filesizeformat(self.max_size),
},
)
if self.content_types:
head = file.read(self.read_bytes)
file.seek(0) # rewind so storage reads the full file later
detected = magic.from_buffer(head, mime=True)
if detected not in self.content_types or (
file.content_type and file.content_type not in self.content_types
):
raise ValidationError(
"Unsupported file type: %(type)s.",
code="unsupported_type",
params={"type": detected},
)
return file
from django import forms
from .fields import RestrictedFileField
MB = 1024 * 1024
ALLOWED_TYPES = [
"application/pdf",
"image/png",
"image/jpeg",
]
class DocumentUploadForm(forms.Form):
title = forms.CharField(max_length=120)
attachment = RestrictedFileField(
max_size=5 * MB,
content_types=ALLOWED_TYPES,
help_text="PDF, PNG or JPEG, up to 5 MB.",
)
def clean_title(self):
return self.cleaned_data["title"].strip()
from django.contrib import messages
from django.urls import reverse_lazy
from django.views.generic.edit import FormView
from .forms import DocumentUploadForm
from .models import Document
class UploadDocumentView(FormView):
template_name = "documents/upload.html"
form_class = DocumentUploadForm
success_url = reverse_lazy("documents:list")
def form_valid(self, form):
# File already passed size + MIME validation in the field's clean().
Document.objects.create(
owner=self.request.user,
title=form.cleaned_data["title"],
file=form.cleaned_data["attachment"],
)
messages.success(self.request, "Document uploaded.")
return super().form_valid(form)
upload_document = UploadDocumentView.as_view()
This snippet shows how upload validation belongs on a custom form field rather than scattered across views, so every form that accepts a document gets the same size and content-type checks for free. The core idea is that Django's forms.FileField already returns an UploadedFile in its clean(), and subclassing it lets extra rules run inside the normal validation pipeline, raising ValidationError that renders inline next to the widget.
In fields.py, RestrictedFileField accepts max_size and content_types in its constructor and stores them as instance state. Its overridden clean() first defers to super().clean() so the built-in required/empty handling stays intact, then returns early when the field is optional and empty. The size guard uses file.size and filesizeformat to build a human-readable message, which is friendlier than a raw byte count.
The important subtlety is MIME sniffing. The browser-supplied content_type is attacker-controlled and trivially spoofed, so RestrictedFileField reads the first read_bytes of the stream and passes them to python-magic, which inspects the actual file signature. After sniffing, file.seek(0) rewinds the pointer so downstream code and storage backends still read the whole file. Both the declared and the detected type are checked, closing the gap where a renamed .exe claims to be a PDF.
In forms.py, DocumentUploadForm wires the field with concrete limits — a 5 MB cap and an allowlist of PDF and common image types — demonstrating that policy lives in the form definition, not the field. Because the field is self-contained, the same configuration can be reused across multiple forms.
In views.py, upload_document is a thin FormView; by the time form_valid() runs, the file has already passed every check, so the view simply persists cleaned_data['attachment']. Note the trade-off: reading bytes for sniffing touches the upload in memory or temp storage, and very large files should be streamed rather than fully buffered. python-magic also depends on the system libmagic, a deployment consideration worth documenting. This pattern is the right reach whenever untrusted uploads must be constrained before they hit disk or a task queue.
Related snips
payload = {
sub: user.id,
iss: 'https://auth.example.com',
aud: 'codesnips-api',
exp: 15.minutes.from_now.to_i,
iat: Time.now.to_i,
JWT issuance and verification without common footguns
class Product(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
cost = models.DecimalField(max_digits=10, decimal_places=2)
margin = models.DecimalField(max_digits=5, decimal_places=2, blank=True)
Django model signals vs overriding save
class SignupForm
include ActiveModel::Model
include ActiveModel::Attributes
attribute :account_name, :string
attribute :email, :string
Shallow Controller, Deep Params: Form Object Pattern
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
Django URL namespacing and reverse lookups
#!/usr/bin/env bash
set -euo pipefail
export VAULT_ADDR="https://vault.internal:8200"
export VAULT_TOKEN="${VAULT_TOKEN:?missing VAULT_TOKEN}"
Secrets management with environment isolation and Vault
import { randomBytes, createHash } from "crypto";
import jwt from "jsonwebtoken";
import { RefreshTokenStore } from "./store";
const ACCESS_SECRET = process.env.ACCESS_SECRET!;
const ACCESS_TTL = "15m";
JWT access + refresh token rotation (conceptual)
Share this code
Here's the card — post it anywhere.