[PYTHON] Quellenanalyse für Django - INSTALLED_APPS

templarbit-illustration-django-1a748506.jpg

Vorwort

Ich werde den Prozess erklären, der zum Schreiben dieses Artikels führte. Ich hatte diese Frage auf Teratail. Ich weiß nicht, wie ich das Projekt unterrichten soll, wenn ich das Django-Modell aktiviere

Der Inhalt der Frage war wie folgt.

Warum sollte das INSTALLED_APPS-Modul von Django als app name.apps.app name config eingefügt werden? In Bezug auf die Verzeichnisstruktur sollte es "../app name / apps.app name config" sein.

Daher möchte ich den Django-Quellcode für "INSTALLED_APPS" erläutern. Wenn Sie sich für den Kern von Django interessieren, bleiben Sie bitte bis zum Ende bei uns. : entspannt:

Vorbereitung

Zur Erklärung werde ich ein einfaches Projekt namens "django_test" erstellen. Die Verzeichnisstruktur ist wie folgt.

djnago_test
|-- django_test
|-- |-- __init__.py
|-- |-- asgi.py
|-- |-- settings.py
|-- |-- urls.py
|-- |-- wsgi.py
|-- manage.py

runserver Starten Sie Ihr Django-Projekt über die Befehlszeile.

python manage.py runserver

Was danach geschah, werfen wir einen Blick auf den Inhalt von manage.py.

manage.py


#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_test.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == '__main__':
    main()

--setdefault fügt die Wörterbuchdaten von Schlüssel und Wert zu "Umgebung" hinzu. Wenn Schlüssel vorhanden ist, wird der Wert abgerufen.

Schauen wir uns zunächst den Inhalt von sys.argv, den Pfad von manage.py und den Ausführungsbefehl an.

['manage.py', 'runserver']

Schauen Sie sich als nächstes den Inhalt von execute_from_command_line (sys.argv) an.

management/__init__.py


def execute_from_command_line(argv=None):
    """Run a ManagementUtility."""
    utility = ManagementUtility(argv)
    utility.execute()

Der Inhalt ist sehr einfach, er nimmt den Wert von "sys.argv" an. Ich habe die ManagementUtility instanziiert und die execute Funktion ausgeführt. Werfen wir einen Blick auf die Funktion init von ManagementUtility.

management.py


    def __init__(self, argv=None):
        self.argv = argv or sys.argv[:]
        self.prog_name = os.path.basename(self.argv[0])
        if self.prog_name == '__main__.py':
            self.prog_name = 'python -m django'
        self.settings_exception = None

in diesem Fall:

Schauen wir uns den nächsten an. Was hat die Funktion "Ausführen" getan? Der Inhalt der Funktion ist sehr lang, daher werde ich nur die wichtigen Teile erläutern.

management.py


try:
    subcommand = self.argv[1]
except IndexError:
    subcommand = 'help'

python manage.py runserver Beim Ausführen lautet der Wert des Unterbefehls runserver. Geben Sie dann den folgenden Block ein.

management.py


...
if subcommand == 'runserver' and '--noreload' not in self.argv:
   try:
      autoreload.check_errors(django.setup)()
...

Werfen wir einen Blick auf den Inhalt von django.setup.

django/__init__.py


...
def setup(set_prefix=True):
    """
    Configure the settings (this happens as a side effect of accessing the
    first setting), configure logging and populate the app registry.
    Set the thread-local urlresolvers script prefix if `set_prefix` is True.
    """
    from django.apps import apps
    from django.conf import settings
    from django.urls import set_script_prefix
    from django.utils.log import configure_logging

    configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
    if set_prefix:
        set_script_prefix(
            '/' if settings.FORCE_SCRIPT_NAME is None else settings.FORCE_SCRIPT_NAME
        )
    apps.populate(settings.INSTALLED_APPS)

Zu diesem Zeitpunkt ist der Prozess in Bezug auf "INSTALLED_APPS" klar geworden. Werfen wir einen Blick auf die Quelle von "bevölkern", sie ist ziemlich lang, daher erkläre ich nur die wichtigen Teile.

