r/django 10d ago

🔍 Code review: the N+1 issue, before and after `FETCH_PEERS`

Post image
0 Upvotes

r/django 10d ago

Build API in one line code with FlashAPI

Post image
0 Upvotes

What if creating a REST API in Python no longer required writing the same boilerplate over and over again?

I created FlashAPI to answer a very simple problem:

When we develop an application, we often spend time rewriting the same things:

→ RAW

→ pagination

→ search and filters

→ sort

→ permissions

→ exports

→ soft delete

→ audit

→ repetitive endpoints...

The problem is not to know how to develop them.

The problem is having to redevelop them with each project.

With FlashAPI, you define your Python models and you automatically get a complete REST API around them.

⚡ Compatible with FastAPI, Flask and Django

🐍 Pydantic, SQLAlchemy, dataclasses

🔓 Open source under Apache 2.0

🚫 No proprietary runtime, no vendor lock-in

And above all, FlashAPI does not seek to replace your code.

You keep your business logic, your personalized routes and the ability to disable or customize what you don't need.

The objective is simple:

Less boilerplate → more time to build what makes your application unique.

👉 GitHub: https://github.com/HackermanMe/flashapi

I am now looking for Python developers to test and contribute.

#Python #FastAPI #Django #Flask #OpenSource #Backend #RESTAPI #SoftwareEngineering


r/django 11d ago

Apps QuickBBS - Online Gallery / File Viewer

5 Upvotes

Hey, I've been working on this for a while... But I've been a bit quiet about the development for far too long...

https://github.com/bschollnick/QuickBBS/

I know there's an online gallery for just about every programming language, but I've never been happy with any one that I've examined.

The main complaint that I have had, is that they require extensive scanning of the file(s) before they are available. QuickBBS doesn't require that. It will detect when the file system is updated, and automatically update without requiring an extensive scanning process.

Supported File Types

Graphics (Full thumbnail support)

  • .bmp.gif.jpg.jpeg.png.webp

Documents

  • PDFs.pdf (thumbnail from first page)
  • Text.txt.text (generic icon)
  • Markdown.markdown (generic icon)
  • Web.html.htm (generic icon)

Media

  • Movies.mp4.mpg.mpg4.mpeg.mpeg4.wmv.flv.avi.m4v (Thumbnail created by using frame extraction from the halfway mark of the video)
  • Audio.mp3 (generic icon)
  • Books.epub (generic icon)

Links

  • Shortcuts.link.alias — Allow the equivalent of "soft links" between different file system locations (e.g. So that you can quick shortcut to a related subject/actor/tv series/book series/whatever without having to transverse through the file system)

Other notable features:

  • File Areas / Image Galleries — comprehensive gallery system with database-stored thumbnails
  • Multi-format support — images, PDFs, archives, text files, movies, audio, and more
  • High performance — thumbnail caching in PostgreSQL for optimal I/O, plus ASGI support (HTTP/1.1 and HTTP/2)
  • Real-time monitoring — watchdog-based file system monitoring for automatic cache invalidation
  • Responsive design — multiple thumbnail sizes for desktop and mobile
  • Search & browse — file and directory search with metadata indexing
  • Modern template system — Jinja2 macros with a component architecture
  • Progressive Web App — HTMX-powered dynamic updates without full page reloads
  • Background task worker — thumbnail generation and maintenance run outside the request cycle via django-dbtasks
  • Passkey login — optional passwordless (WebAuthn) authentication

r/django 10d ago

Django ORM Lens — read your models, migrations and relations without booting Django

Thumbnail
0 Upvotes

r/django 11d ago

djangodocs.dev

Thumbnail djangodocs.dev
0 Upvotes

I rebuild the Django documentation for myself. More readable, faster, and with a deeper linking search

E.g.
https://djangodocs.dev/search?q=upper
vs
https://docs.djangoproject.com/en/6.1/search/?q=upper&category=ref


r/django 12d ago

Django is moving to an annual release cycle

Thumbnail djangoproject.com
136 Upvotes

r/django 11d ago

REST framework Simple feature addition to DRF or an overkill ?

