Najlepsze praktyki dotyczące struktury katalogów roboczych projektu Django

173

Wiem, że właściwie nie ma jednej właściwej drogi. Jednak odkryłem, że trudno jest stworzyć strukturę katalogów, która działa dobrze i pozostaje czysta dla każdego programisty i administratora. W większości projektów na githubie istnieje pewna standardowa struktura. Ale nie pokazuje sposobu na uporządkowanie innych plików i wszystkich projektów na komputerze.

Jaki jest najwygodniejszy sposób zorganizowania wszystkich tych katalogów na komputerze deweloperskim? Jak je nazwiesz i jak łączysz się i wdrażasz na serwerze?

  • projekty (wszystkie projekty, nad którymi pracujesz)
  • pliki źródłowe (sama aplikacja)
  • kopia robocza repozytorium (używam git)
  • wirtualne środowisko (wolę to umieścić w pobliżu projektu)
  • statyczny root (dla skompilowanych plików statycznych)
  • Media root (dla przesłanych plików multimedialnych)
  • README
  • LICENCJA
  • dokumenty
  • szkice
  • przykłady (przykładowy projekt korzystający z aplikacji dostarczonej przez ten projekt)
  • baza danych (w przypadku użycia sqlite)
  • cokolwiek innego, czego zwykle potrzebujesz do udanej pracy nad projektem

Problemy, które chcę rozwiązać:

  • Dobre nazwy katalogów, tak aby ich przeznaczenie było jasne.
  • Przechowywanie wszystkich plików projektu (w tym virtualenv) w jednym miejscu, dzięki czemu mogę łatwo kopiować, przenosić, archiwizować, usuwać cały projekt lub szacować wykorzystanie miejsca na dysku.
  • Tworzenie wielu kopii wybranych zestawów plików, takich jak cała aplikacja, repozytorium lub virtualenv, przy jednoczesnym zachowaniu jednej kopii innych plików, których nie chcę klonować.
  • Wdrażanie odpowiedniego zestawu plików na serwerze poprzez rsyncing wybranego katalogu.
raacer
źródło

Odpowiedzi:

257

Istnieją dwa rodzaje "projektów" Django, które mam w swoim ~/projects/katalogu, oba mają nieco inną strukturę .:

  • Niezależne witryny internetowe
  • Aplikacje wtykowe

Samodzielna witryna internetowa

W większości projekty prywatne, ale nie musi. Zwykle wygląda to tak:

~/projects/project_name/

docs/               # documentation
scripts/
  manage.py         # installed to PATH via setup.py
project_name/       # project dir (the one which django-admin.py creates)
  apps/             # project-specific applications
    accounts/       # most frequent app, with custom user model
    __init__.py
    ...
  settings/         # settings for different environments, see below
    __init__.py
    production.py
    development.py
    ...

  __init__.py       # contains project version
  urls.py
  wsgi.py
static/             # site-specific static files
templates/          # site-specific templates
tests/              # site-specific tests (mostly in-browser ones)
tmp/                # excluded from git
setup.py
requirements.txt
requirements_dev.txt
pytest.ini
...

Ustawienia

Główne ustawienia to ustawienia produkcyjne. Inne pliki, np. ( staging.py, development.py) Po prostu wszystko z importu production.pyi nadpisać tylko niezbędne zmienne.

Dla każdego środowiska istnieją osobne pliki ustawień, np. produkcja, rozwój. W niektórych projektach mam również ustawienia testowania (dla test runner), staging (jako sprawdzenie przed ostatecznym wdrożeniem) i heroku (do wdrożenia w heroku).

Wymagania

Raczej określam wymagania bezpośrednio w setup.py. Tylko te, które są wymagane dla środowiska programistycznego / testowego, które mam w requirements_dev.txt.

Niektóre usługi (np. Heroku) wymagają posiadania requirements.txtw katalogu głównym.

setup.py

Przydatne podczas wdrażania projektu przy użyciu setuptools. Dodaje manage.pysię PATH, więc mogę uruchomić manage.pybezpośrednio (gdziekolwiek).

Aplikacje specyficzne dla projektu

