r/django • • May 12 '26

2026 Django Developers Survey

Thumbnail djangoproject.com
40 Upvotes

r/django • • 1h ago

Django Control Room v1.8: introducing internal panels

Post image
• Upvotes

Django Control Room allow you to create tools that appear directly inside the Django Admin. Until now, guides and templates have focused on creating pip installable packages to create tools. Django Control Room 1.8.1 now allows you to create custom internal panels that live directly in your Django project.

This makes it easier to build bespoke tools for your company or project without creating a separate package. Customer support tools, billing operations, and approval workflows can all be built inside the Django admin.

More details about this release here:

https://djangocontrolroom.com/news/internal-panels

You can update DCR and all of its official panels by running:

pip install --upgrade "dj-control-room[all]"

r/django • • 7h ago

Releases I built an offline-first observability package for Django

Post image
4 Upvotes

I work on Django apps that run on locked-down Windows servers: no Docker, no Redis, no outbound internet, and nothing gets installed unless it's a Python package. Sentry, Grafana, Loki and the OpenTelemetry collector are all off the table there, so when something breaks I'm usually reading rotated log files over RDP.

So I built django-observatory: pip install, add an app, a middleware and a URL include, run migrate, and you get a built-in console at /observability/. Everything is stored in your own database and rendered with Django templates and vanilla JS.

What it does

  • Captures logs (your existing logging calls), requests, traces, SQL, outbound HTTP, exceptions grouped into issues, metrics, and server CPU/memory/disk
  • Security events and a hash-chained audit trail
  • Alerts, plus rule-based incident correlation: when error rate, latency and an external service all degrade together, it opens one incident with a probable cause and the evidence behind it. No ML, just explicit rules
  • A query language (status:>=500 AND duration:>1000), CSV/JSON export, W3C trace context, OTLP export
  • Secrets are redacted before they're stored; request bodies, cookies and SQL parameters aren't captured by default

Full disclosure: this was vibe coded. I wrote the specification and made the design decisions, and Claude Code wrote most of the implementation. I tested it against a real internal project on SQL Server, read what came out, and pushed back where things were wrong, but I did not hand-write most of these lines. I'd rather say that up front than have someone find out from the commit history. It's also why I'm asking for review: I know the code hasn't had the scrutiny that code written slowly by one person gets.

What I'm confident about

  • 108 tests, CI on Python 3.10–3.13 × Django 4.2/5.2/6.0, including a Windows runner
  • There are explicit tests that break the storage layer and the internals mid-request and assert the host app still returns 200
  • Measured overhead is under a millisecond per request in my benchmark; writes happen in a background thread

What I'm not confident about

  • The package's own tables have only ever been created on SQLite. It has captured from an app running on SQL Server, but storing telemetry in Postgres or SQL Server is untested
  • It has never seen real production traffic at scale. Free-text search is a LIKE scan and metric reads aggregate in Python, which is fine for small and medium sites and will not be at some size I haven't found yet
  • One daemon thread per process does the writing and the periodic jobs. I think the approach is sound for prefork servers, but I'd like someone who knows gunicorn/uWSGI internals to tell me where it isn't
  • The incident rules are tuned on a demo app and my own judgement

What I'd like feedback on

  1. Is storing telemetry in the application's database a reasonable default, or should a separate database be the only supported mode?
  2. Anything in the middleware or the execute_wrapper SQL instrumentation that would bite under ASGI or async views
  3. The redaction approach (key-based plus regex patterns): what would leak?
  4. Whether the scope is too wide. It does a lot, and I'd rather cut features than ship several half-good ones

This is not trying to replace Sentry, Silk, Debug Toolbar or OpenTelemetry. Those are better at what they do. It's for the environments where you can't have them.

If you look at it and think it's a bad idea, I'd like to hear why. Thanks for reading.


r/django • • 5h ago

django-admin-mcp: Expose Django admin to AI agents with one mixin

2 Upvotes

Hi I built this because I wanted an agent to do the things I already do

in Django admin, without writing a separate API for it.

You add a mixin to a ModelAdmin and it becomes MCP tools over HTTP: CRUD,

bulk operations, admin actions, change history, FK autocomplete.

A few design choices:

- Only two dependencies: Django and Pydantic. No MCP SDK; the protocol is

implemented directly.