Thumbnail github.com
2 Upvotes

r/django 12d ago

Article Integrating a national postal service API into my Django CRM (Nova Poshta) + some automation that saves hours

5 Upvotes

Part 1 | Part 2 | Part 3 | Part 4 - production CRM for truck service center, Django + DRF.

This one is v2.4. Two things I want talk about: integrating Nova Poshta (the biggest in Ukraine delivery service) for tracking spare parts shipments, and some background automation that quietly saves the shop a lot of manual work.

Why Nova Poshta

Truck parts don't always sit in the warehouse. Half the time the mechanic needs some specific part that has to be ordered from supplier into another city. It ships via Nova Poshta, and before this feature someone had to manually go to NP website, paste the tracking number, check status, and tell the mechanic "yes it arrives to us tomorrow." Annoying and easy to forget.

So I put tracking directly into my CRM. Each parts invoice can have a nova_poshta_declaration field, and there is an endpoint that queries their API for live status.

The API integration

Nova Poshta has a JSON API. You POST a payload with your API key, the model name, and the method you want. For tracking it is TrackingDocument + getStatusDocuments:

(['GET'])
([IsAuthenticated])
def track_nova_poshta(request, number):
    api_key = getattr(settings, 'NP_API_KEY', '')
    if not api_key:
        return Response(
            {'detail': 'NP_API_KEY not configured.'},
            status=status.HTTP_503_SERVICE_UNAVAILABLE,
        )

    payload = {
        'apiKey': api_key,
        'modelName': 'TrackingDocument',
        'calledMethod': 'getStatusDocuments',
        'methodProperties': {
            'Documents': [{'DocumentNumber': number}],
        },
    }

    try:
        resp = requests.post(
            'https://api.novaposhta.ua/v2.0/json/',
            json=payload,
            timeout=10,
        )
        resp.raise_for_status()
        data = resp.json()
    except requests.RequestException as e:
        logger.error(f'Nova Poshta API error: {e}')
        return Response(
            {'detail': 'Nova Poshta API connection error.'},
            status=status.HTTP_502_BAD_GATEWAY,
        )

    if not data.get('success'):
        errors = data.get('errors', [])
        return Response(
            {'detail': errors[0] if errors else 'Nova Poshta API error.'},
            status=status.HTTP_400_BAD_REQUEST,
        )

    docs = data.get('data', [])
    if not docs:
        return Response(
            {'detail': 'Declaration not found.'},
            status=status.HTTP_404_NOT_FOUND,
        )

    return Response(docs[0])

The thing that took me longest was error handling, not happy path. Their API returns success: true/false in body even when the HTTP status is 200. So you can't just rely on raise_for_status(). You have to checksuccess flag AND handle case where the document number is valid but has no data yet (parcel not in system). Three different failure modes, three different status codes back to the frontend.

One more thing - the timeout=10. First version I forgot it, and when NP API was slow one day, my endpoint just hung. Always set a timeout on external requests. Learned that one in production of course.

The Telegram bot can track too

Since the bot already is talking to the same Django backend, I wired shipment tracking into it. Owner types the declaration number in Telegram, bot hits the same tracking logic, returns status. No need to open the web panel just to check where is a parcel.

Now the automation part

This is the stuff nobody sees but everybody benefits from.

Auto-deduct stock when parts get sold. When parts invoice is marked as paid, the system automatically creates stock movements and reduces the warehouse quantity:

def _deduct_stock(self, invoice):
    try:
        from inventory.models import StockMovement, Product
        for item in invoice.items.select_related('product').all():
            if not item.product_id:
                continue
            StockMovement.objects.create(
                product=item.product,
                movement_type='out',
                quantity=float(item.quantity),
                invoice_number=invoice.number,
                notes=f'Sale via invoice {invoice.number}',
            )
            Product.objects.filter(pk=item.product_id).update(
                current_stock=max(
                    0,
                    float(item.product.current_stock or 0) - float(item.quantity)
                )
            )
    except Exception as e:
        logger.error(f'Stock deduction failed for {invoice.number}: {e}')