Kiedyś umieszczałem te aplikacje w project_name/apps/katalogu i importowałem je za pomocą importu względnego.

Pliki szablonów / statyczne / locale / testy

Umieszczam te szablony i pliki statyczne w globalnym katalogu szablonów / statycznym, a nie w każdej aplikacji. Te pliki są zwykle edytowane przez osoby, które w ogóle nie przejmują się strukturą kodu projektu ani Pythonem. Jeśli jesteś programistą z pełnym stosem pracującym samodzielnie lub w małym zespole, możesz utworzyć szablony dla aplikacji / katalog statyczny. To naprawdę tylko kwestia gustu.

To samo dotyczy ustawień regionalnych, chociaż czasami wygodnie jest utworzyć oddzielny katalog ustawień regionalnych.

Testy zwykle lepiej jest umieścić w każdej aplikacji, ale zwykle jest wiele testów integracyjnych / funkcjonalnych, które testują więcej aplikacji pracujących razem, więc globalny katalog testów ma sens.

Katalog Tmp

W katalogu głównym projektu znajduje się katalog tymczasowy, wykluczony z VCS. Służy do przechowywania plików multimedialnych / statycznych i bazy danych sqlite podczas programowania. Wszystko w tmp można było usunąć w dowolnym momencie bez żadnych problemów.

Virtualenv

Wolę virtualenvwrapperi umieszczam wszystkie venvy w ~/.venvskatalogu, ale możesz umieścić je w środku, tmp/aby zachować je razem.

Szablon projektu

Stworzyłem szablon projektu dla tej konfiguracji, django-start-template

Rozlokowanie

Wdrożenie tego projektu jest następujące:

source $VENV/bin/activate
export DJANGO_SETTINGS_MODULE=project_name.settings.production
git pull
pip install -r requirements.txt

# Update database, static files, locales
manage.py syncdb  --noinput
manage.py migrate
manage.py collectstatic --noinput
manage.py makemessages -a
manage.py compilemessages

# restart wsgi
touch project_name/wsgi.py

Możesz użyć rsynczamiast git, ale nadal musisz uruchomić pakiet poleceń, aby zaktualizować środowisko.

Niedawno zrobiłem [django-deploy][2]aplikację, która pozwala mi na uruchomienie jednej komendy zarządzającej aktualizacją środowiska, ale używałem jej tylko do jednego projektu i wciąż z nią eksperymentuję.

Szkice i szkice

Szkice szablonów umieszczam w templates/katalogu globalnym . Wydaje mi się, że można utworzyć folder sketches/w katalogu głównym projektu, ale jeszcze go nie używano.

Wtykowa aplikacja

Te aplikacje są zwykle przygotowywane do publikacji jako open-source. Poniżej wziąłem przykład z django-forme

~/projects/django-app/

docs/
app/
tests/
example_project/
LICENCE
MANIFEST.in
README.md
setup.py
pytest.ini
tox.ini
.travis.yml
...

Nazwy katalogów są jasne (mam nadzieję). Pliki testowe umieszczam poza katalogiem aplikacji, ale to naprawdę nie ma znaczenia. Ważne jest, aby zapewnić READMEi setup.py, więc pakiet można łatwo zainstalować za pomocą pip.

