Najczęstsze błędy początkujących w Django (i jak ich unikać)

Piotr Dul

Piotr Dul

28-09-2026

(aktualizacja: 28-09-2026)

Fat views, migracje w .gitignore, konflikty przy pracy na branchach i problem N+1 w ORM — poznaj 4 błędy, które najczęściej popełniają początkujący w Django, i naucz się ich unikać, zanim trafią na produkcję.

Najczęstsze błędy początkujących w Django (i jak ich unikać)
Początkujący w Django najczęściej: wrzucają logikę biznesową do widoków zamiast do modeli, dodają pliki migracji do `.gitignore` (co psuje pracę zespołową), nie radzą sobie z konfliktami migracji przy pracy na wielu branchach, oraz nieświadomie generują problem N+1 w zapytaniach ORM. Każdego z tych błędów da się uniknąć, znając ich przyczynę — a najszybciej uczy się tego na prawdziwym code review, nie z dokumentacji.

Django odejmuje sporo pracy dzięki gotowym rozwiązaniom "z pudełka" — ale to nie znaczy, że trudno w nim popełnić błąd. Poniższe cztery problemy to te, które najczęściej powtarzają się u osób dopiero zaczynających pracę z tym frameworkiem — potwierdzone zarówno realnym code review, jak i skalą pytań o nie na Stack Overflow.

Logika biznesowa w widokach zamiast w modelach

Najbardziej podstawowy, a zarazem najczęstszy błąd: cała logika aplikacji ląduje w pliku views.py, zamiast w modelach albo osobnych funkcjach pomocniczych. Krótkoterminowo to działa — Django nie zabroni Ci tego zrobić — ale kod szybko robi się nie do utrzymania, gdy tej samej logiki potrzebujesz w dwóch różnych widokach, albo gdy chcesz ją przetestować niezależnie od requestu HTTP.

— Piotr Dul, mentor Python w devmentor.pl: "Najczęstszy błąd początkujących? Zbyt dużo logiki wrzucanej bezpośrednio do widoków (views), zamiast do modeli albo osobnych funkcji pomocniczych. Krótkoterminowo działa, ale przy pierwszym większym projekcie taki kod robi się nie do utrzymania — a to właśnie od dobrych nawyków w organizacji kodu zaczynamy pracę na mentoringu."

Jak tego unikać: trzymaj się zasady "fat models, thin views" — widok powinien odbierać request, wywołać odpowiednią metodę modelu (albo serwisu), i zwrócić odpowiedź. Jeśli w widoku pojawia się więcej niż kilka linijek logiki niezwiązanej bezpośrednio z HTTP, to sygnał, że warto ją przenieść niżej.

Commitowanie plików migracji do .gitignore

To błąd, który na pierwszy rzut oka wygląda rozsądnie — pliki w migrations/ są generowane automatycznie, więc intuicja podpowiada "to nie mój kod, nie musi być w repozytorium". To jedno z najczęściej zadawanych pytań o Django na Stack Overflow (ponad 114 tysięcy wyświetleń) — i odpowiedź jest jednoznaczna: migracje MUSZĄ trafiać do repozytorium.

Migracje to nie tylko wygenerowany kod — to historia zmian struktury Twojej bazy danych. Jeśli je zignorujesz:

  • każdy, kto sklonuje repozytorium (w tym Twój mentor przy code review), dostanie inną strukturę bazy niż Ty,
  • na produkcji nie da się bezpiecznie zaktualizować schematu bazy bez tej historii,
  • Django zacznie próbować "zgadywać" zmiany na nowo, co często kończy się konfliktami trudnymi do rozwiązania.

Jak tego unikać: commituj migrations/ tak samo jak resztę kodu. Jedyny wyjątek to plik __pycache__ wewnątrz tego folderu — to faktycznie powinno zostać w .gitignore.

Konflikty migracji przy pracy na wielu branchach

Blisko powiązany, ale osobny problem: dwie osoby (albo Ty i mentor, pracujący równolegle na osobnych branchach) tworzą migracje niezależnie od tej samej bazowej wersji. Django numeruje migracje liniowo, więc po połączeniu branchy dostajesz błąd o wielu "liściach" w grafie migracji (ten dokładny problem ma prawie 39 tysięcy wyświetleń na Stack Overflow) — Django nie wie, w jakiej kolejności je zastosować.

Jak tego unikać:

  1. Przed stworzeniem nowej migracji zrób git pull/zsynchronizuj branch z najnowszą wersją.
  2. Jeśli konflikt już wystąpił, użyj python manage.py makemigrations --merge — Django samo zaproponuje migrację łączącą oba "liście".
  3. W większych zespołach warto trzymać się zasady: migracje tworzy się tuż przed mergem, nie na początku pracy nad zadaniem.

Taki konflikt najczęściej wychodzi na jaw dopiero na code review — mentee dodaje migrację do swojego modelu na jednym branchu, a w międzyczasie na głównej gałęzi pojawia się inna migracja tego samego modelu (np. dodana przy okazji innego zadania). Dopiero próba scalenia branchy ujawnia dwa "liście" w grafie migracji.

Problem N+1 w zapytaniach ORM

Django ORM pozwala pisać zapytania do bazy jak zwykły kod Pythona — ale ta wygoda ma pułapkę. Jeśli w pętli po liście obiektów odwołujesz się do powiązanego modelu (np. for post in Post.objects.all(): print(post.author.name)), Django wykonuje osobne zapytanie SQL dla każdej iteracji — przy 100 postach to 101 zapytań zamiast jednego. To tzw. problem N+1, jeden z najbardziej znanych anti-patternów w całym ekosystemie ORM (nie tylko w Django).

Jak tego unikać: używaj select_related() (dla relacji ForeignKey/OneToOne) i prefetch_related() (dla ManyToMany i relacji odwrotnych), żeby Django pobrał powiązane dane jednym zapytaniem z góry:

# Źle — N+1 zapytań
posts = Post.objects.all()
for post in posts:
    print(post.author.name)

# Dobrze — 1 zapytanie
posts = Post.objects.select_related("author").all()
for post in posts:
    print(post.author.name)

Ten temat wraca w module "Zaawansowane modele i ORM" na naszej ścieżce Python — dokładnie na etapie, gdy modele zaczynają mieć realne relacje między sobą, nie tylko pojedyncze pola.

Jak unikać tych błędów szybciej niż samemu?

Każdy z powyższych błędów da się znaleźć w dokumentacji Django albo na Stack Overflow — ale zwykle po tym, jak już go popełnisz i coś przestanie działać. Na mentoringu 1:1 w devmentor.pl te błędy wyłapuje mentor na etapie code review, zanim trafią na produkcję — a przy okazji tłumaczy, dlaczego dane rozwiązanie jest lepsze, nie tylko że jest.

Chcesz zobaczyć, jak wygląda nauka Django z realnym code review od mentora? Przeczytaj, czym jest Django i do czego służy, albo od razu umów bezpłatną rozmowę i sprawdź program ścieżki Python.

Konsultacja i warsztaty devmentor.pl

Masz pytania?