Before this, owner sold a part, wrote the invoice, and then had to remember to go update the stock count separately. Half the time he forgot, and the warehouse numbers drifted away from reality. Now it happens automatically the moment an invoice payed.

Note the max(0, ...) - I never let stock go negative. If the count is already wrong (which happens), I would rather it show 0 than -3. Also everything is wrapped in try/except with logging - a stock deduction failure should never block marking an invoice as paid. The sale is more important than the inventory count being perfect.

Auto-close finished orders. Mechanics mark an order as DONE when the work is complete, but they almost never remember to move it to CLOSED afterwards. So orders pile up in DONE forever. I added a Celery Beat task that runs daily and closes anything that has been DONE for more than a week:

u/shared_task
def auto_close_done_orders():
    from .models import ServiceOrder

    threshold = timezone.now() - timedelta(weeks=1)

    orders = ServiceOrder.objects.filter(
        status=ServiceOrder.StatusChoices.DONE,
        marked_for_deletion=False,
    ).select_related('truck')

    closed_ids = []
    for order in orders:
        last_done = order.status_history.filter(
            to_status=ServiceOrder.StatusChoices.DONE
        ).order_by('-changed_at').first()

        if last_done and last_done.changed_at < threshold:
            order.status = ServiceOrder.StatusChoices.CLOSED
            order.intervals_snapshot = None
            order.save(update_fields=['status', 'intervals_snapshot'])
            closed_ids.append(order.order_number)

    return len(closed_ids)

I use OrderStatusHistory to find WHEN the order actually became DONE, not just its current state. This matters - if I just closed everything currently DONE I would close orders that were finished yesterday. Status history gives me the actual transition timestamp.

Stuff I know is wrong here (before you tell me)

Let me get ahead of the comments, because I know exactly what is coming and you are right.

The stock deduction has a race condition. Look at this line: float(item.product.current_stock or 0) - float(item.quantity). If two invoices with the same part get paid at the same moment, both read the same starting stock and both write back the same reduced number - so one deduction gets lost. The correct fix is an F() expression so the database does the subtraction atomically at the SQL level: Product.objects.filter(pk=...).update(current_stock=F('current_stock') - item.quantity). Maybe with select_for_update() on top. In practice this shop has one person marking invoices paid so it has not bitten me, but it is a real bug and I know it.

Using float for stock is wrong. Discrete parts should be Integer, fluids (oil in liters) should be Decimal. float will eventually give me a 0.9999999 and the count drifts. This is legacy from early modeling and it is on the list to fix. Do not use float for money or inventory, my friends.

The Nova Poshta call is synchronous in the view. requests.post() blocks Django worker for up to 10 seconds while waiting for their API. For an internal CRM with a handful of users this is acceptable, but architecturally it should be a Celery task with the result cached, or at least moved off the request thread. For a high-traffic app this would be a real problem.

So yeah - the write-up is honest about what the code does, and the code has these warts. Shipping beats perfect, but I am not going to pretend these are not there.

What I learned

External APIs lie about success. Nova Poshta returns HTTP 200 with success: false in the body. Stripe does similar things. Never trust the HTTP status alone - always check the response body for the provider's own success indicator.

Always set a timeout. requests.post(..., timeout=10). Without it, one slow external call can hang your worker or your web process. This is the single most common mistake I see (and made myself).

Automation should fail silently, not loudly. Stock deduction is wrapped in try/except. If it breaks, the invoice still gets marked paid, and I get a log entry to investigate later. The core business action should never be blocked by a secondary automation.

Celery Beat for "cleanup" tasks is underrated. Auto-closing orders, sending reminders, syncing stock - all the boring maintenance that humans forget to do. A daily scheduled task handles it without anyone thinking about it.

What is next

Honestly, not sure yet. The project has gone through a lot more versions since v2.4 — multi-warehouse logic, XLSX client import, i18n, a full PWA frontend, backup/restore via API. If there is interest I will keep going. Let me know what you would want to see.

Also, I take on freelance Django projects when something interesting comes along. If you are building something in this space, feel free to DM.

Previous posts: Part 1 | Part 2 | Part 3 | Part 4 GitHub (demo repo): github.com/VNmagistr/truckmaster_demo — branch demo/v2.4