registry.py


...
    def populate(self, installed_apps=None):
        ...
            for entry in installed_apps:
                if isinstance(entry, AppConfig):
                    app_config = entry
                else:
                    app_config = AppConfig.create(entry)
                if app_config.label in self.app_configs:
                    raise ImproperlyConfigured(
                        "Application labels aren't unique, "
                        "duplicates: %s" % app_config.label)

                self.app_configs[app_config.label] = app_config
                app_config.apps = self
...

Der Inhalt dieser installierten_Apps ist wie folgt: Schleife und nimm eine nach der anderen heraus und starte den nächsten Prozess. Eine Sache zu beachten ist, dass Inhalte wie "django.contrib.admin" vom Typ ** string ** sind.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Der Inhalt der Schleife ist eine bedingte Beurteilung der Vererbungsbeziehung für die in "INSTALLED_APPS" enthaltenen Elemente.

if isinstance(entry, AppConfig):
    app_config = entry
else:
    app_config = AppConfig.create(entry)

Natürlich ist es jetzt nur eine Zeichenfolge, also geht es in den else-Block.

app_config = AppConfig.create(entry)

Werfen wir einen Blick auf den Inhalt von create ().

config.py


    def create(cls, entry):
        ...
        try:
            module = import_module(entry)
        except ImportError:
            module = None
            mod_path, _, cls_name = entry.rpartition('.')

            if not mod_path:
                raise
        ...

An dieser Stelle möchte ich tatsächlich die Funktion "import_module" verwenden. Erstellen Sie eine Benutzer-App und fügen Sie sie zu INSTALLED_APPS hinzu.

python manage.py startapp users
INSTALLED_APPS= [
...
users or users.apps.UsersConfig
]

Wenn als "Benutzer" hinzugefügt.

test.py


import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_test.settings')

from importlib import import_module
print(import_module("users"))
# <module 'users' from '/Users/user/django/django_test/users/__init__.py'>

Er fand die App richtig.

Beim Hinzufügen als users.apps.UsersConfig.

test.py


import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_test.settings')

from importlib import import_module
print(import_module("users.apps.UsersConfig"))
# ModuleNotFoundError: No module named 'users.apps.UsersConfig'; 'users.apps' is not a package

Ich kann die App scheinbar nicht finden, also bin ich im Block unten.

config.py


except ImportError:
    module = None
    mod_path, _, cls_name = entry.rpartition('.')

    if not mod_path:
       raise

mod_path, _, cls_name = entry.rpartition ('.') Wird ausgeführt und Der Wert von "mod_path" ist "users.apps" und "cls_name" ist "UsersConfig". Ich werde es noch einmal testen.

main.py


import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_test.settings')

from importlib import import_module
mod_path, _, cls_name = "users.apps.UsersConfig".rpartition('.')
print(import_module(mod_path))
# <module 'users.apps' from '/Users/user/django/django_test/users/apps.py'>

Er hat die App gefunden.

Recommended Posts

Quellenanalyse für Django - INSTALLED_APPS
Ordnerstruktur zur Analyse
Python für die Datenanalyse Kapitel 4
10 Open Source Web Crawler für 2020
Python für die Datenanalyse Kapitel 2
Tipps und Vorsichtsmaßnahmen bei der Datenanalyse
Python für die Datenanalyse Kapitel 3
Hinweise für herausfordernde Basketball-Videoanalysen
Vorverarbeitungsvorlage für die Datenanalyse (Python)
Datenanalyse zur Verbesserung von POG 3 ~ Regressionsanalyse ~
Quellanalyse von Linux (Kernel): Systemaufruf
Python-Visualisierungstool für die Datenanalyse
Programm zur Twitter-Trendanalyse (persönliches Memo)
JupyterLab Grundeinstellung 2 für die Datenanalyse (pip)
JupyterLab Basic Setup für die Datenanalyse (pip)