Name | cs-djutils JSON |
Version |
20250724
JSON |
| download |
home_page | None |
Summary | My collection of things for working with Django. |
upload_time | 2025-07-24 02:36:00 |
maintainer | None |
docs_url | None |
author | None |
requires_python | None |
license | None |
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"
}