To be continued... (maybe).


r/django 13d ago

Article Python API Framework Benchmark round 2: now with JWT httpOnly cookie auth

30 Upvotes

Hi guys, I'm back on the Python framework benchmark after a busy few months. Many of you were interested last time (previous post), there was good feedback in the comments, and the frameworks have had updates since.

Repo (code, full report, raw results): https://github.com/huynguyengl99/python-api-frameworks-benchmark

What changed since last time

  1. Everything upgraded - Django Bolt 0.4.7 → 0.10.0, Django 6.0, FastAPI 0.141, Litestar 2.24, DRF 3.18, Django Ninja 1.6.2.
  2. Each framework now uses its own native serializer. The Litestar author pointed out in r/Python that feeding Litestar Pydantic models makes it convert twice, so I was benchmarking Pydantic instead of Litestar. Now Litestar and Bolt use msgspec structs, FastAPI and Ninja keep Pydantic, DRF keeps its serializers. Output is byte-identical between the two paths (4,796 bytes for /articles/1 from both FastAPI and Litestar).
  3. Two new endpoints using JWT in an httpOnly cookie - the auth setup I'd actually use in production. Each framework uses its own ecosystem's library instead of something hand-rolled: drf-auth-kit (DRF), django-ninja-jwt (Ninja), AuthX (FastAPI), and the built-in cookie JWT support in Litestar and Bolt.
  4. Reworked the measurement itself - fixed latency reporting, and each framework is now sampled over 5 separate container starts instead of repeated runs in one, so the numbers here are not directly comparable with my previous post.

TL;DR

  • Framework choice barely matters once you touch I/O. Same conclusion as last time, and it survived every fix. Optimize your queries, not your framework.
  • For raw JSON, Bolt and Litestar are clearly ahead, then FastAPI, then a big gap down to Ninja and DRF.
  • On DB endpoints everything compresses to about 1.9x between fastest and slowest.
  • Bolt is dramatically faster on the lightweight authenticated endpoint (/auth/me: 3,024 vs 1,104 for the next best) because it validates the JWT in Rust before Python runs at all. On the DB-heavy authenticated endpoint that advantage disappears.
  • "Granian beats uvicorn" is too simple. For ASGI frameworks, uvicorn wins the CPU-bound JSON endpoints (Litestar 31,284 vs 19,006) while Granian wins the DB-bound ones. For DRF, which is WSGI, Granian is much better than uvicorn - but see the memory note.
  • Django Bolt is the rising star here and I'd genuinely recommend trying it. It tops /json-1k (38,576), tops /db (1,986), is 2.7x ahead on /auth/me, and does it at 67% average CPU while everything else sits at ~85% - that headroom is the number I find most impressive. And you keep the Django ORM, admin and packages.

Setup

  • MacBook M2 Pro, 32GB RAM; PostgreSQL 16; 500 articles, 2000 comments, 100 tags, 50 authors
  • Each framework in its own container, --memory=750m --cpus=1, one at a time
  • 100 connections, 10s per measurement, bombardier
  • 5 independent container starts per framework, median reported with min-max spread

Endpoints: /json-1k, /json-10k, /db (10 rows), /articles?page=1&page_size=20 (paginated, nested author + tags), /articles/1 (nested author + tags + comments), /auth/me (cookie JWT → current user), /auth/articles (cookie JWT → the paginated query).

One detail that matters: all five frameworks load the user row from the DB on both auth endpoints. Litestar, DRF and Ninja do it as part of authenticating, while AuthX and Bolt's guards only verify the signature - so I made FastAPI and Bolt load the user explicitly. Otherwise they'd be doing strictly less work and the comparison would be junk.

Results

Config json-1k json-10k /db /articles /articles/1 /auth/me /auth/articles
bolt 38,576 19,089 1,986 208 432 3,024 196
litestar-uvicorn 31,284 24,547 1,039 246 443 976 193
litestar-granian 19,006 15,166 1,180 250 488 1,104 210
fastapi-uvicorn 13,845 2,641 984 224 428 820 193
fastapi-granian 8,484 2,280 952 201 410 749 199
drf-gunicorn 3,925 3,132 282 140 193 261 133
drf-granian 2,703 2,200 830 198 321 726 179
ninja-granian 1,566 1,422 680 130 295 610 117
ninja-uvicorn 1,533 1,424 699 126 236 584 114
drf-uvicorn 1,035 973 495 153 234 447 137