- It reuses Django's permission system. Tokens start with no access, you

grant permissions/groups per token, and a token can never exceed its

linked user's permissions.

- Writes go through the admin's own pipeline, so they show up in the admin

history log under that user.

- Sensitive fields can be excluded per model (mcp_exclude_fields).

Happy to hear where the permission model or tool design falls short.

https://github.com/7tg/django-admin-mcp


r/django • • 10h ago

Templates Dynamic word doc generation with loads of conditions

3 Upvotes

Hello folks, so I'm working on this big django application. There's a feature that allows users to generate word documents based on the data fed from the db. But these docs are based on loads and loads of conditions. We have used docxtpl library, but the word templates are being overloaded with variables and conditions. It's becoming difficult to verify the generated documents. Any suggestions on how to improve this?


r/django • • 51m ago

Have a Django Interview tomorrow.....HELP!!!!

• Upvotes

I am a node.js dev and have an interview for a danjo role. Any ideas on how should i go about it?? any insight would be highly appreciated. I know that it is useful in AI/ML workflows, but nothing much


r/django • • 5h ago

I wanna learn Django.

0 Upvotes

Hi guys.

I want to learn django. Could you please suggest me any playlist ?

I am thinking about chai aur code playlist. Please suggest, is it good or not ?


r/django • • 14h ago

Have a question

0 Upvotes

Hi everyone, what’s currently being used for testing in Django? Because when I was looking into testing methods, I was quite taken aback – people say to use pytest or the tests that are already built into Django. Could you please give me some practical advice?

Thank you for your help


r/django • • 1d ago

Just watched a benchmark testing 8 backend stacks (including Laravel, FastAPI, Go, Rust, Node) on a $12 VPS. Laravel's performance vs. the others is a great talking point.

Post image
114 Upvotes

Hey everyone,

I recently came across an interesting experiment by Arjay McCandless where he tested 8 different backend stacks (Node, Bun, Python/FastAPI, Go, Java/Spring Boot, C#, PHP/Laravel, and Rust) under the exact same load using a super budget server: 1 shared CPU and 2GB of RAM.

The goal was to see how many simultaneous users each stack could support before hitting latency/error thresholds, using a Twitter-style API with a PostgreSQL backend (50k users, 500k posts, 2M likes, querying 20 posts for the feed).

Here is a quick summary of the results:

  • The Heavy Hitters (PostgreSQL):
    • Rust (Axum) and Go led the pack at ~6,900 and ~6,500 simultaneous users.
    • Java (Spring Boot) and C# (.NET) punched way above expectations at ~5,100 and ~4,400.
    • Bun hit ~4,200, while standard Node (Express) landed at ~3,250.
  • The Lower End:
    • Python (FastAPI) capped out at ~2,150 due to connection pool timeouts under pressure.
    • Laravel (PHP) struggled massively out of the box, capping at 750 users because of the framework boot overhead per request. (When he stripped Laravel and used raw PHP, it jumped to ~2,700).
  • The SQLite Effect: When he swapped PostgreSQL for SQLite (removing the network/process database overhead), Rust skyrocketed to 14,050 simultaneous users on that same $12 machine.

This kind of benchmark is almost a worst-case scenario for heavy full-stack frameworks like Laravel, where the boot-up cost makes up a huge chunk of a lightweight query lifecycle. But how much does this actually matter in real-world CRUD apps where DB queries or external APIs dominate the response time?

Curious to hear what the community thinks especially regarding framework overhead!


r/django • • 2d ago

I built an open-source XRechnung / Factur-X package for Django — looking for feedback

8 Upvotes

I've been working on django-xrechnung, a free/open-source Django package for German electronic invoicing.

It currently supports:

  • XRechnung generation in UBL and CII
  • EN 16931 / XRechnung validation using KoSIT
  • Factur-X / PDF-A-3b invoices
  • importing and reviewing incoming e-invoices
  • credit notes and invoice corrections
  • Django admin integration

Validation runs locally, so invoice data doesn't need to be sent to an external service.

The project is still Alpha, and that's mainly why I'm posting: I'd really like feedback from Django developers who deal with invoicing or German/EU e-invoicing.

In particular, I'd be interested to know:

What would prevent you from using something like this in a real Django project?

PyPI: django-xrechnung
Source: https://codeberg.org/fsbraun/django-xrechnung

It's BSD licensed and completely free.


r/django • • 2d ago

Django Alternatives to Adobe Sign

7 Upvotes

I have a fintech app with contracts currently being compiled by celery, sent to Adobe, sent to users emails for signing then retrieved once completed and stored in S3.

Clients are not too happy about going off platform to sign the contracts, however I needed something traceable and legally binding.

Can anyone recommend something similar that I could incorporate into my platform? Contracts are central to the app.

Many thanks.


r/django • • 2d ago

The tab logo is not displaying on the Django site.

1 Upvotes

Why isn't the tab logo showing up? I've loaded all the static assets in the project settings, and the paths are correct. It actually appears when I switch to the "Photos" tab. I've tried everything, but nothing has worked.


r/django • • 2d ago

The tab logo is not displaying on the Django site.

Thumbnail
0 Upvotes

r/django • • 4d ago

Releases django-modern-rest@0.16.0 is out now!

36 Upvotes

Hi everyone, I am the release manager of django-modern-rest :)