Tomáš Ehrlich
źródło
Dziękuję Ci! Podoba mi się twoja struktura. Dało mi to przydatne pomysły. Dobre uwagi dotyczące używania setup.py do wymagań i instalowania manage.py w PATH. Czy mógłbyś pokazać, jak robisz ostatnią rzecz? Również dobra uwaga na temat „tmp” reż. Wolałbym nazwać go „lokalnie”, wtedy mógłbym mieć „env”, „tmp” i cokolwiek innego w środku. To rozwiązuje problem zbyt wielu transakcji z gitignore. Nowym problemem jest to, że ta nazwa jest zbyt bliska „locale”. Może warto przenieść „locale” do podstawowej aplikacji „nazwa_projektu”, nie jestem pewien. Po prostu nie chcę zmieniać struktury z powodu złej nazwy. Jakieś sugestie?
raacer
Używając setup.py, dodaj scriptsargument słowa kluczowego: github.com/elvard/django-start-template/blob/master/project/… Podoba mi się, tmpponieważ sugeruje "coś tymczasowego", które można usunąć w dowolnym momencie. Katalog najwyższego poziomu localenie jest konieczny, możesz go umieścić w dowolnym miejscu. Po prostu podoba mi się spójność z reżami static / templates.
Tomáš Ehrlich
Moje wymaganie dotyczące możliwości tworzenia kilku kopii plików źródłowych bez kopiowania innych plików nie zostało bezpośrednio rozwiązane. Ale cel nadal można zarchiwizować, używając git checkoutlub wykluczając tylko jeden katalog „tmp” podczas klonowania katalogu projektu. Wygląda więc na to, że Twoja konstrukcja spełnia wszystkie wymagania i jest wystarczająco jasna, aby używać jej regularnie, bez żadnych wątpliwości. Przyjmuję twoją odpowiedź. Dziękuję Ci.
raacer
Dziękuję Ci. Nadal nie rozumiem, co masz na myśli, mówiąc „możliwość zrobienia kilku kopii plików źródłowych bez kopiowania innych plików”. Poprawiona komenda rsync wystarczyłaby, ale prawdopodobnie nie o to ci chodzi ...
Tomáš Ehrlich
Zwykle tworzę srckatalog w katalogu głównym projektu. To jest robocza kopia plików źródłowych i katalogu głównego repozytorium git. Mogę zrobić kilka kopii tego katalogu - src, src.bak, src_tmpi tak dalej. Inne katalogi non-repo jak env, tmp, media, backupznajdujących się na tym samym poziomie. W cp -r src src.bakkażdej chwili mogę więc poeksperymentować z gitem lub porównać wersje z zewnętrznym narzędziem. Chociaż masz pliki lokalne w swoim repozytorium, mam je w katalogu moich plików lokalnych (odwrotnie). Lepsza nazwa mojego srcreż repo.
raacer
19

Moja odpowiedź jest inspirowana moim własnym doświadczeniem zawodowym, a przede wszystkim książką Two Scoops of Django, którą bardzo polecam, w której możesz znaleźć bardziej szczegółowe wyjaśnienie wszystkiego. Odpowiem tylko na kilka punktów, a wszelkie ulepszenia lub poprawki będą mile widziane. Ale mogą być też bardziej poprawne sposoby na osiągnięcie tego samego celu.

Projekty
Mam główny folder w moim katalogu osobistym, w którym zarządzam wszystkimi projektami, nad którymi pracuję.

Pliki źródłowe
Osobiście używam katalogu głównego projektu django jako katalogu głównego repozytorium moich projektów. Ale w książce zaleca się oddzielenie obu rzeczy. Myślę, że jest to lepsze podejście, więc mam nadzieję, że zacznę stopniowo wprowadzać zmiany w moich projektach.

project_repository_folder/
    .gitignore
    Makefile
    LICENSE.rst
    docs/
    README.rst
    requirements.txt
    project_folder/
        manage.py
        media/
        app-1/
        app-2/
        ...
        app-n/
        static/
        templates/
        project/
            __init__.py
            settings/
                __init__.py
                base.py
                dev.py
                local.py
                test.py
                production.py
            ulrs.py
            wsgi.py

Repozytorium
Git lub Mercurial wydają się być najpopularniejszymi systemami kontroli wersji wśród programistów Django. Oraz najpopularniejsze usługi hostingowe do tworzenia kopii zapasowych GitHub i Bitbucket .

Środowisko wirtualne
Używam virtualenv i virtualenvwrapper. Po zainstalowaniu drugiego musisz skonfigurować katalog roboczy. Mój znajduje się w moim katalogu / home / envs , tak jak jest to zalecane w przewodniku instalacji virtualenvwrapper. Ale nie sądzę, że najważniejsze jest to, gdzie jest umieszczony. Najważniejszą rzeczą podczas pracy ze środowiskami wirtualnymi jest aktualizacja pliku Require.txt.

pip freeze -l > requirements.txt 

Statyczny
folder projektu głównego


Folder Media Root Project

README
Katalog główny repozytorium