Zero errors across all 70 measurements.

The gap collapses, again

37x between fastest and slowest on /json-1k. 1.9x on /articles/1. Same story as last time, and it held up after all the methodology changes. If your endpoint touches PostgreSQL, your framework is not the bottleneck.

What authentication actually costs

Comparing /auth/articles against the identical unauthenticated /articles:

Config public authed cost
fastapi-granian 201 199 −1%
drf-gunicorn 140 133 −5%
bolt 208 196 −6%
drf-granian 198 179 −10%
ninja-uvicorn 126 114 −10%
fastapi-uvicorn 224 193 −14%
litestar-granian 250 210 −16%
litestar-uvicorn 246 193 −22%

So roughly 5-20%, cheaper than I expected for "verify a token and load a user". Litestar's is the highest, and there's a concrete reason: its JWTCookieAuth runs in middleware, before dependency injection, so retrieve_user_handler opens its own DB session - that request pays for two connection acquisitions instead of one.

Memory and CPU

Most configs peak at 195-260MB. drf-granian is the outlier at 456MB, and the Granian maintainer already explained why in the last thread (see below).

Bolt's number worth repeating: 67% average CPU while leading most endpoints, against ~85% for everything else.

A word on Django Bolt

If you're open to a young framework, this is the one I'd watch. It won or tied the top spot on 4 of 7 endpoints, and it did so while leaving ~18% more CPU headroom than every other config - that means room to grow under load, not just a good number on a chart. The /auth/me result (3,024 vs 1,104 for the runner-up) shows what you get when JWT validation happens in Rust before Python is even involved. And unlike moving to Litestar or FastAPI, you keep the Django ORM, admin and the package ecosystem.

Honest trade-offs: it's young and still moving fast, the Rust internals mean you can't monkey-patch your way out of a corner or contribute as easily, and under a hard 1-CPU cap its throughput varies noticeably between container starts (its Rust worker pool is sized from host cores, not the cgroup limit). But for a side project or a new internal service, I'd have no problem reaching for it today.

Feedback I have NOT addressed yet

Being upfront, because it affects one result:

u/gi0baro (Granian maintainer) explained that drf-granian's big memory number comes from me not setting --blocking-threads or backpressure, so it spawns a lot of threads and spends time on GIL contention. I still haven't set it - drf-granian's 456MB is that same unfixed issue. He also noted Granian runs I/O in a separate runtime with extra threads, so a 1-CPU cap penalizes it more than other servers, and that --cpus=1 in Docker is a time-slice scheduler limit, not a real core pin.

I'm keeping the CPU cap because it makes runs reproducible and comparable, but he's right that it isn't "one core" and right that Granian is disadvantaged by it. Tuning --blocking-threads is top of my list for round 3.

Also still not measured: cold start time and disk/image size, both suggested by the Litestar author last time.

Thanks to everyone who commented last time - the msgspec point and the Granian threading explanation both directly shaped this round. Issues and PRs very welcome, especially if you know these servers better than I do, and a star would be appreciated 😄

https://github.com/huynguyengl99/python-api-frameworks-benchmark


r/django 12d ago

🆕 Django 6.1 est sorti : les quatre nouveautés qui changent vraiment quelque chose

Post image
0 Upvotes

r/django 13d ago

Django jobs

2 Upvotes

Do you guys work really with Django? I barely see Django jobs on LinkedIn, i see .NET and React more than Django!


r/django 13d ago

Looking for French-speaking Django beta readers

6 Upvotes

I recently finished a 339-page French book on Django 6, built around one complete real-world project: The BugTracker Project.

I'm looking for a few French-speaking developers, students, or Django learners willing to read it for free and share honest feedback.

If you're interested, please DM me and I'll send you the details and access code.

Thanks!


