Skip to main content

Django Building Blocks

Abstract Django base models (and model class factories) to act as building blocks for rapid development of Django database models

Quick start

pip install django-building-blocks

Rationale

django-building-blocks provides common design patterns and behaviours that repeat themselves during the development of django projects. The main aim of this package is to provide common interfaces for the development of django models. This portion of this library is inspired by Kevin Stone's excellent blog post Django Model Behaviors. The secondary aim of this library is to provide interfaces and mixins for Django admin classes, so you can add functionality to your admin pages really fast, without the need to Google solutions and look at Stackoverflow for answers.

By using this library you can create models in such a way to make their fields standard across your entire project and all your projects. For example:

class BlogPost(
    HasNameFactory.as_abstract_model(),
    HasDescription,
    HasHTMLBody,
    Publishable,
    models.Model
):
    pass

Note that we did not need to add anything to the body of the above model. This model is entirely composed of abstract models (and abstract model factories - more on this later). If you have another model:

class WebPage(
    HasNameFactory.as_abstract_model(),
    HasAutoSlugFactory.as_abstract_model(),
    HasHTMLBody,
    Publishable,
    models.Model
):
    pass

Note the similarity between the two models. Now instead of having to code the fields, associated properties and behaviors on each model individually, you can reuse them infinite times, and keep them standard across your project (and all your projects).

The admin class for BlogPost would look something like this:

@admin.register(BlogPost)
class BlogPostAdmin(
    PublishableAdmin,
    admin.ModelAdmin
):
    list_display = (
        *HasNameAdmin.list_display,
        *PublishableAdmin.list_display,
        ...
    )
    ...

