Applikationer¶
Django innehåller ett register över installerade applikationer som lagrar konfiguration och ger introspektion. Det upprätthåller också en lista över tillgängliga modeller.
Det här registret kallas apps och finns i django.apps:
>>> from django.apps import apps
>>> apps.get_app_config("admin").verbose_name
'Administration'
Projekt och tillämpningar¶
Termen projekt beskriver en Django webbapplikation. Projektets Python-paket definieras främst av en inställningsmodul, men det innehåller vanligtvis andra saker. Till exempel:, när du kör django-admin startproject mysite får du en mysite projektkatalog som innehåller ett mysite Python-paket med settings.py, urls.py, asgi.py och wsgi.py. Projektpaketet utökas ofta för att inkludera saker som fixturer, CSS och mallar som inte är knutna till en viss applikation.
Ett projekts rotkatalog (den som innehåller manage.py) är vanligtvis behållaren för alla ett projekts applikationer som inte installeras separat.
Termen applikation beskriver ett Python-paket som tillhandahåller en viss uppsättning funktioner. Applikationer kan återanvändas i olika projekt.
Applikationer innehåller en kombination av modeller, vyer, mallar, malltaggar, statiska filer, webbadresser, mellanprogram osv. De är i allmänhet kopplade till projekt med inställningen INSTALLED_APPS och eventuellt med andra mekanismer som URLconfs, inställningen MIDDLEWARE eller mallarv.
Det är viktigt att förstå att en Django-applikation är en uppsättning kod som interagerar med olika delar av ramverket. Det finns inget sådant som ett Application-objekt. Det finns dock några ställen där Django behöver interagera med installerade applikationer, främst för konfiguration och även för introspektion. Det är därför som applikationsregistret upprätthåller metadata i en AppConfig-instans för varje installerad applikation.
Det finns inga begränsningar för att ett projektpaket inte också kan betraktas som en applikation och ha modeller etc. (vilket skulle kräva att det läggs till i INSTALLED_APPS).
Konfigurera applikationer¶
För att konfigurera en applikation skapar du en apps.py-modul i applikationen och definierar sedan en subklass av AppConfig där.
När INSTALLED_APPS innehåller den prickade sökvägen till en applikationsmodul, som standard, om Django hittar exakt en AppConfig subklass i apps.py submodulen, använder den den konfigurationen för applikationen. Detta beteende kan inaktiveras genom att ställa in AppConfig.default till False.
Om modulen apps.py innehåller mer än en AppConfig-underklass, kommer Django att leta efter en enda där AppConfig.default är True.
Om ingen underklass till AppConfig hittas, kommer basklassen AppConfig att användas.
Alternativt kan INSTALLED_APPS innehålla den prickade sökvägen till en konfigurationsklass för att ange den explicit:
INSTALLED_APPS = [
...,
"polls.apps.PollsAppConfig",
...,
]
För applikationsanvändare¶
Om du använder ”Rock ’n’ roll” i ett projekt som heter anthology, men du vill att det ska visas som ”Jazz Manouche” istället, kan du ange din egen konfiguration:
# anthology/apps.py
from rock_n_roll.apps import RockNRollConfig
class JazzManoucheConfig(RockNRollConfig):
verbose_name = "Jazz Manouche"
# anthology/settings.py
INSTALLED_APPS = [
"anthology.apps.JazzManoucheConfig",
# ...
]
Detta exempel visar projektspecifika konfigurationsklasser som finns i en undermodul som heter apps.py. Detta är en konvention, inte ett krav. AppConfig-subklasser kan definieras var som helst.
I den här situationen måste INSTALLED_APPS innehålla den prickade sökvägen till konfigurationsklassen eftersom den ligger utanför ett program och därför inte kan upptäckas automatiskt.
Konfiguration av applikation¶
- class AppConfig[source]¶
Applikationskonfigurationsobjekt lagrar metadata för en applikation. Vissa attribut kan konfigureras i
AppConfigsubklasser. Andra ställs in av Django och är skrivskyddade.
Konfigurerbara attribut¶
- AppConfig.name¶
Fullständig Python-sökväg till applikationen, t.ex.
'django.contrib.admin'.Detta attribut definierar vilken applikation som konfigurationen gäller för. Det måste anges i alla
AppConfig-subklasser.Den måste vara unik för hela Django-projektet.
- AppConfig.label¶
Kortnamn för applikationen, t.ex.
'admin'Detta attribut möjliggör ommärkning av en applikation när två applikationer har motstridiga etiketter. Standardvärdet är den sista komponenten i
name. Det bör vara en giltig Python-identifierare.Den måste vara unik för hela Django-projektet.
Varning
Om du ändrar det här attributet efter att migreringar har tillämpats för en applikation kommer det att leda till att ändringar i ett projekt eller, när det gäller en återanvändbar app, alla befintliga installationer av den appen bryts. Detta beror på att
AppConfig.labelanvänds i databastabeller och migreringsfiler när en app refereras till i beroendelistan.
- AppConfig.verbose_name¶
Ett mänskligt läsbart namn för applikationen, t.ex. ”Administration”.
Standardvärdet för detta attribut är
label.title().
- AppConfig.path¶
Filsystemets sökväg till applikationskatalogen, t.ex.
'/usr/lib/pythonX.Y/dist-packages/django/contrib/admin'.I de flesta fall kan Django automatiskt upptäcka och ställa in detta, men du kan också tillhandahålla en explicit åsidosättning som ett klassattribut på din
AppConfig-underklass. I några få situationer krävs detta; till exempel om app-paketet är ett namespace package med flera sökvägar.
- AppConfig.default¶
Sätt detta attribut till
Falseför att förhindra Django från att välja en konfigurationsklass automatiskt. Detta är användbart närapps.pybara definierar enAppConfig-underklass men du inte vill att Django ska använda den som standard.Sätt detta attribut till
Trueför att säga till Django att välja en konfigurationsklass automatiskt. Detta är användbart närapps.pydefinierar mer än enAppConfig-underklass och du vill att Django ska använda en av dem som standard.Som standard är detta attribut inte inställt.
- AppConfig.default_auto_field[source]¶
Den implicita primära nyckeltypen som ska läggas till i modeller i den här appen. Du kan använda detta för att behålla
AutoFieldsom primärnyckeltyp för tredjepartsapplikationer.Som standard är detta värdet för
DEFAULT_AUTO_FIELD.
Skrivskyddade attribut¶
- AppConfig.module¶
Rotmodul för applikationen, t.ex.
<module 'django.contrib.admin' from 'django/contrib/admin/__init__.py'>.
- AppConfig.models_module¶
Modul som innehåller modellerna, t.ex.
<module 'django.contrib.admin.models' from 'django/contrib/admin/models.py'>.Den kan vara
Noneom applikationen inte innehåller enmodelsmodul. Observera att de databasrelaterade signalerna sompre_migrateochpost_migrateendast sänds ut för applikationer som har enmodels-modul.
Metoder¶
- AppConfig.get_models(include_auto_created=False, include_swapped=False)[source]¶
Returnerar en iterabel av
Model-klasser för denna applikation.Kräver att appregistret är helt fyllt.
- AppConfig.get_model(model_name, require_ready=True)[source]¶
Returnerar
Modelmed det angivnamodel_name.model_nameär skiftlägesokänsligt.Utlöser
LookupErrorom ingen sådan modell finns i denna applikation.Kräver att appregistret är helt fyllt om inte argumentet
require_readyär satt tillFalse.require_readybeter sig exakt som iapps.get_model().
- AppConfig.ready()[source]¶
Underklasser kan åsidosätta denna metod för att utföra initialiseringsuppgifter som t.ex. registrering av signaler. Den anropas så snart registret är helt fyllt.
Även om du inte kan importera modeller på modulnivå där
AppConfig-klasserna definieras, kan du importera dem iready(), antingen med hjälp av enimport-sats ellerget_model().Om du registrerar
modellsignalerkan du hänvisa till avsändaren med dess strängetikett istället för att använda själva modellklassen.Exempel:
from django.apps import AppConfig from django.db.models.signals import pre_save class RockNRollConfig(AppConfig): # ... def ready(self): # importing model classes from .models import MyModel # or... MyModel = self.get_model("MyModel") # registering signals with the model's string label pre_save.connect(receiver, sender="app_label.MyModel")
Varning
Även om du kan komma åt modellklasser enligt beskrivningen ovan bör du undvika att interagera med databasen i din
ready()-implementering. Detta inkluderar modellmetoder som utför frågor (save(),delete(), managermetoder etc.), och även råa SQL-frågor viadjango.db.connection. Dinready()-metod kommer att köras under uppstarten av varje hanteringskommando. Till exempel:, även om testdatabasens konfiguration är separat från produktionsinställningarna, kommermanage.py testfortfarande att köra några frågor mot din produktions databas!Observera
I den vanliga initialiseringsprocessen anropas metoden
readybara en gång av Django. Men i vissa hörnfall, särskilt i tester som manipulerar installerade applikationer, kanreadyanropas mer än en gång. I så fall ska du antingen skriva idempotenta metoder eller sätta en flagga på dinaAppConfig-klasser för att förhindra att kod som ska köras exakt en gång körs om.
Namnrymdspaket som appar¶
Python-paket utan filen __init__.py kallas ”namespace-paket” och kan vara spridda över flera kataloger på olika platser i sys.path (se PEP 420).
Django-applikationer kräver en enda basfilsystemssökväg där Django (beroende på konfiguration) kommer att söka efter mallar, statiska tillgångar etc. Namnrymdspaket kan således endast vara Django-applikationer om något av följande är sant:
Namnrymdspaketet har faktiskt bara en enda plats (dvs. det är inte utspritt över mer än en katalog)
Klassen
AppConfigsom används för att konfigurera applikationen har ett klassattributpath, som är den absoluta katalogsökvägen som Django kommer att använda som den enda basvägen för applikationen.
Om inget av dessa villkor uppfylls kommer Django att ge upphov till ImproperlyConfigured.
Applikationsregister¶
- apps¶
Applikationsregistret tillhandahåller följande offentliga API. Metoder som inte listas nedan betraktas som privata och kan ändras utan föregående meddelande.
- apps.ready¶
Booleskt attribut som sätts till
Truenär registret är helt fyllt och allaAppConfig.ready()-metoder har anropats.
- apps.get_app_config(app_label)¶
Returnerar en
AppConfigför applikationen med den angivnaapp_label. UtlöserLookupErrorom ingen sådan applikation finns.
- apps.is_installed(app_name)¶
Kontrollerar om en applikation med det angivna namnet finns i registret.
app_nameär det fullständiga namnet på appen, t.ex.'django.contrib.admin'.
- apps.get_model(app_label, model_name, require_ready=True)¶
Returnerar
Modelmed de givnaapp_labelochmodel_name. Som en genväg accepterar denna metod också ett enda argument i form avapp_label.model_name.model_nameär skiftlägesokänsligt.Ger upphov till
LookupErrorom ingen sådan applikation eller modell finns. Ger upphov tillValueErrornär den anropas med ett enda argument som inte innehåller exakt en punkt.Kräver att appregistret är helt fyllt om inte argumentet
require_readyär satt tillFalse.Om du ställer in
require_readytillFalsekan du leta upp modeller :ref:medan appregistret fylls på <app-loading-process>`, särskilt under den andra fasen där den importerar modeller. Då har ``get_model()samma effekt som att importera modellen. Det huvudsakliga användningsfallet är att konfigurera modellklasser med inställningar, till exempelAUTH_USER_MODEL.När
require_readyärFalsereturnerarget_model()en modellklass som kanske inte är helt funktionell (omvända accessorer kan till exempel saknas) förrän appregistret är helt fyllt. Av denna anledning är det bäst att lämnarequire_readytill standardvärdetTruenär det är möjligt.
Initialiseringsprocess¶
Hur applikationer laddas¶
När Django startar ansvarar django.setup() för att fylla på applikationsregistret.
- setup(set_prefix=True)[source]¶
Konfigurerar Django genom att:
Ladda inställningarna.
Sätta upp loggning.
Om
set_prefixär True, ställs URL-resolverns skriptprefix in påFORCE_SCRIPT_NAMEom det är definierat, eller/annars.Initialisering av programregistret.
Denna funktion anropas automatiskt:
När du kör en HTTP-server via Djangos ASGI- eller WSGI-stöd.
När du anropar ett managementkommando.
Den måste anropas explicit i andra fall, t.ex. i vanliga Python-skript.
Applikationsregistret initieras i tre steg. Vid varje steg bearbetar Django alla applikationer i ordningen INSTALLED_APPS.
Först importerar Django varje objekt i
INSTALLED_APPS.Om det är en applikationskonfigurationsklass importerar Django applikationens rotpaket, definierat av dess
name-attribut. Om det är ett Python-paket letar Django efter en applikationskonfiguration i enapps.py-undermodul, eller skapar en standardapplikationskonfiguration.I det här skedet ska din kod inte importera några modeller!
Med andra ord bör dina programs rotpaket och de moduler som definierar dina programkonfigurationsklasser inte importera några modeller, inte ens indirekt.
Strängt taget tillåter Django import av modeller när deras applikationskonfiguration har laddats. Men för att undvika onödiga begränsningar av ordningen på
INSTALLED_APPSrekommenderas det starkt att inte importera några modeller i det här skedet.När detta steg har slutförts blir API:er som arbetar med applikationskonfigurationer, t.ex.
get_app_config(), användbara.Sedan försöker Django importera undermodulen
modelsför varje applikation, om det finns en sådan.Du måste definiera eller importera alla modeller i din applikations
models.pyellermodels/__init__.py. Annars kan det hända att programregistret inte är helt fyllt vid denna tidpunkt, vilket kan leda till att ORM inte fungerar som det ska.När detta steg har slutförts blir API:er som arbetar med modeller, t.ex.
get_model(), användbara.Slutligen kör Django
ready()-metoden för varje applikationskonfiguration.
Felsökning¶
Här följer några vanliga problem som du kan stöta på under initialiseringen:
AppRegistryNotReady: Detta händer när import av en applikationskonfiguration eller en modellmodul utlöser kod som är beroende av appregistret.Till exempel: använder
gettext()appregistret för att leta upp översättningskataloger i program. För att översätta vid importtillfället behöver du iställetgettext_lazy(). (Att användagettext()skulle vara en bugg, eftersom översättningen skulle ske vid importtillfället, snarare än vid varje förfrågan beroende på det aktiva språket)Om du kör databasfrågor med ORM vid importtillfället i modellmoduler kommer detta undantag också att utlösas. ORM kan inte fungera korrekt förrän alla modeller är tillgängliga.
Detta undantag inträffar också om du glömmer att anropa
django.setup()i ett fristående Python-skript.ImportError: cannot import name ...Detta händer om importsekvensen hamnar i en slinga.För att eliminera sådana problem bör du minimera beroendet mellan dina modellmoduler och göra så lite arbete som möjligt vid importtillfället. För att undvika att exekvera kod vid importtillfället kan du flytta den till en funktion och cacha dess resultat. Koden kommer att exekveras när du först behöver dess resultat. Det här konceptet kallas ”lazy evaluation”.
django.contrib.adminutför automatiskt autodiscovery avadmin-moduler i installerade applikationer. För att förhindra det, ändra dinINSTALLED_APPSså att den innehåller'django.contrib.admin.apps.SimpleAdminConfig'istället för'django.contrib.admin'.RuntimeWarning: Accessing the database during app initialization is discouraged.Denna varning utlöses för databasfrågor som körs innan appar är klara, t.ex. under modulimport eller i metodenAppConfig.ready(). Sådana för tidiga databasfrågor avråds eftersom de kommer att köras under uppstarten av varje hanteringskommando, vilket kommer att sakta ner projektstarten, potentiellt cacha inaktuella data och kan till och med misslyckas om migreringar väntar.Ett vanligt misstag är t.ex. att göra en databasfråga för att fylla i formulärfältens val:
class LocationForm(forms.Form): country = forms.ChoiceField(choices=[c.name for c in Country.objects.all()])
I exemplet ovan körs frågan från
Country.objects.all()under modulimporten, eftersomQuerySetitereras över. För att undvika varningen kan formuläret använda enModelChoiceFieldistället:class LocationForm(forms.Form): country = forms.ModelChoiceField(queryset=Country.objects.all())
För att göra det lättare att hitta koden som utlöste varningen kan du få Python behandla varningar som fel att visa stackspårningen, till exempel med
python -Werror manage.py shell.