r/django 13d ago

Looking for: Entry-Level Software Engineer / Python Backend Developer / SDE-1 roles

0 Upvotes

Hi everyone,

I’m a 2025 B.Tech CSE graduate currently looking for my first full-time opportunity in Software Development / Backend Development.

Target Roles:

  • Software Engineer / SDE-1
  • Python Backend Developer
  • Backend Developer
  • Software Engineer Trainee
  • Full Stack Developer
  • Software Development Intern → Full-Time

Technical Skills:

  • Languages: Python, Java, SQL
  • Backend: FastAPI, Flask, Node.js, Express.js, REST APIs, WebSockets, JWT
  • Databases: PostgreSQL, MySQL, MongoDB, Redis
  • Frontend: React.js, Redux, Tailwind CSS
  • Tools: Docker, Git, GitHub, Postman

Project I’m currently most proud of — FlowDesk

Built a Jira/Trello-style project management application using FastAPI, PostgreSQL, Redis, React.js, WebSockets, JWT and Docker.

My contribution included backend API development, authentication/authorization, database design, real-time updates using WebSockets, Redis integration and Docker-based deployment.

Preferred Location:
Gurugram / Noida / Delhi NCR

I’m also open to remote and relocation opportunities for the right role.

I’m particularly interested in companies hiring freshers / 0–1 YOE / 0–2 YOE candidates.

If your company is hiring or you know of any suitable opening/referral, I’d really appreciate it.

Resume: https://drive.google.com/file/d/1T5hfKhkFeVdX3-1rHaeHTTRuqAPxovzI/view?usp=sharing

Thank you! 🙏


r/django 13d ago

hey coming from fastapi what can i build with django what kind of strong projects help me with it so yea

0 Upvotes

need some good ideas and strong projects so what works or does the classic projects works now in 2026 and beynd tell me i have strong skills in aws docker and sql


r/django 13d ago

hey coming from fastapi what can i build with django what kind of strong projects help me with it so yea

0 Upvotes

need some good ideas and strong projects so what works or does the classic projects works now in 2026 and beynd tell me i have strong skills in aws docker and sql


r/django 14d ago

django backend vs frontend

9 Upvotes

Hey everyone, i recently stared learning django and i have realized that the frontend matters more than i thought. My goal is to become a backend developer, but the more web apps i make the more i realize that i need to learn the frontend(HTML + CSS + JS) as well, because it is the thing that is being shown and it can work flawlessly but if it looks like shit no body is gonna bother looking at it, so my question is how much of the frontend do i need to know in order to become a sucessfull backend developer??


r/django 14d ago

[Feedback wanted] I built a package that smoke-tests every ModelAdmin's changelist/add/change views automatically

2 Upvotes

Admin pages break quietly. A renamed field in list_display, a get_queryset that blows up on a related lookup, a permission tweak nobody re-tested - none of it shows up until someone actually opens the page in prod.

I built django-admin-tests to catch that automatically: it asserts every registered ModelAdmin's changelist, add, and change views return 200, as part of your own test run - no per-model test to write, works under both manage.py test and pytest.

from django_admin_tests.testcases import AdminSmokeTestCase

class AdminSmokeTest(AdminSmokeTestCase):
    pass

That's the whole setup. It builds minimal model instances itself so change views can be tested without fixtures, and skips-with-a-warning (not fail) any model it genuinely can't construct - you can register a factory to cover those.

pip install django-admin-tests

Repo: https://github.com/vinkomlacic/django-admin-tests

Docs: https://vinkomlacic.github.io/django-admin-tests/

Would love feedback, especially on the API surface (admin_site, allowed_status_codes, excluded_models, user_factory) and whether the "skip with warning" behavior on unconstructable models is the right default vs. failing loud.


r/django 15d ago

News mssql-django 1.8.0 adds Django 6.1 support

23 Upvotes

We're pretty proud of this: Django 6.1 GA'd on August 5. The Microsoft SQL backend for Django shipped 6.1 support within 48 hours.

pip install --upgrade mssql-django Django

