Skip to main content

My collection of things for working with Django.

Project description

My collection of things for working with Django.

Latest release 20250113.1: model_batches_qs: new exclude=dict and filter=dict optional parameters to filter before the slice.

Presently this provides:

  • BaseCommand: a drop in replacement for django.core.management.base.BaseCommand which uses a cs.cmdutils.BaseCommand style of implementation
  • model_batches_qs: a generator yielding QuerySets for batches of a Model

Class BaseCommand(cs.cmdutils.BaseCommand, django.core.management.base.BaseCommand)

A drop in class for django.core.management.base.BaseCommand which subclasses cs.cmdutils.BaseCommand.

This lets me write management commands more easily, particularly if there are subcommands.

This is a drop in in the sense that you still make a management command in nearly the same way:

from cs.djutils import BaseCommand

class Command(BaseCommand):

and manage.py will find it and run it as normal. But from that point on the style is as for cs.cmdutils.BaseCommand:

  • no argparse setup
  • direct support for subcommands as methods
  • succinct option parsing, if you want additional command line options
  • usage text in the subcommand method docstring

A simple command looks like this:

class Command(BaseCommand):

    def main(self, argv):
        """ Usage: {cmd} .......
              Do the main thing.
        """
        ... do stuff based on the CLI args `argv` ...

A command with subcommands looks like this:

class Command(BaseCommand):

    def cmd_this(self, argv):
        """ Usage: {cmd} ......
              Do this.
        """
        ... do the "this" subcommand ...

    def cmd_that(self, argv):
        """ Usage: {cmd} ......
              Do that.
        """
        ... do the "that" subcommand ...

If want some kind of app/client specific "overcommand" composed from other management commands you can import them and make them subcommands of the overcommand:

from .other_command import Command as OtherCommand

class Command(BaseCommand):

    # provide it as the "other" subcommand
    cmd_other = OtherCommand

Option parsing is inline in the command. self comes presupplied with a .options attribute which is an instance of cs.cmdutils.BaseCommandOptions (or some subclass).

Parsing options is light weight and automatically updates the usage text. This example adds command line switches to the default switches:

  • -x: a Boolean, setting self.options.x
  • --thing-limit n: an int, setting self.options.thing_limit=n
  • --mode blah: a string, setting self.options.mode=blah

Code sketch:

from cs.cmdutils import popopts

class Command(BaseCommand):

    @popopts(
        x=None,
        thing_limit_=int,
        mode_='The run mode.',
    )
    def cmd_this(self, argv):
        """ Usage: {cmd}
              Do this thing.
        """
        options = self.options
        ... now consult options.x or whatever
        ... argv is now the remaining arguments after the options

BaseCommand.Options

BaseCommand.SubCommandClass

BaseCommand.add_arguments(self, parser): Add the Options.COMMON_OPT_SPECS to the argparse parser. This is basicly to support the Django call_command function.

BaseCommand.handle(*, argv, **options): The Django BaseComand.handle method. This creates another instance for argv and runs it.

BaseCommand.run_from_argv(argv): Intercept django.core.management.base.BaseCommand.run_from_argv. Construct an instance of cs.djutils.DjangoBaseCommand and run it.

Class DjangoSpecificSubCommand(cs.cmdutils.SubCommand)

A subclass of cs.cmdutils.SubCOmmand with additional support for Django's BaseCommand.

DjangoSpecificSubCommand.__call__(self, argv: List[str]): Run this SubCommand with argv. This calls Django's BaseCommand.run_from_argv for pure Django commands.

DjangoSpecificSubCommand.is_pure_django_command: Whether this subcommand is a pure Django BaseCommand.

DjangoSpecificSubCommand.usage_text(self, *, cmd=None, **kw): Return the usage text for this subcommand.

model_batches_qs(model, field_name='pk', *, chunk_size=1024, desc=False, exclude=None, filter=None) -> Iterable[django.db.models.query.QuerySet]

A generator yielding QuerySets which produce nonoverlapping batches of model instances.

Efficient behaviour requires the field to be indexed. Correct behaviour requires the field values to be unique.

Parameters:

  • model: the Model to query
  • field_name: default 'pk', the name of the field on which to order the batches
  • chunk_size: the maximum size of each chunk
  • desc: default False; if true then order the batches in descending order instead of ascending order
  • exclude: optional mapping of Django query terms to exclude by
  • filter: optional mapping of Django query terms to filter by

Example iteration of a Model would look like:

from itertools import chain
from cs.djutils import model_batches_qs
for instance in chain.from_iterable(model_batches_qs(MyModel)):
    ... work with instance ...

By returning QuerySets it is possible to further alter each query:

from cs.djutils import model_batches_qs
for batch_qs in model_batches_qs(MyModel):
    for result in batch_qs.filter(
        some_field__gt=10
    ).select_related(.......):
        ... work with each result in the batch ...

or:

from itertools import chain
from cs.djutils import model_batches_qs
for result in chain.from_iterable(
    batch_qs.filter(
        some_field__gt=10
    ).select_related(.......)
    for batch_qs in model_batches_qs(MyModel)
):
        ... work with each result ...

Release Log

Release 20250113.1: model_batches_qs: new exclude=dict and filter=dict optional parameters to filter before the slice.

Release 20250113: model_batches_qs: improve the query which measures the current batch.

Release 20250111.1: Documentation update.

Release 20250111: New model_batches_qs() generator yielding QuerySets for batches of a Model.

Release 20241222.3: Autocall settings.configure() if required because Django's settings object is a royal PITA.

Release 20241222.2: BaseCommand.Options.settings: call settings.configure() on init if that has not already been done.

Release 20241222.1: Placate the dataclass - upgrade BaseCommand.Options.settings to be a field() with a default_factory.

Release 20241222: BaseCommand.Options: include .settings with the public django.conf.settings names, mostly for cmd_info and cmd_repl.

Release 20241119: New DjangoSpecificSubCommand(CSBaseCommand.SubCommandClass) to include support for pure Django BaseCommands.

Release 20241111: Rename DjangoBaseCommand to just BaseCommand so that we go from cs.djutils import BaseCommand. Less confusing.

Release 20241110: Initial PyPI release with DjangoBaseCommand, cs.cmdutils.BaseCommand subclass suppplanting django.core.management.base.BaseCommand.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cs_djutils-20250113.1.tar.gz (5.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cs_djutils-20250113.1-py2.py3-none-any.whl (7.1 kB view details)

Uploaded Python 2Python 3

File details

Details for the file cs_djutils-20250113.1.tar.gz.

File metadata

  • Download URL: cs_djutils-20250113.1.tar.gz
  • Upload date:
  • Size: 5.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.7

File hashes

Hashes for cs_djutils-20250113.1.tar.gz
Algorithm Hash digest
SHA256 8a240eef3b4e6bf9ce4fd8af87d9a3b11ed4d046bc2d0fda03c6d21033af5743
MD5 c8d269d405401007f013c9e8266cc0f5
BLAKE2b-256 38379f974dc5256c91b10d503e02e7d58eeeebc5e7c26f772262f314b8c29414

See more details on using hashes here.

File details

Details for the file cs_djutils-20250113.1-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for cs_djutils-20250113.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 13e658e70d7fa6db1551365d5b6acabb556c4e5f7f12cb76411c3dc4fe89d89e
MD5 6cd01b0824528c34f28872810bfbe5b1
BLAKE2b-256 13ea6b78f0809c1355d507a4c21c1ffb6bee698a15346b56935a47a9a3076294

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page