LICENCJA
Katalog główny repozytorium


Katalog główny repozytorium dokumentów . Te pakiety Pythona mogą pomóc w łatwiejszym zarządzaniu dokumentacją:

Szkice

Przykłady

Baza danych

cor
źródło
Dziękuję za podzielenie się swoimi doświadczeniami. W Twojej strukturze znajduje się wiele katalogów „projekt *”. Prawdopodobnie nie używasz takich imion w prawdziwym życiu, prawda? Powiedzmy, że mamy projekt „do zrobienia”. Jak w takim przypadku nazywasz te reżery? Problem, który widzę w twojej obecnej strukturze, polega na mieszaniu repozytorium z plikami nie będącymi repozytoriami (jak zauważyłeś powyżej). Dodawanie śmieci do .gitignore może być denerwujące, prawda? Inną wątpliwą rzeczą jest trzymanie katalogu środowiska tak daleko od samego projektu. Czy jest sens? Dlaczego nie stworzyć ~ / docs, ~ / statics i tak dalej? Nawet git lubi siedzieć blisko plików źródłowych.
raacer
Nazwałbym je: „todo_project” -> todo -> todo (a może todoapp). Myślę, że ważne jest, aby być folderem repozytorium w katalogu głównym hierarchii katalogów. Ale to tylko moja opinia. Jeśli chodzi o katalog środowiska, aby skonfigurować środowisko produkcyjne, wystarczy wpisać: pip install -U -r Requirements.txt. Ale, jak powiedziałem, nie ma jednego rozwiązania na wszystko.
cor
Ścieżka do głównej aplikacji to „projekty / todo_project / todo / todo”. Słowo „projekty” powtórzono dwukrotnie, a słowo „todo” powtórzone trzy razy. Wygląda na to, że „projekty / projekt / mój_projekt / katalog_projektu / projekt / projekt”. Nazwy są bardzo niejasne. Jest to jeden z głównych problemów, które próbuję rozwiązać w mojej strukturze katalogów. Chcę nazwać katalogi, aby ułatwić zrozumienie hierarchii. A co z katalogiem głównym repozytorium, czy mógłbyś wyjaśnić, dlaczego jest ważny? Czy mógłbyś również wyjaśnić, co jest dobrego w trzymaniu kopert poza głównym katalogiem projektu?
raacer
13

Nie lubię tworzyć nowego settings/katalogu. Ja po prostu dodać pliki o nazwach settings_dev.pya settings_production.pywięc nie trzeba edytować BASE_DIR. Poniższe podejście zwiększa domyślną strukturę zamiast ją zmieniać.

mysite/                   # Project
    conf/
        locale/
            en_US/
            fr_FR/
            it_IT/
    mysite/
        __init__.py
        settings.py
        settings_dev.py
        settings_production.py
        urls.py
        wsgi.py
    static/
        admin/
            css/           # Custom back end styles
        css/               # Project front end styles
        fonts/
        images/
        js/
        sass/
    staticfiles/
    templates/             # Project templates
        includes/
            footer.html
            header.html
        index.html
    myapp/                 # Application
        core/
        migrations/
            __init__.py
        templates/         # Application templates
            myapp/
                index.html
        static/
            myapp/
                js/  
                css/
                images/
        __init__.py
        admin.py
        apps.py
        forms.py
        models.py
        models_foo.py
        models_bar.py
        views.py
    templatetags/          # Application with custom context processors and template tags
        __init__.py
        context_processors.py
        templatetags/
            __init__.py
            templatetag_extras.py
    gulpfile.js
    manage.py
    requirements.txt

Myślę, że to:

    settings.py
    settings_dev.py
    settings_production.py

jest lepsze niż to:

    settings/__init__.py
    settings/base.py
    settings/dev.py
    settings/production.py

Ta koncepcja dotyczy również innych plików.


Zwykle umieszczam node_modules/i bower_components/w katalogu projektu w domyślnym static/folderze.

Czasami vendor/katalog dla podmodułów Git, ale zwykle umieszczam je w static/folderze.

isar
źródło
4

