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:
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.
execute_from_command_line (sys.argv)
aus.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:
self.arg
== sys.argv
== ['manage.py', 'runserver']
--self.prog_name
== Pfad von manage.py
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