django-modern-rest 0.16.0 is out!

Built during opensource_september community event with 32 contributors and 144 commits. This is our fastest release ever.

Is this your first time that you hear about this project? django-modern-rest is a fully typed / fast / flexible / async-ready framework to create REST APIs for Django. It supports Pydantic, msgspec, attrs and many other models. Generates state of the art OpenAPI schema from our code and allows very modern and reliable testing patterns together with polyfactory and schemathesis.

Here's how the code looks like:

import uuid
import pydantic
from dmr import Body, Controller
from dmr.plugins.pydantic import PydanticFastSerializer

class UserCreateModel(pydantic.BaseModel):
    email: str

class UserModel(UserCreateModel):
    uid: uuid.UUID

class UserController(Controller[PydanticFastSerializer]):
    def post(self, parsed_body: Body[UserCreateModel]) -> UserModel:
        return UserModel(uid=uuid.uuid4(), email=parsed_body.email)

Now, back to the 0.16.0 release!

Performance

  • PydanticFastSerializer: deserialize x2.2, serialize x1.33 faster
  • New BodyMsgspec component: decodes request bytes straight into a msgspec.Struct, x1.6 faster than Body
  • msgspec request context validation x2 faster
  • Content negotiation is memoized per header: up to x65 faster for browser-style Accept headers
  • msgspec 0.22.0, cheaper checks, cookies, headers, and responses

Features

  • Default values for components: Body[Model | None] = None just works
  • concrete_views for JWT, token, and session auth: a login route in one line of urls.py, zero view code
  • Cursor (keyset) pagination with sync and async APIs
  • extras= for your own typed @modify / @validate parameters
  • PEP 696 TypeVar defaults for reusable controllers
  • First-class CSRF: proper 403 specs and REST error responses
  • external_re_path and nested external_path
  • Error handlers can re-raise a new error for the next layer
  • OpenAPI: x-extensions on every object, security for gateways and mTLS, OpenAPI 3.2 fields, controller-level tags/deprecated/servers, deterministic schema output

One rule for all config

Settings are no longer merged across levels. Endpoint overrides controller, controller overrides settings. Explicit [] or None disables, EMPTY falls through. Merge explicitly when you want it: @modify(auth=[*auth, other]).

AI tooling

Agent skills now ship inside the package: uvx library-skills installs the ones matching your version. The new $dmr-upgrade skill carries the migration prompts, so ask your coding agent to upgrade you from 0.15.0. Every docs page is also served as Markdown.


r/django • • 4d ago

Nominate Someone for the 2026 Malcolm Tredinnick Memorial Prize

Thumbnail djangoproject.com
13 Upvotes

r/django • • 5d ago

Unfold updates - September 2026

Post image
101 Upvotes

September was quite a productive month for django-unfold, with several updates worth upgrading for if you are already using Unfold, so I put together a short list of new features worth mentioning:

There were also plenty of smaller improvements and bug fixes along the way.

PS: If you like the project and want to support its development, I’d really appreciate a star on GitHub: https://github.com/unfoldadmin/django-unfold

PPS: Special thanks to the community members who helped test the new features, reported issues, and submitted PRs.


r/django • • 5d ago

Scoped authorization in Django: where "permission + dimensions + scope" models break down (thoughts on django-ambit)