Oto, co śledzę w moim systemie.

  1. Wszystkie projekty : w moim katalogu domowym znajduje się katalog projektów, tj ~/projects. Wszystkie projekty spoczywają w nim.

  2. Projekt indywidualny : kieruję się standardowym szablonem struktury używanym przez wielu programistów o nazwie django-skel dla indywidualnych projektów. Zasadniczo zajmuje się wszystkimi plikami statycznymi i plikami multimedialnymi i wszystkim.

  3. Środowisko wirtualne : mam folder virtualenvs w moim domu do przechowywania wszystkich środowisk wirtualnych w systemie, tj ~/virtualenvs. Daje mi to elastyczność polegającą na tym, że wiem, jakie mam wszystkie środowiska wirtualne i mogę łatwo wyglądać w użyciu

Powyższe 3 to główne partycje Mojego środowiska pracy.

Wszystkie inne części, o których wspomniałeś, zależą głównie od projektu do projektu (tj. Możesz używać różnych baz danych dla różnych projektów). Powinni więc przebywać w swoich indywidualnych projektach.

Sahil kalra
źródło
Dziękuję Ci. Dodawanie jakichkolwiek śmieci do .gitignore może być denerwujące podczas mieszania repozytorium z plikami nie będącymi repozytoriami. Czyż nie? Niektóre z moich projektów mają do dziesięciu i więcej takich plików i reżerów, więc jest to dla mnie prawdziwy problem. Inną wątpliwą rzeczą jest trzymanie katalogu środowiska tak daleko od samego projektu. Jaka jest elastyczność takiego rozwiązania? Dlaczego nie stworzyć ~ / docs, ~ / statics i tak dalej? Nawet git lubi siedzieć blisko plików źródłowych. Myślałem, że elastyczność polega na tym, że mogę po prostu skopiować / przenieść / zarchiwizować / usunąć cały katalog projektu, w tym virtualenv, i łatwo utrzymywać wiele środowisk w jednym projekcie
raacer
4

Zgodnie ze szkieletem projektu Django, prawidłowa struktura katalogów, której można przestrzegać, to:

[projectname]/                  <- project root
├── [projectname]/              <- Django root
   ├── __init__.py
   ├── settings/
      ├── common.py
      ├── development.py
      ├── i18n.py
      ├── __init__.py
      └── production.py
   ├── urls.py
   └── wsgi.py
├── apps/
   └── __init__.py
├── configs/
   ├── apache2_vhost.sample
   └── README
├── doc/
   ├── Makefile
   └── source/
       └── *snap*
├── manage.py
├── README.rst
├── run/
   ├── media/
      └── README
   ├── README
   └── static/
       └── README
├── static/
   └── README
└── templates/
    ├── base.html
    ├── core
       └── login.html
    └── README

Odwiedź https://django-project-skeleton.readthedocs.io/en/latest/structure.html, aby uzyskać najnowszą strukturę katalogów.

Sachin Vardhan
źródło
7
Nienawidzę podejścia [nazwa projektu] / [nazwa projektu]!)
raacer
1
django-project-skeleton nie jest „dokumentacją Django”. Bardziej trafne byłoby powiedzenie „Według szkieletu-projektu-django ...”.
David Winiecki
0

Możesz skorzystać z repozytorium https://github.com/Mischback/django-project-skeleton .

Uruchom poniższe polecenie:

$ django-admin startproject --template=https://github.com/Mischback/django-project-skeleton/archive/development.zip [projectname]

Struktura wygląda mniej więcej tak:

[projectname]/                  <- project root
├── [projectname]/              <- Django root
   ├── __init__.py
   ├── settings/
      ├── common.py
      ├── development.py
      ├── i18n.py
      ├── __init__.py
      └── production.py
   ├── urls.py
   └── wsgi.py
├── apps/
   └── __init__.py
├── configs/
   ├── apache2_vhost.sample
   └── README
├── doc/
   ├── Makefile
   └── source/
       └── *snap*
├── manage.py
├── README.rst
├── run/
   ├── media/
      └── README
   ├── README
   └── static/
       └── README
├── static/
   └── README
└── templates/
    ├── base.html
    ├── core
       └── login.html
    └── README
Ehsan Barkhordar
źródło