cs-djutils


Namecs-djutils JSON
Version 20250724 PyPI version JSON
download
home_pageNone
SummaryMy collection of things for working with Django.
upload_time2025-07-24 02:36:00
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseNone
keywords python3
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            My collection of things for working with Django.

*Latest release 20250724*:
model_batches_qs (and therefore also model_instances): after may also be a Model instance.

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 `QuerySet`s for batches of a `Model`

Short summary:
* `BaseCommand`: A drop in class for `django.core.management.base.BaseCommand` which subclasses `cs.cmdutils.BaseCommand`.
* `DjangoSpecificSubCommand`: A subclass of `cs.cmdutils.SubCommand` with additional support for Django's `BaseCommand`.
* `model_batches_qs`: A generator yielding `QuerySet`s which produce nonoverlapping batches of `Model` instances.
* `model_instances`: A generator yielding `Model` instances. This is a wrapper for `model_batches_qs` and accepts the same arguments, and some additional parameters.

Module contents:
- <a name="BaseCommand"></a>`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 optionsA 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):
              """ 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

  Usage summary:

      Usage: base [common-options...] .......
              Do the main thing.
        """
        ... do stuff based on the CLI args `argv` ...

*`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.
- <a name="DjangoSpecificSubCommand"></a>`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.
- <a name="model_batches_qs"></a>`model_batches_qs(model: django.db.models.base.Model, field_name='pk', *, after=None, chunk_size=1024, desc=False, exclude=None, filter=None, only=None, yield_base_qs=False) -> Iterable[django.db.models.query.QuerySet]`: A generator yielding `QuerySet`s which produce nonoverlapping
  batches of `Model` instances.

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

  See `model_instances` for an iterable of instances wrapper
  of this function, where you have no need to further amend the
  `QuerySet`s or to be aware of the batches.

  Parameters:
  * `model`: the `Model` to query
  * `field_name`: default `'pk'`, the name of the field on which
    to order the batches
  * `after`: an optional field value - iteration commences
    immediately after this value; this may also be a `Model` instance,
    in which case the value is obtained via `getattr(after,field_name)`
  * `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
  * `only`: optional sequence of field names for a Django query `.only()`
  * `yield_base_qs`: if true (default `False`) yield the base
    `QuerySet` ahead of the `QuerySet`s for each batch;
    this can be useful for a count or other preanalysis

  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 `QuerySet`s 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 ...
- <a name="model_instances"></a>`model_instances(model: django.db.models.base.Model, field_name='pk', prefetch_related=None, select_related=None, yield_base_qs=False, **mbqs_kw) -> Iterable[django.db.models.base.Model]`: A generator yielding `Model` instances.
  This is a wrapper for `model_batches_qs` and accepts the same arguments,
  and some additional parameters.

  If you need to extend the `QuerySet`s beyond what the
  `model_batches_qs` parameters support it may be better to use
  that and extend each returned `QuerySet`.

  If `yield_base_qs` is true (default `False`), yield the base
  `QuerySet` ahead of the model instances; this can be useful
  for a count or other preanalysis.

  Additional parameters beyond those for `model_batches_qs`:
  * `prefetch_related`: an optional list of fields to apply to
    each query with `.prefetch_related()`
  * `select_related`: an optional list of fields to apply to
    each query with `.select_related()`

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

# Release Log



*Release 20250724*:
model_batches_qs (and therefore also model_instances): after may also be a Model instance.

*Release 20250609*:
* model_batches_qs: new yield_base_qs=False parameter to yield the base QuerySet ahead of the batch QuerySets.
* model_instances: new yield_base_qs=False parameter to yield the base QuerySet ahead of the Model instances.

*Release 20250606*:
* model_batches_qs: new after=None parameter to indicate preiteration point.
* model_instances: new optional parameters prefetch_related and select_related to augument the querysets before iteration.

*Release 20250219*:
* model_batches_qs: accept a nonmapping for exclude= or filter= eg a Q() function.
* model_batches_qs: new optional only= parameter.

*Release 20250213*:
New model_instances() wrapper for model_batches_qs() returning an iterable of Model instances.

*Release 20250113.2*:
model_batches_qs: bugfix second and following QuerySet construction.

