Export every Django URL to Postman, including forms and CSRF
How to turn a plain Django project (function views, class-based views, ModelForms, JsonResponse) into a Postman collection, and make CSRF work in Postman.
Plenty of Django APIs don't use Django REST framework: function views returning JsonResponse, FormViews behind a login page, a few json.loads(request.body) endpoints added over the years. There's no serializer for OpenAPI tools to read, so getting them into Postman usually means doing it by hand.
routeman reads plain Django as well as DRF. Here's what that looks like.
Listing every URL Django serves
The first question is often "which URLs does this project actually have?" routeman routes resolves the whole URLconf (every include(), path() and re_path()) and prints methods and body fields:
$ routeman routes
GET /accounts/profile/{pk}/edit/
POST /accounts/profile/{pk}/edit/ form: first_name, last_name, avatar
PUT /accounts/profile/{pk}/edit/ form: first_name, last_name, avatar
GET /accounts/search/
POST /accounts/signup/ json: email, password, name
The admin and static file routes are left out on purpose.
The views behind that output
@require_POST
def signup(request):
data = json.loads(request.body)
user = User.objects.create_user(
username=data["email"], email=data["email"],
password=data["password"], first_name=data.get("name", ""),
)
return JsonResponse({"id": user.id}, status=201)
def search(request):
q = request.GET.get("q")
page = int(request.GET.get("page", 1))
...
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ["first_name", "last_name", "avatar"]
class ProfileUpdateView(LoginRequiredMixin, UpdateView):
model = Profile
form_class = ProfileForm
Here's what routeman worked out:
@require_POSTmeans Signup is POST only.json.loads(request.body)means a JSON body, and thedata["email"]/data.get("name")accesses give the fields. The example body is{"email": "user@example.com", "password": "Str0ngPassw0rd!", "name": ""}.request.GET.get("q")andint(request.GET.get("page", 1))become query parametersq(string) andpage(integer).UpdateViewwith aModelFormgives GET, POST and PUT requests withmultipart/form-data(because of theImageField),first_name=John,last_name=Doe, anavatarfile picker and a field table showing which fields are required.<int:pk>becomes{{profile_id}}, named after the model.
Making CSRF work in Postman
Postman users hit "CSRF verification failed" constantly with Django. Django sets a csrftoken cookie on a GET response and expects it back in the X-CSRFToken header on unsafe methods. Postman keeps the cookie but never copies it into a header.
The collection routeman generates fixes this in two parts:
- A collection-level test script runs after every response:
const csrf = pm.cookies.get('csrftoken'); if (csrf) { pm.collectionVariables.set('csrftoken', csrf); } - Form requests send the header
X-CSRFToken: {{csrftoken}}.
So the workflow is to send any GET request once (the login page, or the GET of the same form), then send your POST. Postman also needs the Referer or Origin to match for HTTPS sites, so when you test a deployed site, use an environment whose base_url matches CSRF_TRUSTED_ORIGINS.
Generating it
$ pip install routeman
$ routeman generate # settings from manage.py
$ routeman generate -a config.settings.dev # or name them
If the project also has DRF endpoints, they're included in the same collection, with DRF's auth (JWT/Token) on those requests. See the DRF guide for details.
Tips for older Django projects
- Settings that need environment variables: keep them in
.env, which routeman loads before importing, or pass--env-file. - Django 3.2 LTS is supported, as are 4.x, 5.x and 6.
- Exclude legacy or internal prefixes with
-x '^/legacy/'. - Requests built from view code are marked as inferred in their description. Double-check them, or add a form to the view for exact types.
Read more on the Django page.
Try routeman on your project
$ pip install routeman
$ routeman generate