- Abstract
- 1.1 Overview
- 1.2 Goals
- 1.3 Benefits
- The Solution
- 2.1 Create
get_namespace
method - 2.2 Create
import_items
method - 2.3 Document how to subclass shell
- 2.1 Create
- Schedule
One of the most used django-extension is shell-plus: a shell that auto-imports models for you. For instance, imagine a django project with several models, and you need to try some operation using the shell: in that case it would be very useful a tool that auto-import model for you. Furthermore, maybe you'd like to import extra-things (modules from other libraries, function that you wrote, ecc.): in that case it may be cool if you can customize things you need to import, overriding only a single method.
The proposal is about to modify existing shell.py
in order to auto-import models of a project and let the developer
customize his imports.
- The first milestone is to create a method
get_namespace
that maps every model to its name/module and use this for importing the models. - The second milestone is to make this method overridable for changing the imports or adding new ones. I'll create
an
import_items
method that the developer can use for importing extra-items. - The third milestone will be to document how an user can extend
get_namespace
in order to import extra-things.
- If you want to try operations for each model of your app, you don't have to manually import the models
- The developer can create his customized shell with customized imports
First of all, we can add a method, such get_apps_and_models
that return a dictionary associating for every module found, a list of associated models. The core function get_namespace
will import all objects.
At the end we return imported_objects
. The signature of the method will be something like:
def get_namespace(self, options, style)
...
- We need to import apps from the existing project in order to associate the
model_module
to the model usingapp_config
:
def get_apps_and_models(self):
for app_conf in apps.get_app_configs():
if app_conf.models_module:
yield app_conf.models_module, app_conf.get_models()
...
- For each app, we try to import each model:
...
for model in app_models:
if model.__module__:
try:
imported_objects[model.__name__] = import_string(
"%s.%s" % (model.__module__, model.__name__)
)
except ImportError as e:
if options.get("traceback"):
traceback.print_exc()
else:
print(
style.ERROR(
"Failed to import %s from %s, reason %s"
% (model.__name__, model.__module__, e)
)
)
...
At this point we imported all objects in INSTALLED_APPS
order, so in the case of two or more models with the same name we pick the first in the order mentioned before.
- Finally we return
imported_objects
- At this time we want something that can help the user to import extra-items. The idea of
import_items
is to get a dictionary that maps for each module all the objects to import like this:
IMPORTS = {'os': [], 'an_app': ['submodule1', 'submodule2']}
If the list is empty, we intend like the user wants to import everything from that module, so we use the importlib.import_module
function adding to imported_objects
all objects imported for that module,
otherwise we import only the objects requested for that module with importlib.__import__
.
- The signature of the method could be like:
def import_items(import_dict, imported_objects, style)
- Finally we import all objects:
...
for module, objects in import_dict.items():
try:
if len(objects) > 0:
imported_objects[module] = importlib.__import__(module, {}, {}, objects)
else:
imported_objects[module] = importlib.import_module(module)
except as ImportError:
print(style.ERROR(f"Unable to import {module}"))
...
The most important goal to achieve in this project is to make shell customizable by the user: in order to do that we have to explain how the user can override the
get_namespace
method: my idea is to add a section to docs/howto/custom-management-commands.txt
and explain what to do:
- Explain how to create your custom dictionary of imports
- Explain how to override
get_namespace
and show some example like:
class Command(shell.Command):
def get_namespace(self, options, style):
import_dict = {}
imported_objects = super().get_namespace(options, style)
import_items(import_dict, imported_objects)
My exams will start in June and will finish in the end of july. So that I think I would be able to devote 15-20 hours a week throughout GSOC period. I would like to devote 50% of my time to learning and coding, and 50% of my time to test the changes and write documentation for new stuff. I also will keep in touch with the community and mentors using django-forum and discord.
- Discuss implementation with mentors
- Figure out any better approach for the solution
(From May 27 - June 30)The goal in this phase is to implement the core function for auto-importing models.
- Modify
imported_objects
inipython
,b_python
andpython
- Write unit tests and verify that fails for new imported_objects
- Create the method
- Write unit tests
- Documentation (if required)
- Import all models
- Write unit tests
- Documentation (if required)
(From July 1 - July 16)The goal in this phase is to implement a function that helps user to customize his auto-importing shell.
- Implement a prototype
- Write unit tests
- Documentation
(From July 16 - August 10)The goal in this phase is to create an exaustive documentation about the new functionality and how user can subclass the shell
- Writing docs in the customize django-admin commands
My name is Salvo Polizzi
and I am a Pre-final year Btech. student from University Of Catania (Italy)
. I started coding when join the university with C++ then used python for some projects. I started learnig Django because interested in web framework and how they are built.
I started contributing in django in December 2023 and I found a lot of help from all the community.