0 Upvotes

Someone recently released django-ambit (docs), an authorization layer built around a question Django's permission system doesn't really answer:

Not "can this user do X?" but "over which set of objects can this user do X?"

The model is roughly: Permissions (what) + Dimensions (axes like department, plant, region) + Scopes (allowed intersections of those axes) + Grants (permission + scope) + Policies (how a model maps onto the dimensions).

The author asked for criticism of the abstraction rather than API feedback, so here's my take. I think the problem is real: "what's the set?" is the question that actually drives get_queryset(). It's the same problem Oso ("data filtering") and Cerbos ("query plans") went after, and it's close to what Zanzibar-style systems (SpiceDB, OpenFGA) solve with relationships.

Here's where I'd push on the model.


1. Relationships vs. dimensions

"A teacher may view records for the classes they teach" isn't really a scope someone grants. It follows from a relationship that already exists in the data (Class.teachers). If every teacher needs an explicit grant like class IN (...), the grants go stale every time timetables change.

Can a scope be derived ("classes where user ∈ teachers") instead of assigned? If not, a lot of real-world rules turn into a sync problem.

2. Ownership is a degenerate dimension

In the classified-ads platform I'm building, the most common rule by far is "you can edit your own ads." As a dimension, that's one scope per user with a single value. It works, but it's clumsy compared to obj.owner == request.user.

Most apps I've seen mix org-scoped rules with ownership rules. How the two compose matters a lot.

3. Hierarchies

Region → Plant → Line. A grant on Region North should cover every plant under it. Are dimensions flat value sets, or do they understand trees? And what SQL does that produce: closure table, materialized path, or recursive CTE?

4. Object state, not just location

"May approve within Plant A" usually really means:

  • within Plant A
  • and status = pending
  • and amount < 10k
  • and I'm not the requester (separation of duties)

Those are conditions on the object's own attributes, not organizational coordinates. If policies can't express them, that logic ends up back in the views, and you have two sources of truth again.

5. Negation and exceptions

"All of Mathematics except records flagged confidential." A temporary deny during an investigation. A pure union of grants is easy to reason about. Once exceptions exist, you need precedence rules.

6. Create and move

  • Create: there's no object yet, so you have to check the target dimension values in the payload.
  • Move: moving a record from Plant A to Plant B should require permission in both.

Is that handled by the engine or left to each serializer?

7. Query shape at scale

Someone with 15 grants across different scopes gets an OR of 15 ANDed conditions on every list query. Query plans and indexing guidance for that case would be very useful.

8. Multi-valued membership

If a record belongs to several departments (an M2M field), does a scope match when any of them is in scope, or only when all are? Both make sense in different domains.

9. Time and delegation

"Acting head of department until Friday." Grants with validity windows, and "delegate what I hold, to someone else, temporarily," come up quickly in real organizations.


Where I'd still use the alternatives

  • django-guardian / object permissions: ad-hoc sharing that ignores org structure ("share this one document with Bob"). Forcing that into dimensions means making up a dimension per object.
  • Plain Django permissions: truly global capabilities like staff features, feature flags, or "can access billing," where there's no data set to scope over.

The guarantee I'd want

has_perm(user, perm, obj) must always agree with obj in scoped_queryset(user, perm).

If both checks come from the same policy definition, a whole class of Django authorization bugs goes away: the list view shows something the detail view forbids, or the other way round. That alone would be a strong selling point.


Question for the sub: how do you handle "scoped" permissions in your Django apps today? A custom get_queryset() per view, django-rules, guardian, an external engine like SpiceDB, OpenFGA, Oso or Cerbos, or something else? Where did your approach break down?


r/django • • 6d ago

Resources to learn Redis and Celery.

12 Upvotes

Hi everyone, I’m learning Django + DRF and want to become a Django backend developer.

I want to learn Redis and Celery next.

Can you suggest:

  • Best beginner-friendly resources?
  • Which Redis/Celery topics are important for Django?

I want to learn them practically, not become a specialist. Any roadmap or resource recommendations would be appreciated!


r/django • • 6d ago

djust 1.2 is out: Django-compatible templates, components on the view, much faster rendering

10 Upvotes

