Test a Django endpoint's public and private responses

A permission test that checks only "200 OK" can miss a sensitive field added to an otherwise public response. Verify the exact shape and contents that each audience is allowed to receive.
Each audience has an independently tested response-field contract.
Write a response matrix
Assume a toy project-detail endpoint deliberately exposes only id and title publicly. Its owner response may also contain internal_notes. Other authenticated users receive the public representation.
from django.test import TestCase
class ProjectVisibilityTests(TestCase):
def test_public_payload_omits_private_notes(self):
project = make_project(
title="Fixture project",
internal_notes="private fixture marker",
)
response = self.client.get(f"/api/projects/{project.pk}/")
self.assertEqual(response.status_code, 200)
payload = response.json()
self.assertEqual(set(payload), {"id", "title"})
self.assertNotIn("private fixture marker", response.content.decode())
def test_owner_payload_contains_expected_notes(self):
owner = make_user()
project = make_project(owner=owner, internal_notes="owner-only")
self.client.force_login(owner)
response = self.client.get(f"/api/projects/{project.pk}/")
self.assertEqual(response.json()["internal_notes"], "owner-only")
When the public and owner serializers differ, include a regression fixture for newly added model fields so private defaults cannot silently enter the public representation. The factories above are application-specific fixtures, not built-in Django functions. Implement them using the toy application's real model fields and include the corresponding endpoint implementation.
Exact key assertions are useful when accidental extra fields are a meaningful regression. They are less suitable for APIs designed to add harmless fields freely. Choose the strictness from the sensitivity of the representation, not from a universal testing preference.
Test the other user's path
Create a second user, authenticate as that user and request the owner's project. Confirm the expected public representation or denial, according to the product policy. Check list endpoints too: a detail-only rule does not prove a public list serializer excludes private data.
Repeat the checks for update and delete operations if they exist. A response can conceal internal_notes while still accepting a write to that field. Read and write permissions need separate assertions.
Keep a recognizable synthetic secret marker in the fixture so nested objects and error responses can also be searched for leaks. Avoid using real customer data to make a test feel realistic.
Authentication helpers intentionally bypass parts of a real login flow. They are useful for authorization tests, but they do not establish that cookies, CSRF settings or session expiry work in a deployed browser.
The Nirogidhara case study offers related role-sensitive application context. Django's testing tools describe the client and login helpers.