Why do both of the following ways of importing UpdateView work?:
I was assuming 2. was the correct way, and 1. would not work, but from testing both work.
What you see here is quite common (at least in some Python packages). If you define a .py
file, that acts as a module. For example the django.views.generic.edit
module maps on the django/views/generic/edit.py
file [GitHub].
A directory is a Python module as well (due to the __init__.py
file), but it does not contain any elements by default, hence that would mean that django.views.generic
would be empty.
If we take a look at the django/views/generic/__init__.py
file [GitHub], we see:
from django.views.generic.base import RedirectView, TemplateView, View # ... from django.views.generic.edit import ( CreateView, DeleteView, FormView, UpdateView, ) # ... __all__ = [ 'View', 'TemplateView', 'RedirectView', 'ArchiveIndexView', 'YearArchiveView', 'MonthArchiveView', 'WeekArchiveView', 'DayArchiveView', 'TodayArchiveView', 'DateDetailView', 'DetailView', 'FormView', 'CreateView', 'UpdateView', 'DeleteView', 'ListView', 'GenericViewError', ] # ...
This thus imports the UpdateView
from the generic.py
file, and re-exports the class.
You thus can reference to the class in two ways: through the module defined by the generic.py
file, or through the re-export of the module of the directory, specified through the __init__.py
file.
This is typically done to export a portion of the items that are defined in the files, export these under a more convenient name, or provide some extra classes at the module level (for example the __init__.py
file defines the GenericViewError
error).
This directory-level module thus "groups" interesting views together. For example the FormMixin
is not exported at this level. The __init__.py
here groups (popular) class-based views together, whereas the mixins, that are typically used to define such generic views, are still specific to a file.