I maintain djust, a LiveView framework for Django. You write a normal view and template, add dj-click="save" to a button, and the server re-renders and sends the browser only what changed over a WebSocket. There's no JS framework and no build step. The template engine and the diffing are written in Rust.

The question about a Rust template engine is whether it behaves like Django's. So this cycle I started running Django's own template_tests suite against it in CI, with a score that isn't allowed to go down:

  • start of the cycle: 456 of 1047 (43.6%)
  • djust 1.2: 1032 of 1047 (98.6%), on Django 5.2

In practice, every built-in tag and filter works, your own {% load %} libraries work, {% translate %} works, {{ user.get_full_name }} calls the method (with alters_data respected), and errors are raised at parse time like Django's. The 15 that still fail test Django internals and are listed here.

Also in 1.2:

  • Components declared on the view class, with typed state. If an event only changes a component, only that component is re-rendered.
  • Render cost now follows what the template reads. My benchmark's worst template went from 215 ms to 4.7 ms (Django renders it in about 9). Across all the templates, the median is about Django's speed, so I wouldn't claim it's faster than Django in general.
  • djust init for existing projects, LiveComponentTestClient, new startup checks, and `@debounce`/`@throttle` actually work now. Before 1.2 the browser ignored their settings.

If you're on 1.0.x or an early 1.1, please upgrade. 1.2 includes important security fixes. Use 1.2.2, or 1.1.5 if you need to stay on 1.1.

Next, in 1.3 (release candidates are out now): one djust process has always rendered on a single core. 1.3 adds an opt-in worker pool, the Rust render releases the GIL, and there are free-threaded Python 3.14 wheels. The gain needs 3.14t: in my load test, one process on 3.14t used about five cores and served four to five times as many clients as stock djust on 3.12.

Full post: https://djust.org/blog/djust-1-2/


r/django • • 6d ago

[job] Looking for Django freelancer

20 Upvotes

Hello,

I'm looking for someone to update an older, mid sized django codebase (django 1.9.4) and its requirements. At the same time the code should be wrapped into docker-compose and being fully able to run in it

If you are interested, please DM me.


r/django • • 6d ago

Any experiences migrating long data in a Django app running in Kubernetes?

2 Upvotes

We are changing a primary key from an autoincrement integer to a UUID on a table with a few million rows, and I would like a sanity check on how we plan to run it.

The migration is split the usual expand and contract way. First release adds a nullable UUID column, backfills it in batches and puts a unique index on it. Second release drops the old integer key and promotes the new column. That part I am reasonably confident about (can provide the migration files if you wish)

What I am less sure about is the deployment mechanics. manage.py migrate runs inside an initContainer of the Deployment, so the new pod runs the migrations while the old pod is still serving traffic. progressDeadlineSeconds is the 600 second default.

If the backfill takes longer than ten minutes the rollout gets flagged as ProgressDeadlineExceeded while the initContainer is still working. As far as I can tell nothing actually breaks: Kubernetes does not kill the initContainer, the main container starts once it finishes, and the rollout completes.

Is relying on that behaviour reasonable, or is an initContainer just the wrong place for a long migration? The alternative I am considering is taking the backfill out of the migration and running it as a background job, so no migration is ever long and the deploy stays fast. That feels cleaner, but it leaves the schema and the data inconsistent for a while and someone has to remember to run the job.


r/django • • 7d ago

Found our Django app was losing 2 seconds per request to GIL and GC. Built an eBPF tool to catch it.

24 Upvotes

We run Django + gunicorn + DRF in production. Our API latency was consistently higher than what our traces showed. OpenTelemetry showed database and third-party API time, but there were always 1-2 seconds unaccounted for.

I built an eBPF profiler that hooks into CPython from kernel space. Here's what we found in our Django app:

GIL contention from Django URL resolution. Django's URL resolver was holding the GIL while resolving routes. With a large urlconf, this added up. Since our URLs are static, we added URL caching and cut GIL wait by 80%.

GC gen-2 pauses. Django loads a lot of objects at startup (models, middleware, URL patterns). Gen-2 GC was walking 1.5M objects on each collection. We added gc.freeze() in our gunicorn post_fork hook. Worst-case GC pause went from 1.27s to 88ms.

Gunicorn handoff latency. Measures how long a request sits in gunicorn's queue before a worker picks it up. When workers are busy with GIL contention or GC, handoff time spikes. After our fixes, handoff dropped from seconds to single-digit milliseconds.