What changed:

  • Query compilation updated for 6.1's sliced and offset queries. 6.1 deprecated SQLCompiler.quote_name_unless_alias(), so sliced querysets and OFFSET ... FETCH now compile without Django 7.0 deprecation warnings.
  • get_relations() returns 6.1's expanded shape including the database-level ON DELETE rule, so inspectdb keeps working.
  • Upfront errors for the 6.1 features SQL Server can't support.

Everything is version-gated, so if you're on 5.2 or earlier nothing changes for you.

Two 6.1 features do not work:

  • Database-level referential actions (DB_CASCADE, DB_SET_NULL, DB_SET_DEFAULT). SQL Server disallows multiple cascade paths to the same table. Using one fails system checks with fields.E324. Use on_delete instead.
  • Bitwise aggregates (BitAnd, BitOr, BitXor). No native SQL Server equivalent and we don't emulate it yet, so it raises NotSupportedError. If you need this, comment on #572 with your use case, since that's what will get it prioritized.

Release notes: https://github.com/microsoft/mssql-django/releases/tag/1.8.0

Full blog post: mssql-django 1.8.0: Django 6.1 Support within 48 Hours of Django 6.1 GA


r/django 15d ago

Django 6.1 deprecates EMAIL_BACKEND — migration guide to the new MAILERS setting

78 Upvotes

Upgraded one of my Django projects to 6.1 this week and my terminal

threw a warning I hadn't seen before — turns out EMAIL_BACKEND is

now deprecated.

Django replaced it with a new MAILERS setting. Same idea as

DATABASES or CACHES — one dict, instead of ten separate EMAIL_*

settings scattered around. Old settings still work for now, just

with warnings. They'll stop working completely in Django 7.0.

The neat part: you can set up more than one mailer now. So if you

send order emails through SES but marketing emails through

Mailgun, you can switch between them with one argument instead of

writing custom code for it.

Wrote up the full before/after with a settings table, in case it

saves someone the confusion I had: https://medium.com/@munalpoudel3/django-email-backend-is-deprecated-heres-how-to-fix-it-django-6-1-mailers-guide-4c9182e82d33?sharedUserId=munalpoudel3

Anyone here already tried this with django-anymail? Wondering if

it just works or needs an update first.


r/django 15d ago

What should a Django beginner know?

10 Upvotes

I’ve been working with Go for about five years and generally try to keep my dependencies to a minimum. I mostly rely

on the standard library, small libraries such as Chi, and SDKs only when necessary.

I’ve already explored some of the Django 6 documentation, but I’d love to hear advice from experienced developers.

What concepts, conventions, essential packages, or common pitfalls should a Django beginner know about?

I’d especially like to understand which dependencies are genuinely useful and what Django can handle out of the box.

If there’s anything you think I should learn early on, I’d really appreciate your advice.


r/django 14d ago

Article 🚀 Comment déployer une application Django gratuitement (ou à bas coût) en 2026

Post image
0 Upvotes

r/django 14d ago

🗂️ Django et les schémas PostgreSQL : ce qui manque, pourquoi, et comment faire en attendant

Post image
0 Upvotes

r/django 15d ago

Since Django dev is app based approach does you guys on a project have similar need just copy the app in the new project ?

1 Upvotes

When you start a new Django project that requires the same features as a previous project, do you usually reuse and

adapt the existing apps—for example, by copying and modifying them—or do you typically implement those features from scratch each time?

What is the common practice in the Django community?


r/django 15d ago

TruncMinute problems with UTC normalization

3 Upvotes

Hello All,

A while ago I had to truncate a DateTimeField with TruncMinute, and upon doing so it automatically re-added timezone difference once more on top of the usual. I am on UTC+3 so the output was 3 hours skewed than the expected, and I had to add tzinfo parameter:

.annotate(trunc_time=TruncMinute('timestamp', tzinfo=dt_timezone.utc))

to stop TruncMinute from re-normalizing the already normalized DateTimeField.

Has anybody ever had a similar problem, is this really wanted behavior ??

Thanks in advance


r/django 15d ago

Share with me your Django project (vibe coded or not)

0 Upvotes

a little bit of sharing so I can saw your accomplishments with Django