Django source code parsing (1)
Django source code parsing (2) manage. py
Django source code parsing (3) Django development server, wsgi standard implementation
Django source code parsing (4) Middleware
Django source code parsing (5) URL Configuration
1. What is manage. py?
Manage. py is automatically generated under the project root directory when you create a Django project using a django-admin.py. It is used to implement command line operations on the Django project.
Call Django. Core. Management. execute_manager () to execute the command.
#!/usr/bin/env pythonfrom django.core.management import execute_managerimport imptry: imp.find_module('settings') # Assumed to be in the same directory.except ImportError: import sys sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__) sys.exit(1)import settingsif __name__ == "__main__": execute_manager(settings)
2. Differences between manage. py and django-admin.py
The django-admin.py calls Django. Core. Management. execute_from_command_line () to execute the command.
#!/usr/bin/env pythonfrom django.core import managementif __name__ == "__main__": management.execute_from_command_line()
Both manage.pyand django-admin.pyuse the cmd.exe cute_manager () method of the django.core.managementpackage for use by manage. py, and execute_from_command_line ()
Provided for the use of django-admin.py. (Earth people are seen, ⊙ B ).
The main difference between these two commands is that execute_manager () executes a setup_environ (settings_mod) method. To find out the role of this method, we will know the main difference between manage. py and django-admin.py.
def execute_manager(settings_mod, argv=None): """ Like execute_from_command_line(), but for use by manage.py, a project-specific django-admin.py utility. """ setup_environ(settings_mod) utility = ManagementUtility(argv) utility.execute()
The Code mainly displays the setup_environ (settings_mod) method function:
# Set DJANGO_SETTINGS_MODULE appropriately. if original_settings_path: os.environ['DJANGO_SETTINGS_MODULE'] = original_settings_path else: os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name) # Import the project module. We add the parent directory to PYTHONPATH to # avoid some of the path errors new users can have. sys.path.append(os.path.join(project_directory, os.pardir)) project_module = import_module(project_name) sys.path.pop()
It can be seen that the main function of setup_environ (settings_mod) method is the main difference between manage. py and django-admin.py:
Manage. py sets a system environment variable named django_settings_module.
For example, the root directory of my Django project is "E: \ workspace \ Django \ Pearl", and the file name of the settings module is set to "Settings. py. django_settings_module"
For example, the root directory of my Django project is "E: \ workspace \ Django \ Pearl". Add "E: \ workspace \ Django" to pythonpath and import the package named "Pearl ".
The above two points actually enable the use of manage. py without entering the "-- Settings" and "-- pythonpath" parameters like when using the django-admin.py. For more convenient operations.
Note: when using the django-admin.py directly, you need to set the 'django _ settings_module 'environment variable or the "-Settings" option.
Iii. Manage. py Command Execution Process
Through the execute_manager () and execute_from_command_line () methods, we can see that the execution of Django commands is mainly performed through the Django. Core. Management. managementutility class.
The execute () method of the managementutility class is the execution entry.
Command Execution Process:
1. parse the command to obtain the name of the sub-command to be executed. parse the command line by inheriting to the optionparser class laxoptionparser.
2. Obtain the complete module path for all executable sub-commands.
The command file is defined in the Django/CORE/management/commands directory and the installed_apps (defined in the settings. py file)/management/commands directory.
Use the managementutility. fetch_command () method to call the get_commands () method.
3. Return the instance of the command class corresponding to the module with the same name as the sub-command.
4. Run the command. Call the run_from_argv () method of the instance of the command class.
Def handle_default_options (options): "This method sets 'django _ settings_module 'and pythonpath, that is, in the manage. "" If options. settings: OS. environ ['django _ settings_module '] = options. settings if options. pythonpath: SYS. path. insert (0, options. pythonpath) Class managementutility (object): "encapsulates the logic of the django-admin.py and manage. PY utilities. A managementutility has a number of commands, which can be manipulated by editing the self. commands dictionary. "def _ init _ (self, argv = none): # obtain the input parameter self. argv = argv or sys. argv [:] # Command Execution file, manage. PY or django-admin.py self. prog_name = OS. path. basename (self. argv [0]) ######################################## ###################################### omitted ## ######################################## ################################## def fetch_command (self, subcommand): "tries to fetch the given subcommand, printing a message with the appropriate command called from the command line (usually" django-admin.py "or" manage. PY ") if it can't be found. "" try: # obtain the module prefix corresponding to the sub-commands under the installed_apps/management/commands directory under the Django/CORE/management/commands directory # For example, "Cleanup" corresponds to the module prefix "Django. core "app_name = get_commands () [subcommand] handle T keyerror: SYS. stderr. write ("Unknown command: % R \ ntype '% s help' for usage. \ n "% \ (subcommand, self. prog_name) sys. exit (1) If isinstance (app_name, basecommand): # If the command is already loaded, use it directly. klass = app_name else: # core code of load_command_class, which returns an instance of the command class of the subcommand module. # module = import_module ('% S. management. commands. % s' % (app_name, name) # Return Module. command () Klass = load_command_class (app_name, subcommand) return Klass ###################################### ####################################### omitted ######################################## #################################### def execute (self): "given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. main execution entry. parse the command line by inheriting to the optionparser class laxoptionparser. execute the corresponding sub-commands. "# preprocess options to extract -- settings and -- pythonpath. # These options cocould affect the commands that are available, so they # Must be processed early. parser = laxoptionparser (usage = "% prog subcommand [Options] [ARGs]", version = get_version (), option_list = basecommand. option_list) self. autoComplete () Try: Options, argS = parser. parse_args (self. argv) # If the settings and pythonpath parameters are input, set the handle_default_options (options) parameters T: pass # ignore any option errors at this point. try: # The Sub-command to be executed is as follows: "manage. in py runserver, "runserver" subcommand = self. argv [1] couldn t indexerror: # print the "help" Information subcommand = 'help' # display help if no arguments were given if no sub-commands are entered. if subcommand = 'help': If Len (ARGs)> 2: Self. fetch_command (ARGs [2]). print_help (self. prog_name, argS [2]) else: parser. print_lax_help () sys. stderr. write (self. main_help_text () + '\ n') sys. exit (1) # Special-cases: We want 'django-Admin. PY -- version' and # 'django-Admin. PY -- help 'to work, for backwards compatibility. elif self. argv [1:] = ['-- version']: # laxoptionparser already takes care of printing the version. pass Elif self. argv [1:] In (['-- help'], ['-H']): parser. print_lax_help () sys. stderr. write (self. main_help_text () + '\ n') else: # locate the corresponding sub-command and execute. self. fetch_command (subcommand ). run_from_argv (self. argv)
Insert advertisement: settings. settings_module
The settings_module attribute of Django. conf. settings is often used to associate it with the settings module of our own project. How is it implemented?
Hey, this is achieved through the django_settings_module system environment variables mentioned above. Let's look at the core code of this implementation.
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"settings_module = os.environ[ENVIRONMENT_VARIABLE]self.SETTINGS_MODULE = settings_module
Iv. Commands
The Django command must be written in a module with the same name as the command line sub-command. The module must contain a class named command as the call entry.
The Django. Core. Management. basecommand class serves as the base class for all commands. It also provides three auxiliary classes: appcommand labelcommand and noargscommand.
Custom commands can inherit from basecommand or other three helper classes, and rewrite different methods of the parent class at the same time.
Brief Introduction
1. basecommand
For the basic classes of all commands, a handle () method is reserved for the subclass to override.
def handle(self, *args, **options): """ The actual logic of the command. Subclasses must implement this method. """ raise NotImplementedError()
2. appcommand
Take the name of one or more installed applications as the first part of the parameter. Implement operations on the app. Reserve a handle_app () method for the subclass to override.
def handle_app(self, app, **options): """ Perform the command's actions for ``app``, which will be the Python module corresponding to an application name given on the command line. """ raise NotImplementedError()
3. labelcommand
Accept one or more tag parameters, and reserve a handle_label () method for the subclass to override.
def handle_label(self, label, **options): """ Perform the command's actions for ``label``, which will be the string as given on the command line. """ raise NotImplementedError()
4. noargscommand
Parameter is not accepted. A handle_label () method is reserved for the subclass to override.
def handle_noargs(self, **options): """ Perform this command's actions. """ raise NotImplementedError()