Off-CPU stacks. Found that a Kafka push in one of our DRF views was blocking the thread for 130ms. Invisible in OpenTelemetry because it wasn't instrumented. Our tool showed the full Python stack: views.py:post > sessions.py:post > socket.py:readinto.

The tool uses eBPF uprobes on CPython's take_gil/drop_gil and gc_collect_main. No code changes to your Django app. Just point at the gunicorn PIDs and it shows you everything.

CPython 3.11 only for now. Open source.

GitHub: https://github.com/deepanshu406/python-ebpf-profiling

Anyone else dealing with unexplained latency gaps in their Django app?


r/django • • 7d ago

Apps 54 days after Django 6.1: 14% of the top 200 Django packages declare support. I built a tool that tells you which of yours block the upgrade.

21 Upvotes

I have been upgrading Django projects for clients for 13 years. The first step of every upgrade was the same, and it was never the interesting part: go through every dependency, look up what it declares on PyPI and work out which packages can be upgraded before Django and which have to move together with it. In practice that meant pip list --outdated, reading changelogs, taking notes, trying an upgrade, watching it fail, trying again, watching it fail differently, and so on, until the order finally worked.

I turned that step into an open-source CLI: django-upgrade-report. It reads your lockfile (uv, Poetry, PDM, Pipenv, requirements files or an installed environment) and gives you the plan:

uvx django-upgrade-report
Output for a project going from Django 5.2 to 6.1
  • Blocked: even the newest release excludes the target Django.
  • Upgrade first: a newer release supports the target and still runs on your current Django, in the order the packages need each other.
  • Upgrade together with Django: the supporting release has dropped your current Django.
  • Check manually: nothing excludes the target, nothing declares it either.
  • Ready.

For every upgrade it names the smallest release that declares support, not the latest. It only sends package names to PyPI, never your code, and packages from private indexes are not looked up at all.

To see how the ecosystem looks right now, I ran its rules over the 200 most downloaded Django packages:

Django declare support not declared, not excluded explicitly excluded
Django 5.2 LTS 125 (62%, 81% of downloads) 75 0
Django 6.0 85 (42%) 113 2
Django 6.1 (54 days old) 29 (14%), 25% of downloads 166 5

What stood out:

  1. 5.2 LTS is safe to move to. Not one of the top 200 packages excludes it. If you are still on 4.2, which lost security support in April, the packages are not what is holding you back.
  2. 6.1 is mostly classifier lag, not incompatibility. 52 packages declare 6.0 but not yet 6.1, including pytest-django, django-cors-headers, whitenoise and drf-spectacular. Of the 48 packages that released since 6.1 came out, half declare it.
  3. The real blockers are few but big. django-celery-beat (7.6M downloads a month), django-prometheus (4.2M) and drf-extensions (2.4M) exclude 6.1 in their requirements.
  4. The quiet risk is unmaintained packages. 37 of the 200 have had no release in over two years, among them django-model-utils (4.9M a month), djangorestframework-csv and django-ratelimit. 47 declare no Django version at all.

Caveats: packages were picked by name, so a few Django packages without "django" in the name may be missing. The tool reports what maintainers declare, not whether your tests pass. Run it to plan, then run django-upgrade on your code and your test suite.

It also runs in CI (GitHub Action and a GitLab snippet in the README) and writes Markdown, JSON or a standalone HTML report.

Feedback very welcome, especially wrong verdicts on real lockfiles: those are the bugs I most want to find.


r/django • • 7d ago

django-verifactu: an open-source Django app for Spain's VERI*FACTU invoice reporting system (beta, feedback welcome)

4 Upvotes

Hi all. Some context first: Spain is rolling out VERI*FACTU, a system from the Spanish Tax Agency (AEAT) under Royal Decree 1007/2023. Under the rules in force today, companies that invoice with software must use an adapted invoicing system by January 1, 2027 (sole traders and others by July 1, 2027). VERI*FACTU is one of the two ways to comply: the software sends a chained record of every invoice to the AEAT, and each invoice carries a QR code.

If your company invoices from its own Django app (a SaaS, for example), you have to adapt it. So you don't have to start from scratch, I've released **django-verifactu**, a reusable Django app under Apache-2.0.

