Pulp Platform Application Layout¶
The Pulp Platform is built using two key frameworks, the Django Web Framework and the Django REST Framework. Where possible, conforming to the conventions of these frameworks is encouraged. The Pulp Platform strives to leverage these frameworks as much as possible, ideally making Pulp Platform development a work of implementation before innovation.
In the event that one of these components offers functionality that augments or supersedes functionality in another component, the order of precedence of these frameworks is:
- Pulp Platform
- Django REST Framework (DRF)
- Django Web Framework (Django)
So, features provided by the Pulp Platform should preferred over similar features provided by DRF, and features in DRF should be preferred over similar features provided by Django.
Module Layout¶
This is the basic layout of the pulpcore.app package, on the filesystem:
pulpcore
├── app
│   ├── apps.py
│   ├── fields.py
│   ├── __init__.py
│   ├── logs.py
│   ├── management
│   │   ├── commands
│   │   │   ├── __init__.py
│   │   │   └── ...
│   │   └── __init__.py
│   ├── manage.py
│   ├── migrations
│   ├── models
│   │   ├── __init__.py
│   │   └── ...
│   ├── pagination.py
│   ├── response.py
│   ├── serializers
│   │   ├── __init__.py
│   │   └── ...
│   ├── settings.py
│   ├── tasks
│   │   ├── __init__.py
│   │   └── ...
│   ├── templates
│   │   └── ...
│   ├── tests
│   │   └── ...
│   ├── urls.py
│   ├── viewsets
│   │   ├── __init__.py
│   │   └── ...
│   └── wsgi.py
└── __init__.py
The contents of this package are documented in detail in the ../platform-api/index
documentation. Details how this package is organized can be found
below, along with information about some of the modules found in this namespace.
Tip
This tree is incomplete, and maybe be out of date. Only the most notable and
durable modules have been listed; the most complete listing of modules in this
namespace will always be the ../platform-api/index documentation.
Module Imports¶
For modules in the pulpcore.app namespace that are large and capture behaviors
across multiple concerns of pulp, such as our models, we have separated these
packages into subpackages. All public identifiers and objects defined
in submodules are then collected into that module's __init__.py, from which
they will be imported by other Pulp Platform modules.
Using pulpcore.app.models as an example, this means that when breaking up the
models package in pulpcore.app, the following things are true:
- 
No models are defined in the __init__.pyofpulpcore.app.models.
- 
All models are defined in submodules located in the pulpcore.app.modelsmodule directory (where its__init__.pycan be found).
- 
The __init__.pyinpulpcore.app.modelsshould consist only of import statements, ordered to prevent any circular import issues that may result based on the imports that are done in any included submodules.
- 
Any models defined in submodules in pulpcore.app.modelsnamespace must be imported from thepulpcore.app.modelsnamespace, not the submodule in which they are defined. Yes:from pulpcore.app.models import PulpModel, No:from pulpcore.app.models.pulp import PulpModel.
- 
When adding new models, they must be imported into the pulpcore.app.models__init__.py, so that they are available to be imported by any other Pulp Platform components that use them from thepulpcore.app.modelsnamespace.
- 
Imports done inside any submodules should be relative, e.g. from .submodule import identifierorfrom . import submodule, avoiding the creation of circular imports.
- 
Imports done inside the module's __init__.pyshould be relative and explict, e.g.
- 
Yes: from .submodule import identifier1, identifier2
- No: from submodule import identifier1, identifier2
- No: from .submodule import *
Any module in pulpcore.app broken up in this way, such as
pulpcore.app.serializers or pulpcore.app.viewsets, should do so in such a way
that renders the implementation invisible to anyone importing from that module.
pulpcore.app¶
pulpcore.app is the package containing the core Pulp Platform Django application. This package contains all of the Pulp Platform models, serializers, and viewsets required to assemble Pulp's REST API and underlying database.
pulpcore.app.apps¶
This module defines the pulpcore.app.apps.PulpPluginAppConfig base class
used by all Pulp plugins to identify themselves to the Pulp Platform as plugins.
This module also includes the pulpcore.app.apps.PulpAppConfig class which
is the Pulp Platform application config.
pulpcore.app.settings¶
This is the main settings module for the platform Django project, which puts together all of the various Django applications that the Pulp Platform depends on to function, as well as the Pulp Platform application itself and its plugins.
Many things are defined in here, including the database settings, logging configuration,
REST API settings, etc. This file also finds and registers Pulp plugins with the Pulp
Platform Django Project, using the pulpcore.plugin entry point.
In order to use django-related tools with the Pulp Platform, the platform must be installed,
and the DJANGO_SETTINGS_MODULE environment var must be set to
pulpcore.app.settings.
pulpcore.app.urls¶
This module contains the API pulpcore.app.urls.root_router, and is where all non-API
views (should we ever write any) are mapped to URLs.
pulpcore.app.models¶
All models are contained in pulpcore.app.models.
The Platform models are all importable directly from the pulpcore.app.models
namespace. All Pulp models should subclass pulpcore.app.models.Model, or
one of its subclasses.
Note
All models must exist in the pulpcore.app.models namespace in order to be recognized by Django and included in the Django ORM.
Master/Detail Models¶
A few Pulp Platform models, including the Content model as well as
Remotes and Publishers, implement a strategy we refer to as "Master/Detail".
The Master/Detail strategy, as implemented in Pulp, allows us to define
necessary relationships on a single master Model, while still allowing
plugin developers to extend these Master classes with details pertinent
to the plugin's requirements. Using the pulpcore.app.models.Content
model as an example, pulpcore.app.models.Repository relates to the
Content model. This causes all content to relate to the repositories that
contain them the same way while still allowing plugin writers to add any
additional fields or behaviors to the model as-needed for their use cases.
In the Pulp Platform, models requiring this sort of behavior should subclass
pulpcore.app.models.MasterModel.
Serializers, ViewSets, and other Model-Related Classes¶
The modules containing Serializers and ViewSets, located in pulpcore.app.serializers and
pulpcore.app.viewsets, respectively, should be organized similarly to the models that
they represent where possible. For example, if pulpcore.app.models.Repository is defined
in the pulpcore.app.models.repository module, its corresponding serializer should be
defined in pulpcore.app.serializers.repository, and its corresponding viewset should be
defined in pulpcore.app.viewsets.repository, making it easy to find.
These, and other model-related classes, should be named in such a way as to make their
relationship to their Model unambiguous. To that end, model-related classes should include
the name of the model class they're related to in their name. So, the serializer for the
pulpcore.app.models.Repository model should be named RepositorySerializer, and the viewset
related to that model should be named RepositoryViewSet.
Classes not directly related to a model, or related to multiple models, should still of course be named in such a way as to make their purpose obvious an unambiguous.
ViewSet Registration¶
In order for ViewSets to be automatically registered with the Pulp Platform API router,
they must subclass pulpcore.app.viewsets.base.NamedModelViewSet and be imported into the
pulpcore.app.viewsets namespace.
ViewSets not meeting this criteria must be manually registered with the API router in
pulpcore.app.urls by using the router's register method during application setup.