Notice how we have composed each element in the admin using a concept called Admin Blocks. Each of the abstract classes in this library, have an associated Admin block class (which looks like a normal admin class, but usually isn't meant to be inherited), that enables you to define admin for their inheritors in a standard way. For example in the case of Publishable, you would probably like to show the publication status and date in list_display. Instead of having to remember to include both fields in all your admins, you can just include the Admin block in the way showed above and have the fields show up in the list table for all the inheritors of Publishable.

Details and classes provided

Note: Check the docstring under each class for their documentation.

Abstract models

Django Model Behaviors describes a design pattern for developing django models that makes them compositional. For example, your project might have the ability to post blog posts (BlogPost), and each post goes through 3 stages: Draft, Published, and Archived. In your project, your users might also have the ability to post shorter status updates (StatusUpdate), and you'd like those status updates to also go through a similar publishing pipeline. Furthermore, both BlogPost and StatusUpdate are timestamped with the date and time they are published.

As a seasoned developer, instead of coding the functionality on both models, you would create an abstract model, let's call it Publishable, and have both BlogPost and StatusUpdate inherit from it. Now you have abstracted away common functionality between your models, into the Publishable interface/abstract model. Not only this is DRY, but also if you like to make updates to how your publishing pipeline works, you can just update Publishable and both BlogPost and StatusUpdate would get updated with the new pipeline.

django-building-blocks provides a number of such abstract models:

Note: if you're coming from v0.0.x, take a look at this migration file to help you with writing migrations for your Archivable or Publishable models, as in v0.1.0 they have switched to use an integer status field.

Abstract model factories

Abstract model factories enable you to create abstract models on the fly. Abstract model factories enable you to modify the inherited fields dynamically from the same base class. For example, you might have a model that will have an email field. You can use HasEmailFactory.as_abstract_model() that returns an abstract model that can be inherited from. Now say you have another model that also has a email, but the email here is an optional field (blank=True). Instead of creating a whole new abstract model (like HasOptionalEmail), you can inherit from HasEmailFactory.as_abstract_model(optional=True) which will return an abstract model with the same email field, but this time the email field is optional.

Abstract model factories provided:

You can create your own abstract model factory by inheriting from building_blocks.models.factories.AbstractModelFactory. Check some of the implementations for an example.

Mixin model classes

Admin block classes

The following admins (called admin blocks) aren't usually meant to be inherited by your model's admin class. Instead, each field in the admin is used to create your desired admin class. For example:

# example/sample/admin.py

@admin.register(ArchivableHasUUID)
class ArchivableHasUUIDAdmin(
    ArchivableAdmin,  # Inheritable admin to add common functionality. More on this later. 
    admin.ModelAdmin
):
    search_fields = (
        *HasUUIDAdmin.search_fields,  # AdminBlock to assist in shaping the admin
    )
    list_display = (
        *HasUUIDAdmin.list_display,
        *ArchivableAdmin.list_display,
    )
    list_filter = (
        *ArchivableAdmin.list_filter,
    )

    readonly_fields = (
        *HasUUIDAdmin.readonly_fields,
        *ArchivableAdmin.readonly_fields,
    )
    fieldsets = (
        *HasUUIDAdmin.fieldsets,
        *ArchivableAdmin.fieldsets,
    )

As its name suggests, the model ArchivableHasUUID inherits from both Archivable and HasUUID and thus has fields form both. With admin blocks you can create ArchivableHasUUIDAdmin without mentioning individual fields from each class, adding to the conciseness of your code. It'll also make it hard to miss a field since the AdminBlock has the default and recommended fields for each admin field.

Available Admin Blocks:

Inheritable Admin block classes

Some Admin block classes are also meant to be inherited by your admin class. The usually provide functionality such as common admin actions to your admin.

Please note that the majority of the inheritable admins use django-object-actions to enable admin actions on objects' admin:change pages. To enable this functionality add 'django_object_actions' to your INSTALLED_APPS so your project can find the templates from django_object_actions which are used in rendering the buttons for the actions.

Mixin Admin classes

Admin inline mixins

When you need some fields on an inline admin to be readonly only for editing (equivalent of EditReadonlyAdminMixin), you have to split the interface into two inlines, one for adding which doesn't show any objects, and one for listing them, which has the readonly fields defined. The following classes facilitate this design pattern:

HTML render utilities

They are used in conjunction with @admin.display to render html such as anchor tags, or images on the admin.

Forms

UnrequiredFieldsForm and unrequire_form

Make fields that are usually required in a model form, be not required. Used in conjunction with HasAutoFields, since the fields that aren't required are auto set. Also used in conjunction with EditReadonlyAdminMixin to allow manual setting of a field upon creation.

Fields

Development and Testing

IDE Setup

Add the example directory to the PYTHONPATH in your IDE to avoid seeing import warnings in the tests modules. If you are using PyCharm, this is already set up.

Running the Tests

Install requirements

pip install -r requirements.txt

For local environment

pytest

For all supported environments

tox

Metadata

Release files for django-building-blocks 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-building-blocks 0.1.0
File Size Uploaded Provenance
django-building-blocks-0.1.0.tar.gz 23.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-building-blocks 0.1.0
File Interpreter ABI Platform
django_building_blocks-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 54.9 kB

Release files / django-building-blocks-0.1.0.tar.gz

Download URL django-building-blocks-0.1.0.tar.gz
Size 23.9 kB
Tags Source
SHA-256 checksum
How to use checksums
5f0fa507a185f82cda2d383a20fb55cd9db76630263a7a1ce7049b75707d62a2
BLAKE2b-256 checksum
How to use checksums
f7802eed2fa16f5641b656bb0f8df7169d9fc1c6f80f6a4893dc7d09f768a032
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.2 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.10

Release files / django_building_blocks-0.1.0-py3-none-any.whl

Download URL django_building_blocks-0.1.0-py3-none-any.whl
Size 31.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b8d7873bde0b0ed14438ecca271f06e3cb62d4e1511da8fb55b5b1cb8a9a0f1c
BLAKE2b-256 checksum
How to use checksums
ad26dbdf3c5dc8e7b6acadad63a52bad44dd8c082fc190bd0b5bfb7c67d78873
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.4.2 importlib_metadata/4.6.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.61.2 CPython/3.9.10

Security for django-building-blocks 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page