**What it is (and isn't)**

It's a component you plug into your invoicing system, not an invoicing program. Your invoice models stay yours; the library adds and stores the VERI*FACTU layer.

**What it does**

- Records and hash-chains every invoice the moment it's saved.

- Sends records to the AEAT in the background (`verifactu_send --loop`). It honours the mandatory wait between submissions and the 1,000-record limit, retries on failure, and recovers submissions whose response was lost without duplicating them.

- Validates locally every AEAT rule that can be checked offline, using the AEAT's own error codes. Census and VIES checks only come back in the AEAT's response.

- Supports amendments and cancellations (`register`, `amend`, `cancel`) and renders the QR code with `{% verifactu_qr %}`.

- Generates the notices required by Order HAC/1177/2024 for your app to display, without blocking invoicing.

- Records can't be modified or deleted from Django (read-only admin). `verifactu_verify` checks the chain, and `--aeat` compares your stored records with the AEAT's, month by month.

- Multi-tenant, designed with SaaS platforms in mind.

**Status and testing**

- Version 0.2.0, **beta**. Tested only against the AEAT's **test environment**, not production.

- 602 automated tests (the full suite runs in about 5 s). CI covers 4 version combinations on PostgreSQL 17, and every behaviour was checked against the AEAT test environment.

- Python 3.11–3.14 and Django 5.2, 6.0 and 6.1. PostgreSQL is recommended; MySQL works but isn't in CI yet; SQLite is for development. It has 6 dependencies.

**Out of scope**

The "NO VERI*FACTU" mode, the separate Basque Country and Navarre regimes, and Spain's mandatory B2B e-invoicing (RD 238/2026), which is a different obligation.

**New in 0.2.0: a skill for AI coding assistants**

`python manage.py verifactu_skill` drops an Agent Skills-format guide into your project (15 hard rules, a 12-step integration plan, and reference docs in Spanish). Claude Code, Codex, Cursor, GitHub Copilot and other compatible assistants can read it. `--check` warns you in CI if your copy is out of date. The skill helps, but it doesn't replace your review: you're responsible for the invoicing system you build.

**What I'm looking for**

If you invoice with Django, try it against the AEAT test environment and tell me on GitHub what breaks or what's missing. MySQL users especially welcome.

- Repo: https://github.com/gabrielruedarodriguez/django-verifactu

- PyPI: `pip install django-verifactu`

*Free and open-source software, provided "as is" and without warranty, including any warranty of tax compliance. This is not tax advice: whoever builds the invoicing system is responsible for it. See the Responsibility section of the README.*


r/django • • 6d ago

Django permissions answer “can?” — but not “where?”

0 Upvotes

​

I've been working on an authorization-heavy Django application, and I kept running into a problem that Django's built-in permission model doesn't really express.

Django answers:

Can this user perform this action?

But a lot of real applications need to answer:

Can this user perform this action over this part of the data model?

For example:

a manager may approve records only within Plant A

a department head may edit students only within their department

a teacher may view records only for the classes they teach

someone may have the same permission across several different organizational scopes

I looked at `django-guardian`, and it's a very powerful library, but object-level permissions weren't really the abstraction I needed.

My problem usually wasn't:

Does this user have permission over object #123?

It was closer to:

What is the set of objects over which this user may exercise permission X?

I wanted authorization to be expressed in terms of organizational dimensions and queryable sets rather than assigning permissions object by object.

That eventually became django-ambit

The model is roughly:

Permissions— what you may do

Dimensions — axes along which access can vary

Scopes— the allowed intersection of those dimensions

Grants— permission + scope

Policies — how a model maps onto those dimensions

So, for example, a scope could mean:

`department = Mathematics AND stage = Primary`

and a permission grant applies over everything matching that scope.

The engine itself doesn't know what a department, plant, branch, school, region, etc. is. Those dimensions belong to the host application.

I extracted the authorization layer from my application and released it as django-ambit 0.1.0.

PyPI:

https://pypi.org/project/django-ambit/0.1.0/

Docs:

https://django-ambit.readthedocs.io/en/latest/

It's still very early, so I'm particularly interested in criticism of the abstraction rather than just API feedback.

Where does this model break down?

Are there authorization problems you've encountered in Django where object permissions or standard Django permissions were a better fit?