*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.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "cs-djutils",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "python3",
    "author": null,
    "author_email": "Cameron Simpson <cs@cskk.id.au>",
    "download_url": "https://files.pythonhosted.org/packages/05/ac/dee2f26d33f2f8fba3c33c723cfc8f1b7018cef61ceccabb6ab0a8b3cddb/cs_djutils-20250724.tar.gz",
    "platform": null,
    "description": "My collection of things for working with Django.\n\n*Latest release 20250724*:\nmodel_batches_qs (and therefore also model_instances): after may also be a Model instance.\n\nPresently this provides:\n* `BaseCommand`: a drop in replacement for `django.core.management.base.BaseCommand`\n  which uses a `cs.cmdutils.BaseCommand` style of implementation\n* `model_batches_qs`: a generator yielding `QuerySet`s for batches of a `Model`\n\nShort summary:\n* `BaseCommand`: A drop in class for `django.core.management.base.BaseCommand` which subclasses `cs.cmdutils.BaseCommand`.\n* `DjangoSpecificSubCommand`: A subclass of `cs.cmdutils.SubCommand` with additional support for Django's `BaseCommand`.\n* `model_batches_qs`: A generator yielding `QuerySet`s which produce nonoverlapping batches of `Model` instances.\n* `model_instances`: A generator yielding `Model` instances. This is a wrapper for `model_batches_qs` and accepts the same arguments, and some additional parameters.\n\nModule contents:\n- <a name=\"BaseCommand\"></a>`class BaseCommand(cs.cmdutils.BaseCommand, django.core.management.base.BaseCommand)`: A drop in class for `django.core.management.base.BaseCommand`\n  which subclasses `cs.cmdutils.BaseCommand`.\n\n  This lets me write management commands more easily, particularly\n  if there are subcommands.\n\n  This is a drop in in the sense that you still make a management command\n  in nearly the same way:\n\n      from cs.djutils import BaseCommand\n\n      class Command(BaseCommand):\n\n  and `manage.py` will find it and run it as normal.\n  But from that point on the style is as for `cs.cmdutils.BaseCommand`:\n  - no `argparse` setup\n  - direct support for subcommands as methods\n  - succinct option parsing, if you want additional command line options\n  - usage text in the subcommand method docstring\n\n  A simple command looks like this:\n\n      class Command(BaseCommand):\n\n          def main(self, argv):\n              \"\"\" Usage: {cmd} .......\n                    Do the main thing.\n              \"\"\"\n              ... do stuff based on the CLI args `argv` ...\n\n  A command with subcommands looks like this:\n\n      class Command(BaseCommand):\n\n          def cmd_this(self, argv):\n              \"\"\" Usage: {cmd} ......\n                    Do this.\n              \"\"\"\n              ... do the \"this\" subcommand ...\n\n          def cmd_that(self, argv):\n              \"\"\" Usage: {cmd} ......\n                    Do that.\n              \"\"\"\n              ... do the \"that\" subcommand ...\n\n  If want some kind of app/client specific \"overcommand\" composed\n  from other management commands you can import them and make\n  them subcommands of the overcommand:\n\n      from .other_command import Command as OtherCommand\n\n      class Command(BaseCommand):\n\n          # provide it as the \"other\" subcommand\n          cmd_other = OtherCommand\n\n  Option parsing is inline in the command. `self` comes\n  presupplied with a `.options` attribute which is an instance\n  of `cs.cmdutils.BaseCommandOptions` (or some subclass).\n\n  Parsing options is light weight and automatically updates the usage text.\n  This example adds command line switches to the default switches:\n  - `-x`: a Boolean, setting `self.options.x`\n  - `--thing-limit` *n*: an `int`, setting `self.options.thing_limit=`*n*\n  - `--mode` *blah*: a string, setting `self.options.mode=`*blah*\n\n  Code sketch:\n\n      from cs.cmdutils import popopts\n\n      class Command(BaseCommand):\n\n          @popopts(\n              x=None,\n              thing_limit_=int,\n              mode_='The run mode.',\n          )\n          def cmd_this(self, argv):\n              \"\"\" Usage: {cmd}\n                    Do this thing.\n              \"\"\"\n              options = self.options\n              ... now consult options.x or whatever\n              ... argv is now the remaining arguments after the optionsA drop in class for `django.core.management.base.BaseCommand`\n  which subclasses `cs.cmdutils.BaseCommand`.\n\n  This lets me write management commands more easily, particularly\n  if there are subcommands.\n\n  This is a drop in in the sense that you still make a management command\n  in nearly the same way:\n\n      from cs.djutils import BaseCommand\n\n      class Command(BaseCommand):\n\n  and `manage.py` will find it and run it as normal.\n  But from that point on the style is as for `cs.cmdutils.BaseCommand`:\n  - no `argparse` setup\n  - direct support for subcommands as methods\n  - succinct option parsing, if you want additional command line options\n  - usage text in the subcommand method docstring\n\n  A simple command looks like this:\n\n      class Command(BaseCommand):\n\n          def main(self, argv):\n              \"\"\" A command with subcommands looks like this:\n\n      class Command(BaseCommand):\n\n          def cmd_this(self, argv):\n              \"\"\" Usage: {cmd} ......\n                    Do this.\n              \"\"\"\n              ... do the \"this\" subcommand ...\n\n          def cmd_that(self, argv):\n              \"\"\" Usage: {cmd} ......\n                    Do that.\n              \"\"\"\n              ... do the \"that\" subcommand ...\n\n  If want some kind of app/client specific \"overcommand\" composed\n  from other management commands you can import them and make\n  them subcommands of the overcommand:\n\n      from .other_command import Command as OtherCommand\n\n      class Command(BaseCommand):\n\n          # provide it as the \"other\" subcommand\n          cmd_other = OtherCommand\n\n  Option parsing is inline in the command. `self` comes\n  presupplied with a `.options` attribute which is an instance\n  of `cs.cmdutils.BaseCommandOptions` (or some subclass).\n\n  Parsing options is light weight and automatically updates the usage text.\n  This example adds command line switches to the default switches:\n  - `-x`: a Boolean, setting `self.options.x`\n  - `--thing-limit` *n*: an `int`, setting `self.options.thing_limit=`*n*\n  - `--mode` *blah*: a string, setting `self.options.mode=`*blah*\n\n  Code sketch:\n\n      from cs.cmdutils import popopts\n\n      class Command(BaseCommand):\n\n          @popopts(\n              x=None,\n              thing_limit_=int,\n              mode_='The run mode.',\n          )\n          def cmd_this(self, argv):\n              \"\"\" Usage: {cmd}\n                    Do this thing.\n              \"\"\"\n              options = self.options\n              ... now consult options.x or whatever\n              ... argv is now the remaining arguments after the options\n\n  Usage summary:\n\n      Usage: base [common-options...] .......\n              Do the main thing.\n        \"\"\"\n        ... do stuff based on the CLI args `argv` ...\n\n*`BaseCommand.Options`*\n\n*`BaseCommand.SubCommandClass`*\n\n*`BaseCommand.add_arguments(self, parser)`*:\nAdd the `Options.COMMON_OPT_SPECS` to the `argparse` parser.\nThis is basicly to support the Django `call_command` function.\n\n*`BaseCommand.handle(*, argv, **options)`*:\nThe Django `BaseComand.handle` method.\nThis creates another instance for `argv` and runs it.\n\n*`BaseCommand.run_from_argv(argv)`*:\nIntercept `django.core.management.base.BaseCommand.run_from_argv`.\nConstruct an instance of `cs.djutils.DjangoBaseCommand` and run it.\n- <a name=\"DjangoSpecificSubCommand\"></a>`class DjangoSpecificSubCommand(cs.cmdutils.SubCommand)`: A subclass of `cs.cmdutils.SubCommand` with additional support\n  for Django's `BaseCommand`.\n\n*`DjangoSpecificSubCommand.__call__(self, argv: List[str])`*:\nRun this `SubCommand` with `argv`.\nThis calls Django's `BaseCommand.run_from_argv` for pure Django commands.\n\n*`DjangoSpecificSubCommand.is_pure_django_command`*:\nWhether this subcommand is a pure Django `BaseCommand`.\n\n*`DjangoSpecificSubCommand.usage_text(self, *, cmd=None, **kw)`*:\nReturn the usage text for this subcommand.\n- <a name=\"model_batches_qs\"></a>`model_batches_qs(model: django.db.models.base.Model, field_name='pk', *, after=None, chunk_size=1024, desc=False, exclude=None, filter=None, only=None, yield_base_qs=False) -> Iterable[django.db.models.query.QuerySet]`: A generator yielding `QuerySet`s which produce nonoverlapping\n  batches of `Model` instances.\n\n  Efficient behaviour requires the field to be indexed.\n  Correct behaviour requires the field values to be unique.\n\n  See `model_instances` for an iterable of instances wrapper\n  of this function, where you have no need to further amend the\n  `QuerySet`s or to be aware of the batches.\n\n  Parameters:\n  * `model`: the `Model` to query\n  * `field_name`: default `'pk'`, the name of the field on which\n    to order the batches\n  * `after`: an optional field value - iteration commences\n    immediately after this value; this may also be a `Model` instance,\n    in which case the value is obtained via `getattr(after,field_name)`\n  * `chunk_size`: the maximum size of each chunk\n  * `desc`: default `False`; if true then order the batches in\n    descending order instead of ascending order\n  * `exclude`: optional mapping of Django query terms to exclude by\n  * `filter`: optional mapping of Django query terms to filter by\n  * `only`: optional sequence of field names for a Django query `.only()`\n  * `yield_base_qs`: if true (default `False`) yield the base\n    `QuerySet` ahead of the `QuerySet`s for each batch;\n    this can be useful for a count or other preanalysis\n\n  Example iteration of a `Model` would look like:\n\n      from itertools import chain\n      from cs.djutils import model_batches_qs\n      for instance in chain.from_iterable(model_batches_qs(MyModel)):\n          ... work with instance ...\n\n  By returning `QuerySet`s it is possible to further alter each query:\n\n      from cs.djutils import model_batches_qs\n      for batch_qs in model_batches_qs(MyModel):\n          for result in batch_qs.filter(\n              some_field__gt=10\n          ).select_related(.......):\n              ... work with each result in the batch ...\n\n  or:\n\n      from itertools import chain\n      from cs.djutils import model_batches_qs\n      for result in chain.from_iterable(\n          batch_qs.filter(\n              some_field__gt=10\n          ).select_related(.......)\n          for batch_qs in model_batches_qs(MyModel)\n      ):\n              ... work with each result ...\n- <a name=\"model_instances\"></a>`model_instances(model: django.db.models.base.Model, field_name='pk', prefetch_related=None, select_related=None, yield_base_qs=False, **mbqs_kw) -> Iterable[django.db.models.base.Model]`: A generator yielding `Model` instances.\n  This is a wrapper for `model_batches_qs` and accepts the same arguments,\n  and some additional parameters.\n\n  If you need to extend the `QuerySet`s beyond what the\n  `model_batches_qs` parameters support it may be better to use\n  that and extend each returned `QuerySet`.\n\n  If `yield_base_qs` is true (default `False`), yield the base\n  `QuerySet` ahead of the model instances; this can be useful\n  for a count or other preanalysis.\n\n  Additional parameters beyond those for `model_batches_qs`:\n  * `prefetch_related`: an optional list of fields to apply to\n    each query with `.prefetch_related()`\n  * `select_related`: an optional list of fields to apply to\n    each query with `.select_related()`\n\n  Efficient behaviour requires the field to be indexed.\n  Correct behaviour requires the field values to be unique.\n\n# Release Log\n\n\n\n*Release 20250724*:\nmodel_batches_qs (and therefore also model_instances): after may also be a Model instance.\n\n*Release 20250609*:\n* model_batches_qs: new yield_base_qs=False parameter to yield the base QuerySet ahead of the batch QuerySets.\n* model_instances: new yield_base_qs=False parameter to yield the base QuerySet ahead of the Model instances.\n\n*Release 20250606*:\n* model_batches_qs: new after=None parameter to indicate preiteration point.\n* model_instances: new optional parameters prefetch_related and select_related to augument the querysets before iteration.\n\n*Release 20250219*:\n* model_batches_qs: accept a nonmapping for exclude= or filter= eg a Q() function.\n* model_batches_qs: new optional only= parameter.\n\n*Release 20250213*:\nNew model_instances() wrapper for model_batches_qs() returning an iterable of Model instances.\n\n*Release 20250113.2*:\nmodel_batches_qs: bugfix second and following QuerySet construction.\n\n*Release 20250113.1*:\nmodel_batches_qs: new exclude=dict and filter=dict optional parameters to filter before the slice.\n\n*Release 20250113*:\nmodel_batches_qs: improve the query which measures the current batch.\n\n*Release 20250111.1*:\nDocumentation update.\n\n*Release 20250111*:\nNew model_batches_qs() generator yielding QuerySets for batches of a Model.\n\n*Release 20241222.3*:\nAutocall settings.configure() if required because Django's settings object is a royal PITA.\n\n*Release 20241222.2*:\nBaseCommand.Options.settings: call settings.configure() on init if that has not already been done.\n\n*Release 20241222.1*:\nPlacate the dataclass - upgrade BaseCommand.Options.settings to be a field() with a default_factory.\n\n*Release 20241222*:\nBaseCommand.Options: include .settings with the public django.conf.settings names, mostly for cmd_info and cmd_repl.\n\n*Release 20241119*:\nNew DjangoSpecificSubCommand(CSBaseCommand.SubCommandClass) to include support for pure Django BaseCommands.\n\n*Release 20241111*:\nRename DjangoBaseCommand to just BaseCommand so that we go `from cs.djutils import BaseCommand`. Less confusing.\n\n*Release 20241110*:\nInitial PyPI release with DjangoBaseCommand, cs.cmdutils.BaseCommand subclass suppplanting django.core.management.base.BaseCommand.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "My collection of things for working with Django.",
    "version": "20250724",
    "project_urls": {
        "MonoRepo Commits": "https://bitbucket.org/cameron_simpson/css/commits/branch/main",
        "Monorepo Git Mirror": "https://github.com/cameron-simpson/css",
        "Monorepo Hg/Mercurial Mirror": "https://hg.sr.ht/~cameron-simpson/css",
        "Source": "https://github.com/cameron-simpson/css/blob/main/lib/python/cs/djutils.py"
    },
    "split_keywords": [
        "python3"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9cbc8f7c2a97243878b0d371d87d6b3c45d80a7195f5a51e0e433f9aeb11cbf9",
                "md5": "342c7ee3af2b27298380d57744eea98a",
                "sha256": "22e96a664fe2bda69640743f0dd1244d690402309d78a992bf6707802c5c0605"
            },
            "downloads": -1,
            "filename": "cs_djutils-20250724-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "342c7ee3af2b27298380d57744eea98a",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 8672,
            "upload_time": "2025-07-24T02:35:59",
            "upload_time_iso_8601": "2025-07-24T02:35:59.260205Z",
            "url": "https://files.pythonhosted.org/packages/9c/bc/8f7c2a97243878b0d371d87d6b3c45d80a7195f5a51e0e433f9aeb11cbf9/cs_djutils-20250724-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "05acdee2f26d33f2f8fba3c33c723cfc8f1b7018cef61ceccabb6ab0a8b3cddb",
                "md5": "721496fe44840791f63af4b5f530a376",
                "sha256": "a4546d73845ddfb502f425ef6480c803f150a6c457a82cbf83bd2329b46cd705"
            },
            "downloads": -1,
            "filename": "cs_djutils-20250724.tar.gz",
            "has_sig": false,
            "md5_digest": "721496fe44840791f63af4b5f530a376",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 6945,
            "upload_time": "2025-07-24T02:36:00",
            "upload_time_iso_8601": "2025-07-24T02:36:00.692254Z",
            "url": "https://files.pythonhosted.org/packages/05/ac/dee2f26d33f2f8fba3c33c723cfc8f1b7018cef61ceccabb6ab0a8b3cddb/cs_djutils-20250724.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-24 02:36:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "cameron-simpson",
    "github_project": "css",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "cs-djutils"
}
        
Elapsed time: 0.38877s