pax_global_header00006660000000000000000000000064147760664050014531gustar00rootroot0000000000000052 comment=ad015513e5d8e8ee6ad748fca5f32ccf3fb3d5c5 django-extensions-django-extensions-ad01551/000077500000000000000000000000001477606640500211475ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/.editorconfig000066400000000000000000000004321477606640500236230ustar00rootroot00000000000000# https://editorconfig.org # Source: pydanny cookiecutter-django repo root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [*.{py,rst,ini}] indent_style = space indent_size = 4 [*.yml] indent_style = space indent_size = 2 django-extensions-django-extensions-ad01551/.github/000077500000000000000000000000001477606640500225075ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/.github/FUNDING.yml000066400000000000000000000003571477606640500243310ustar00rootroot00000000000000# These are supported funding model platforms github: [trbs] patreon: djangoextensions open_collective: djangoextensions custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=P57EJJ9QYL232'] thanks_dev: u/gh/trbs django-extensions-django-extensions-ad01551/.github/workflows/000077500000000000000000000000001477606640500245445ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/.github/workflows/compile_catalog.yml000066400000000000000000000007331477606640500304140ustar00rootroot00000000000000name: Compile Catalog on: pull_request: push: branches: - main jobs: compile_catalog: name: Compile Catalog runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python 3.x uses: actions/setup-python@v5 with: python-version: "3.13" - run: python -m pip install tox - name: Compile Catalog run: tox env: TOXENV: compile-catalog django-extensions-django-extensions-ad01551/.github/workflows/linters.yml000066400000000000000000000014121477606640500267450ustar00rootroot00000000000000name: Linters on: pull_request: push: branches: - main jobs: ruff: name: ruff runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python 3.x uses: actions/setup-python@v5 with: python-version: "3.13" - run: python -m pip install tox - name: tox ruff run: tox env: TOXENV: ruff mypy: name: mypy runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python 3.x uses: actions/setup-python@v5 with: python-version: "3.13" - run: python -m pip install tox - name: tox mypy run: tox env: TOXENV: mypy django-extensions-django-extensions-ad01551/.github/workflows/precommit.yml000066400000000000000000000007111477606640500272650ustar00rootroot00000000000000name: Pre-Commit Checks on: pull_request: push: branches: - main jobs: precommit: name: precommit runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python 3.x uses: actions/setup-python@v5 with: python-version: "3.13" - run: python -m pip install tox - name: tox precommit run: tox env: TOXENV: precommit django-extensions-django-extensions-ad01551/.github/workflows/pytest.yml000066400000000000000000000042731477606640500266250ustar00rootroot00000000000000name: PyTest on: pull_request: push: branches: - main jobs: pytest: runs-on: ubuntu-latest strategy: fail-fast: false max-parallel: 4 matrix: python-version: - 3.9 - "3.12" - "3.13" # 2023-06-05: disabled pypy3.9 due to asgiref typing error # - "pypy3.9" tox-django-version: - "42" - "51" - "52" # GH Actions don't support something like allow-failure ? # - "master" exclude: - python-version: "3.9" tox-django-version: "51" - python-version: "3.9" tox-django-version: "52" - python-version: "3.13" tox-django-version: "42" - python-version: "pypy3.9" tox-django-version: "42" steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: python -m pip install tox - name: Pytest run: tox -e py-dj${{ matrix.tox-django-version }} pytest-postgresql: runs-on: ubuntu-latest services: postgres: image: postgres env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: django_extensions_test ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: fail-fast: false max-parallel: 4 matrix: python-version: - "3.13" tox-django-version: - "52" steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - run: python -m pip install tox - name: Pytest run: tox -e py-dj${{ matrix.tox-django-version }}-postgres env: DJANGO_EXTENSIONS_DATABASE_HOST: localhost DJANGO_EXTENSIONS_DATABASE_USER: postgres DJANGO_EXTENSIONS_DATABASE_PASSWORD: postgres django-extensions-django-extensions-ad01551/.github/workflows/security.yml000066400000000000000000000007061477606640500271410ustar00rootroot00000000000000name: Check Security Vulnerabilities on: pull_request: push: branches: - main jobs: safety: name: safety runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python 3.x uses: actions/setup-python@v5 with: python-version: "3.13" - run: python -m pip install tox - name: safety run: tox env: TOXENV: safety django-extensions-django-extensions-ad01551/.gitignore000066400000000000000000000003301477606640500231330ustar00rootroot00000000000000*.py[cod] *.egg-info MANIFEST build dist docs/_build docs/_static venv* .tox *.bak .DS_Store .eggs/ .idea/ htmlcov/ .coverage .coverage.* .cache/ .mypy_cache/ .pytest_cache/ django-sample-app*/ *.swp *.swo *.sqlite3 django-extensions-django-extensions-ad01551/.pre-commit-config.yaml000066400000000000000000000024151477606640500254320ustar00rootroot00000000000000repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - id: trailing-whitespace - id: check-added-large-files args: - --maxkb=128 - id: check-ast - id: check-case-conflict - id: check-docstring-first - id: check-json - id: check-merge-conflict - id: check-xml - id: check-yaml - id: detect-private-key - id: end-of-file-fixer - id: mixed-line-ending args: [ '--fix=lf' ] description: Forces to replace line ending by the UNIX 'lf' character. - id: fix-encoding-pragma - id: name-tests-test args: - --django exclude: ^tests/testapp|^tests/management/|^tests/collisions/|^tests/pythonrc.py|^tests/runner.py - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.11.4 hooks: # Run the linter. - id: ruff # Run the formatter. - id: ruff-format args: - --diff - repo: https://github.com/tox-dev/pyproject-fmt rev: v2.5.0 hooks: - id: pyproject-fmt args: - --check - repo: https://github.com/trbs/pre-commit-hooks-trbs.git rev: 1.2.4 hooks: - id: forbid-executables exclude: manage.py|setup.py django-extensions-django-extensions-ad01551/.readthedocs.yml000066400000000000000000000011341477606640500242340ustar00rootroot00000000000000# Read the Docs configuration file for Sphinx projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Set the OS, Python version and other tools you might need build: os: ubuntu-24.04 tools: python: "3.12" # Build documentation in the "docs/" directory with Sphinx sphinx: configuration: docs/conf.py # Optional but recommended, declare the Python requirements required # to build your documentation # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html python: install: - requirements: docs/requirements.txt django-extensions-django-extensions-ad01551/.tx/000077500000000000000000000000001477606640500216605ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/.tx/config000066400000000000000000000003311477606640500230450ustar00rootroot00000000000000[django-extensions.master] file_filter = django_extensions/locale//LC_MESSAGES/django.po source_file = django_extensions/locale/en/LC_MESSAGES/django.po source_lang = en [main] host = https://www.transifex.com django-extensions-django-extensions-ad01551/CHANGELOG.md000066400000000000000000001324731477606640500227720ustar00rootroot00000000000000Changelog ========= See https://github.com/django-extensions/django-extensions/releases 4.1 --- Changes: - Add: show_permissions command (#1920) - Improvement: graph_models, style per app (#1848) - Fix: JSONField, bulk_update's (#1924) 4.0 --- Changes: - Improvement: Support for Python 3.12 and 3.13 - Improvement: Support for Django 5.x - Improvement: Switch from setup.{cfg,py} to pyproject.toml - Improvement: graph_models, Add option to display field choices in graph_models (#1854) - Improvement: graph_models, Add webp support (#1857) - Improvement: graph_models, Support for ordering edges on pydot/dot/graphviz (#1914) - Improvement: mail_debug, Update mail_debug command to use aiosmtpd (#1880) - Improvement: shell_plus, Improve error message for missing import (#1898) - Improvement: reset_db, Add reset_db support for django_tenants (#1855) - Improvement: docs, various improvements (#1852, #1888, #1882, #1901, #1912, #1913) - Improvement: jobs, Handle non-package modules when looking for job definitions (#1887) - Improvement: Add django-prometheus DB backends support (#1800) - Improvement: Call post_command when the command raises an unhandled exception (#1837) - Fix: sqldiff, do not consider ('serial', 'integer') nor ('bigserial', 'bigint') as a `field-type-differ` (#1867) - Fix: shell_plus, Fix start up order and add history (#1869) - Remove pipchecker and associated tests (#1906) - Following Django's release numbering style more closely (see https://docs.djangoproject.com/en/5.2/internals/release-process/ ) 3.2.3 ----- Changes: - Improvement: Add support for psycopg3 (#1814) - Improvement: runserver_plus, autoreload on template change (#1796) - Improvement: highlighting, test_should_highlight_bash_syntax_without_name to include whitespace spans (#1797) - Improvement: tests, add Python 3.11 to tox and actions to formally support python 3.11 (#1786) - Improvement: runserver_plus, Send the file_changed event when a reload is triggered (#1775) - Improvement: runserver_plus, Add REMOTE_USER to werkzeug environment (#1708) - Improvement: pipchecker, force pip to use pkg_resources as backend for resolving distributions (#1782) - Fix: Fix error with lack of PosixPath support (#1785) - Fix: Cleanup http: links (#1798) 3.2.1 ----- Changes: - Improvement: fix translation interpolation in prospective arabic translations (#1740) - Improvement: runserver_plus, Add option to ignore files on runserver_plus reload (#1762) - Improvement: docs: Fix a few typos (#1764) (#1751) - Improvement: drop python 3.5 as it is EOL (#1735) - Improvement: sqldiff, Added support for meta indexes and constraints in sqldiff. (#1726) - Improvement: show_urls, Ensure consistent output in show_urls for django 4.0+ (#1759) - Fix: dumpscript, make_aware should not be called if aware already (#1745) - Fix: Use list values for requires_system_checks (#1736) 3.2.0 ----- Changes: - Improvement: Django 4 support - Improvement: Accept both --no-input and --noinput - Improvement: sqldsn, Added more styles to the sqldsn management command - Improvement: graph_models, Flag for to color code relations based on on_delete - Improvement: graph_models, Add --relation-fields-only flag - Improvement: RandomCharField, allow keeping default values - Fix: HexValidator, Max length validation - Fix: runserver_plus, Fix KeyError: 'werkzeug.server.shutdown' - New: managestate, Saves current applied migrations to a file or applies migrations from file 3.1.5 ----- Changes: - Fix: pipchecker, crude way slow down to avoid HTTPTooManyRequests - Fix: pipchecker, fix for removed get_installed_distributions function 3.1.4 ----- Changes: - Fix: set_default_site, improve django.contrib.sites application detection - Improvement: documentation, Fix name of mixin in docs - Improvement: mypy, type ignore backwards compatible imports - Improvement: graph_models, add --rankdir to change graph direction - Improvement: runserver_plus, Add --sql-truncate cli modifier - Improvement: shell_plus, Add --sql-truncate cli modifier 3.1.3 ----- Changes: - Fix: Django 3.2, Run tests against Django 3.2 - Fix: Django 3.2, Handle warnings for default_app_config (#1654) - Fix: sqldiff, Fix for missing field/index in model case 3.1.2 ----- Changes: - Improvement: shell_plus, not save ipython history when using Jupyter - Improvement: docs, fix spelling mistakes - Improvement: tests, move to Github Actions instead of Travis - Improvement: drop_test_database, delete all cloned test databases (#1637) - Improvement: setup.py, Added minimum Django>=2.2 version to PyPI package - Improvement: shell_plus, fix --command globals / locals error 3.1.1.post1 ----------- Changes: - Improvement: setup.py, Added minimum Django>=2.2 version to PyPI package 3.1.1 ----- Changes: - Improvement: graph_models, add option --app-labels - Improvement: shell_plus, update shell_plus for jupyterlab 3 - Improvement: tests, add Python 3.9 3.1.0 ----- Changes: - Improvement: pipchecker, sleep 60s if pypi raises a fault - Improvement: add django_zero_downtime_migrations to list of supported postgresql engines - Improvement: use list of supported database engines from settings for all database commands - Improvement: reset_db, documentation - Fix: tests, Python 3.9 fixes for some tests - Fix: runserver_plus, parsing of RUNSERVER_PLUS_EXTRA_FILES 3.0.9 ----- Changes: - Improvement: runserver_plus, survive syntax and configuration errors part II - Improvement: tests, refactor test runner - Improvement: sqlcreate, support postgresql unix domain socket 3.0.8 ----- Changes: - Improvement: setup.cfg, remove universal flag from wheel, we only support Python 3 and up - Improvement: sqlcreate, fixed mentioned of old syncdb - Fix: runserver_plus, stop catching SyntaxError since reload for it was not working properly 3.0.7 ----- Changes: - Improvement: runserver_plus, gh #1575 survive syntax and configuration errors - Improvement: runscript, use exit-code 1 if script is not found 3.0.6 ----- Changes: - Improvement: runscript, add --continue-on-error unless set runscript will exit on errors - Improvement: runscript, allow to return exit-code - Improvement: runscript, support raise CommandError(... returncode=...) - Improvement: runscript, run Django checks() and check_migrations() before executing scripts - Improvement: shell_plus, set application name on all postgresql backends 3.0.5 ----- Changes: - Fix: runserver_plus, exceptions must derive from BaseException error 3.0.4 ----- Changes: - Various cleanups - Deprecated using `--router` instead use `--database` - Locales: Indonesian and Polish, updated - Improvement: show_dsn, fix crash with django-postgres-extra - Improvement: print_settings, added wildcard support - Improvement: print_settings, added --fail option - Improvement: delete_squashed_migrations, add --database option - Improvement: runserver_plus, added RUNSERVER_PLUS_EXTRA_FILES setting - Improvement: runserver_plus, added runserver_plus_started signal 3.0.3 ----- Changes: - New: InternalIPS, allows to specify CIDRs for INTERNAL_IPS - Docs: restructure toctree 3.0.2 ----- Changes: - Fix: shell_plus, fix honouring SHELL_PLUS in settings.py 3.0.1 ----- Changes: - Fix: setup.py, add python_requires and remove legacy trove classifiers 3.0.0 ----- This is the first Django Extensions release which only targets Django 2.2 and above. It drops official support for Python 2.7. Changes: - Removal of Python 2 support - Removal of deprecated keyczar encrypted fields EncryptedTextField and EncryptedCharField - Removal of deprecated passwd command - Removal of truncate_letters filter - Change: TimeStampedModel; Removed default ordering on abstract model - New: DjangoExtensionsConfig AppConfig - New: shell_plus, JupyterLab support - New: list_signals, List all signals by model and signal type - Improvement: shell_plus, use -- to directly pass additional arguments to Jupyter - Improvement: shell_plus, improvements to MySQL support - Improvement: jobs, use logging to record errors - Improvement: syncdata, added --remove-before flag - Improvement: graph_models, add field and model to template context - Fix: syncdata, fix non existent field in fixture data - Fix: pipchecker, compatibility with pip 20.1 2.2.9 ----- Changes: - Fix: shell_plus, move notebook down the list of preferred shells - Fix: sqldiff, fix KeyError when detecting missing (unique) indexes - Improvement: encrypted fields, make it harder to use deprecated keyczar fields - Locale: Removed empty localizations 2.2.8 ----- Changes: - Locale: zh_Hans, removed as it generated UnicodeDecodeError errors (#1478) 2.2.7 ----- Changes: - Improvement: shell_plus, #865 always add manage.py basedir to path for notebook kernel - Improvement: docs, add zh-Hans locale - Improvement: runserver_plus, fix broken import for werkzeug v1.0.0 - Improvement: runserver_plus, #1461 fix always trying to load StaticFilesHandler - Improvement: pipchecker, #1471 fix import of PipSession 2.2.6 ----- Changes: - Improvement: travis, update pypy and pypy3 versions - Improvement: shell_plus, ability to print location/traceback besides sql - Improvement: runserver_plus, ability to print location/traceback besides sql - Improvement: UniqueFieldMixin, Support Django 2.2 UniqueConstraint.condition - Improvement: DEFAULT_MYSQL_ENGINES, add mysql.connector.django - Improvement: shell_plus, allow setting SHELL_PLUS="notebook" - Improvement: shell_plus, add -c/--command to shell_plus mirroring django's shell command - Fix: shell_plus, fix postgresql debug wrapper on django 3.0 or higher - Fix: runserver_plus, fix postgresql debug wrapper on django 3.0 or higher 2.2.5 ----- Changes: - Improvement: travis, add Python 3.8 - Improvement: setup.py, update classifiers 2.2.4 ----- Changes: - Improvement: RandomCharField, Support unique_together - Improvement: export_emails, add settings for overriding queryset fields, order_by and the full_name function 2.2.3 ----- Changes: - Fix: admin widgets, fix import of static template tag (part 2) 2.2.2 ----- Changes: - Fix: autoslugfield, find unique method overrideable - Fix: notes, do not replace dot in template dirs - Fix: admin widgets, fix import of static template tag - Improvement: print_user_for_session, use session backend - Improvement: sqlcreate, postgis support - Improvement: graph_models, permit combination of includes and excludes - Improvement: Adds missing GIS engine to DEFAULT_MYSQL_ENGINES - Improvement: sqldiff, use lowercase field names in MySQL - Improvement: sqldiff, mysql code could duplicate AUTO_INCREMENT and UNSIGNED statements 2.2.1 ----- Changes: - Fix: tests, support for newer versions of pytest - Fix: tests, disable test with drf dependency for older python versions 2.2.0 ----- Changes: - Fix: removing wrongly released text_tags template - Fix: graph_models, support for Python <3.6 - Improvement: ForeignKeySearchInput, wrap media files in static() - Improvement: UniqField, added tests - Improvement: dumpscript, fix orm_item_locator to use dateutil - Improvement: graph_models, added argument to change arrow_shape 2.1.9 ----- Changes: - Fix: show_urls, fix for traceback on multi language sites - Improvement: reset_db, fix typo's in help test 2.1.8 ----- Changes: - New: HexValidator, validate hex strings - Improvement: reset_db, move settings to `django_settings.settings` which makes it easier to override. - Improvement: AutoSlugField, extend support for custom slugify function - Fix: runprofileserver, fix autoreloader for newer Django versions 2.1.7 ----- Changes: - New: test, many many more tests :-) thanks everybody - New: docs, many documentation updates - New: graph_model, add simple theming support and django2018 theme - Improvement: ModificationDateTimeField, make modificationfield name modifiable - Improvement: graph_model, option to not showrelations labels in the graph - Improvement: reset_db, allow to override list of backends for database engines - Improvement: reset_db, add psqlextra backend - Improvement: runserver_plus, idle support - Improvement: generate_secret_key, removed get_random_string in favour of get_random_secret_key - Improvement: update_permissions, add create-only and update-only flags - Improvement: update_permissions, update changed names of permission to match correct permission name - Improvement: syncdata, add --database option - Improvement: runscript, allow to override RUNSCRIPT_SCRIPT_DIR - Fix: create_command, fix mknod error on macos - Fix: runserver_plus, fix in resolving ssl certificate path - Fix: sqldiff, fix hstorefield - Deprecate: truncate_letters, use Django's truncatechars - Deprecate: passwd, use Django's changepassword - Deprecate: Keyczar encrypted fields, Keyczar is abandoned / deprecated 2.1.6 ----- Changes: - Fix: runserver_plus, auto_reloader fix for compatibility with Django 2.2 - New: test, many many more tests :-) thanks @kuter 2.1.5 ----- Changes: - New: ipdb, pdb and wdb filters - Fix: ForeignKeySearchInput, error with widget render(...) parameters on Django 2.1 - Fix: pipchecker, unsupported format string passed to NoneType.format error - Tests: bunch of new test cases 2.1.4 ----- Changes: - Fix: null_technical_500_response, handle function-based middleware - Fix: shell_plus, fix #1261 check for --notebook-dir=... argument style - Fix: graph_models, Excluded models displayed as an underscore - Fix: set_fake_password, requires_model_validation has been replaced with requires_system_checks since 1.9 - Docs: admin_generator, new documentation and examples - Improvement: JSONField, use new from_db_value syntax on Django 2 and up - Improvement: EncryptedTextField, use new from_db_value syntax on Django 2 and up - Improvement: graph_models, add --dot option - Improvement: graph_models, allow to redirect (text) output to file - Improvement: sqldiff, better support for indexes, index_together and unique_together 2.1.3 ----- Changes: - Fix: Readme, add direct link to screencast video - Fix: graph_models, regression under Python 2 - Fix: ForeignKeyAutocompleteAdmin, 2.0.8 breaks ForeignKeyAutocompleteAdmin - Fix: AutoSlugField, fix regression when copying an autoslug model require the explicit clearing of the slug if it needs to be recalculated - Fix: technical_response, check for AttributeError - Improvement: graph_models, Add feature disable_abstract_fields - Improvement: AutoSlugField, Add overwrite_on_add - Improvement: runscript, Improve module existence test in runscript 2.1.2 ----- Changes: - Fix: AutoSlugField, fix check on list or tuple type 2.1.1 ----- Removed support for Django versions before 1.11 Changes: - Fix: foreignkey_searchinput, remove unnecessary img tag - Fix: sqldiff, fix deprecated get_indexes call - Fix: AutoSlugField, check that any non-callable value passed to populate_from is a string type - Fix: tests, fix ChangingDirectoryTests: cd back in tearDown - Fix: show_template_tags, should handle AppConfig class in INSTALLED applications - Improvement: runserver_plus, reduce reraise pollution in traceback page - Improvement: dumpscript, prevent many2many field with custom intermediate models to be added directly on the parent model - Docs: fix typos 2.1.0 ----- Changes: - Fix: travis 2.0.9 ----- Changes: - Improvement: use README as project description on PyPI 2.0.8 ----- Please stop using ForeignKeyAutocompleteAdmin edition :-) Changes: - Fix: special markers in runserver_plus.rst - Fix: shell_plus, refactor reading pythonrc file outside of exec(compile(...)) - Fix: reset_db, fix default utf8 support - Fix: autoslugfield, Fix autoslug generation when existing model is copied - Improvement: Cleanup management commands options after argparse migration #916 - Improvement: sqldiff, add more tests - Improvement: sqldiff, add DurationField and SearchVectorField - Improvement: shell_plus, add more tests - Improvement: shell_plus, backport macos fix for tab completion - Improvement: clear_cache, add --all option - Improvement: pipchecker, treat dev versions as unstable - Deprecation: ForeignKeyAutocompleteAdmin, Django 2.0 has similar capabilities, which are much better supported. 2.0.7 ----- Changes: - Fix: pipchecker, pip 10.0.0 compatibility - Fix: sqldiff, improve support of GIS fields by using Django introspection - Fix: shell_plus, fix bug in windows when PYTHONPATH is defined - Fix: shell_plus, Call execute on CursorWrapper instead of directly on cursor to ensure wrappers are run - Fix: runserver_plus, Call execute on CursorWrapper instead of directly on cursor to ensure wrappers are run - Improvement: sqldiff, drop old compatibility code - Improvement: ForeignKeyAutocompleteAdminMixin, improvements for Django >1.9 2.0.6 ----- Changes: - Fix: shell_plus, Fix of deprecation warning in collision resolvers 2.0.5 ----- Changes: - Improvement: setup.py, Use PEP 508 when setuptools is version 36 or higher should fix issues with pipenv - Fix: docs, Docs should show that django 2.0 is supported 2.0.4 ----- Changes: - Fix: setup.py, fix installation of typing in python < 3.5 2.0.3 ----- Changes: - Fix: shell_plus, python 2.7 support broken due to use of Python3 super() 2.0.2 ----- Changes: - Improvement: sqldiff, add --include-defaults to include default value in missing field for sqldiff #1064 2.0.1 ----- Changes: - Fix: setup.py, do not include `typing` requirement in recent versions of Python - Improvement: shell_plus, add support for using -- to pass cli argument directly to underlying python shell implementation - New: generate_password, Generates a new password based on `BaseUserManager.make_random_password` 2.0.0 ----- Changes: - Fix: runserver_plus, for 1.11 still using MIDDLEWARE_CLASSES - Fix: show_urls, Fix display in Django 2.0 - Fix: validate_templates, remove realpath in validate_templates - Fix: sqldiff, bug with including proxy models in sqldiff output - Improvement: shell_plus, allow configurating of sqlparse formatting and pygments formatting - Improvement: shell_plus, add collision resolvers based on app label - Improvement: shell_plus, automatic importing of subclasses defined in SHELL_PLUS_SUBCLASSES_IMPORT - New: reset_schema, simple command to recreate public schema in PostgreSQL - Docs: fix links to Werkzeug documentation 1.9.9 ----- Changes: - Fix: runserver_plus, fix for Django 2.0 middleware handling - Fix: shell_plus, fixed app_name resolving - Fix: AutoSlugField, deconstruct did not match construction values - Fix: runjob, not compatible with apps that use AppConfig in INSTALLED_APPS - Improvement: runserver_plus, added configuring paths to certificates - Improvement: sample.py template, add newline to avoid linter warnings - Improvement: jobs, add integration tests for runjob and runjobs management commands - New: merge_model_instances, new management command for de-duplicating model instances 1.9.8 ----- Changes: - Fix: show_urls, fix for Django 2.0 (Locale URL Resolvers are still broken) - Fix: runserver_plus, fix rendering of ipv6 link - Improvement: validate_templates, allow relative paths - Improvement: validate_templates, automatically include app templates - Improvement: pip_checker, could not find some packages - Docs: shell_plus, `--print-sql` usage clearification 1.9.7 ----- This release add checking types with MyPy to the test suite. At this point only a few lines of code are explicitly typed. Changes: - Improvement: shell_plus, Collision resolver implemented. - Improvement: shell_plus, Skipping all models importing feature added. - Improvement: runscript, Script execution directory policy feature added. - django-extensions now requires the [typing](https://pypi.python.org/pypi/typing) package. 1.9.6 ----- Fix boo-boo with release version in django_extensions/__init__.py 1.9.4 ----- Changes: - Fix missing test case 1.9.3 ----- Changes: - Tests: shell_plus, simple test for get_imported_objects 1.9.2 ----- Changes: - Fix: mail_debug, regression in mail_debug for older Pythons - Fix: shell_plus, SyntaxError on exec(), python compatibility - Fix: ForeignKeyAutocompleteAdminMixin, use text/plain 1.9.1 ----- Changes: - Fix: graph_models, fix json option - Fix: runserver_plus, avoid duplicate messages logged to console - Fix: mail_debug, python3 fix - Improvement: sqldiff, basic support for array types in postgresql - Improvement: runscript, handle import errors better - Docs: updated documentation for model extensions 1.9.0 ----- The change to --no-startup/--use-pythonrc in `shell_plus` changes the default behaviour to automatically load PYTHONSTARTUP and ~/.pythonrc.py unless --no-startup is set. Changes: - Fix: pipchecker, fix up-to-date check for Github sha commits - Fix: JSONField, fix handling to_python() for strings with tests - Fix: print_settings, fix print_settings to receive positional args - Improvement: shell_plus, update PYTHONSTARTUP / pythonrc handling to match Django - Improvement: shell_plus, added new 1.11 features from django.db.models to shell_plus import list - Improvement: runserver_plus, startup message now accounts for https - Docs: jobs, improve documentation about jobs scheduling - Docs: admin, add documentation for ForeignKeyAutocompleteStackedInline and ForeignKeyAutocompleteTabularInline - Docs: fix typos 1.8.1 ----- Changes: - Build: use tox's 'TOXENV' environment variable - Fix: resetdb, fix problem that 'utf8_support' option is ignored - Improvement: export_emails, moved custom csv UnicodeWriter (for py2) into compat.py - Translations: pt, removed since it was causing issues with the builds if anybody wants to update and fix it that would be much appreciated ! 1.8.0 ----- UUIDField has been removed after being deprecated. Deprecation schedule for JSONField has been removed after requests from the community. Changes: - Fix: runserver_plus, fixed Python 3 print syntax - Fix: sqldiff, Use 'display_size', not 'precision' to identify MySQL bool field - Fix: export_emails, fix and refactor the command and all its output options - Improvement: tests, added Python 3.6 and PyPy3.5-5.8.0 - Improvement: clear_cache, add --cache option to support multiple caches - Improvement: runserver_plus, limit printing SQL queries to avoid flooding the terminal - Improvement: shell_plus, limit printing SQL queries to avoid flooding the terminal - Docs: graph_models, document including/excluding specific models - Docs: shell_plus, added PTPython 1.7.9 ----- Changes: - Fix: AutoSlugField, foreignkey relationships - Fix: shell_plus, supported backends 'postgresql' for set_application_name - Improvement: various commands, Add syntax highlighting when printing SQL - Improvement: pipchecker, treat rc versions as unstable - Improvement: shell_plus, allow to subclass and overwrite import_objects - Improvement: shell_plus, fix SHELL_PLUS_PRE_IMPORTS example - Improvement: setup.py, fix and unify running tests - Improvement: runserver_plus, add RUNSERVERPLUS_POLLER_RELOADER_TYPE setting - Improvement: generate_secret_key, use algorithm from django - Docs: fix grammar and spelling mistakes 1.7.8 ----- Changes: - Improvement: django 1.11, add testing for Django 1.11 - Improvement: pipchecker, make it possible to parse https github urls - Improvement: unreferenced_files, make command much faster by using set() - Docs: add undocumented commands - Docs: shell_plus, additional documentation for referencing nested modules - Fix: sync_s3, fix exclusion of directories - Fix: runprofileserver, fix ip:port specification - Fix: runprofileserver, support --nothreading 1.7.7 ----- Changes: - Improvement: admin_generator, use decorator style for registering ModelAdmins. - Improvement: sqldiff, quote tablename for PRAGMA in sqlite - Fix: graph_models, Fix `attributes` referenced before assignment - Fix: pipchecker, Fix AttributeError caused by missing method 1.7.6 ----- Changes: - Improvement: sqldiff, ignore proxy models in diff (with cli option to include them if wanted) 1.7.5 ----- Changes: - New: ForeignKeyAutocompleteAdmin, Add autocomplete for inline model admins - Improvement: graph_models, Rewrite modelviz module from method to class based processor - Improvement: db fields, make MAX_UNIQUE_QUERY_ATTEMPTS configurable per field and via settings - Improvement: runserver_plus, Added nopin option to disable pin - Fix: graph_models, Support PyDot 1.2.0 and higher - Fix: shell_plus, Fix that aliases from SHELL_PLUS_MODEL_ALIASES were not applied - Removed: validate_templatetags, remove support for pre django-1.5 style {% url %} tags - Cleanup: removing support for end-of-life Python 3.2 - Docs: simplify installation instructions - Docs: fix example for NOTEBOOK_ARGUMENTS - Docs: Remove extraneous '}' characters from shell_plus docs 1.7.4 ----- Changes: - Improvement: show_urls, support --no-color option - Fix: notes, Fix reading templates setting after django 1.8 - Fix: create_app, Fixed typo in deprecation warning - Fix: shell_plus, Use new location for url reverse import - Docs: some commands where missing from the docs - Docs: runscript, added documentation for --traceback 1.7.3 ----- Changes: - Fix: ForeignKeySearchInput, fix bug with constructing search_path urls - Docs: runscript, fix runscript example - Deprecation: JSONField, Django now includes JSONField our field is now deprecated 1.7.2 ----- Changes: - Fix: passwd, Update passwd command up to Django>=1.8 - Improvement: shell_plus, add settings.SHELL_PLUS_PRINT_SQL config option - Improvement: shell_plus, allow to specifies the connection file to use if using the --kernel option 1.7.1 ----- Changes: - Fix: sqldiff, fix optional app_label arguments - Fix: runscript, remove args from command class - Doc: runscript, remove = from --script-args example 1.7.0 ----- The "Letting go of the past" release. From this moment on Django Extensions requires version 1.8 or higher. A lot of work has been done to remove old backwards compatibility code and make sure that Django Extensions uses the current Django API's. This should result in better and easier to maintain code (and hopefully less bugs :). This release touches a lot of code if you have any issues please report them at [https://github.com/django-extensions/django-extensions/issues] We still need more tests to make sure we don't break people's projects when refactoring. If you have some spare time please contribute tests ! Changes: - Cleanup: removing backwards compatibility hacks for (now) unsupported versions of Django - Cleanup: use six instead of home grown functions - Fix: AutoSlugField, allow_duplicates didn't set slug value to model instance - Fix: MongoDB fields, verbose_name on mongoengine fields does not seem to be supported - Fix: MongoDB fields, fix relative import problem with json.py - Improvement: Start using pre-commit - Improvement: syncdata, Replace custom transaction logic with transaction.atomic - Improvement: Django 1.10, use from_db_value instead of models.SubfieldBase - Improvement: print_user_session, support for non standard user model - Improvement: widont, tests to work with py2 and py3 - Improvement: runserver_plus, prevent 2nd reload of debugger on runserver_plus - Improvement: runserver_plus, prevent killing the server when request.META values are evaluated - Improvement: reset_db, add argument to make closing sessions optional - Improvement: print_settings, Fix positional arguments - Improvement: runscript, migrate to argparse and add_arguments - Improvement: graph_models, do not rely on .models_module for inclusion in output - Improvement: jsonfield, fix issues with mutable default - Docs: Convert readthedocs links for their .org -> .io migration 1.6.7 ----- Changes: - Fix: describe_form, fix No module named 'django.db.models.loading' error - Improvement: shell_plus, Add a setting to prefix all models in an application #887 - Improvement: pipchecker, check for requirements-{dev,prod}.txt as well - Docs: pipchecker, update documentation 1.6.6 ----- Changes: - Fix: admin_generator, fix for using all apps in Django <1.7 - Fix: dump_script, fix for using all apps in Django <1.7 - Fix: UniqueFieldMixin, resolve get_fields_with_model deprecation Django 1.10 - Fix: runprofileserver, Fix call grind format to enable source code navigation in qcachegrind. - Docs: runserver_plus, add a little note about the debugger PIN. 1.6.5 ----- Bumped version number since PyPi returns 500 errors while uploading packages :( 1.6.4 ----- Changes: - Fix: jobs cache_cleanup, use `caches` instead of deprecated `get_cache` - Fix: ModificationDateTimeField, missing default value for `update_modified` - Fix: modelviz, use get_model_compat and look up missing app_label - Fix: modelviz, use get_models_for_app instead of get_models_compat - Fix: dumpscript, use `list_app_labels` instead of `get_apps` when no app_labels are given - Improvement: compat.py, move code from try to else block for Django 1.7+ - Docstring: get_models_for_app, clearify argument 1.6.3 ----- Bumped version number for incomplete PyPi upload 1.6.2 ----- The long over due release :-) Changes: - Fix: JsonFields, do not parse floats as decimals. This fixes bugs that causes them to be returned as strings after multiple saves. Note that this can be backwards incompatible ! - Fix: use add_arguments() instead of option_list (Django 1.10) - Fix: create_command, Django 1.9 fixes - Fix: create_jobs, Django 1.9 fixes - Fix: RandomCharField, when not unique get the first value from the generator - Fix: graph_models, render() must be called with a dict - Fix: graph_models, use force_bytes fixes command for Python 3 - Fix: graph_models, fix django 1.6 compatibility for strings defined relation - Fix: graph_models, fix settings.GRAPH_MODELS breaking the command - Fix: graph_models, add support for lazy relationships - Fix: ForeignKeyAutocompleteAdmin, url_patterns is just a list (Django 1.9+) - Fix: ForeignKeySearchInput, use url reversing instead of hardcoded paths - Fix: find_template, Fix for Django 1.8+ - Fix: admin_generator, incompatible "default" identifier raising TypeError - Improvement: show_urls, add json and pretty-json formatting - Improvement: runserver_plus, add support for whitenoise - Improvement: ModificationDateTimeField, add parameter to preserve timestamps on save - Improvement: runprofileserver, raise command error when hotspot is not available - Improvement: reset_db, better parsing of mysql cnf file - Improvement: restored coverage for Python 3.2 - Improvement: pep8 fixes, remove unused shims & imports & commented code - Improvement: graph_models, JSON output - Improvement: graph_models, add wildcard filters - Docs: removed text on donations, the hope was that we could generate some funds to have more consistent development and outreach. - Docs: runserver_plus, added some documentation about LOGGING - Docs: runscript, update documentation to match Django tutorial for Django 1.8+ - Docs: runprofileserver, add documentation on profiler choices - Docs: update_permissions, add basic documentation for command 1.6.1 ----- Changes: - Revert: JSONField, revert Django 1.9 fix as it breaks the field (ticket #781) 1.6.0 ----- Changes: - Fix: Django 1.9 compatibility - New: runserver_plus, add --startup-messages to control when to show them - New: added support for Python 3.5 - Improvement: show_template_tags, renamed from show_templatetags for consistency - Removed: jquery library (after dropping support for Django 1.5) 1.5.9 ----- Changes: - Fix: wheel still had the old migrations directory in the package 1.5.8 ----- Changes: - Fix: migrations, fix BadMigrationError with Django 1.8+ - Fix: reset_db, Django 1.8+ compatibility fix - Fix: runserver_plus, fix signature of null_technical_500_response for Django 1.8+ - Fix: graph_models, use force_bytes instead of .decode('utf8') - Improvement: print_settings, add format option to only print values - Improvement: print_settings, add format option for simple key = value text output - Improvement: email_export, documentation updates - Improvement: shell_plus, auto load conditional db expressions Case and When 1.5.7 ----- Changes: - Fix: CreationDateTimeField, migration error - Fix: ModificationDateTimeField, migration error - Fix: shell_plus, options is not always in db config dictionary - Fix: admin filters, contrib.admin.util fallback code - Fix: graph_models, correctly support parsing lists for cli options - Improvement: sqldsn, support postfix - Improvement: utils, remove get_project_root function 1.5.6 ----- Changes: - New: RandomCharField, prepopulates random character string - New: (Not)NullFieldListFilter, filters for admin - New: runserver_plus, integrate with django-pdb - New: runserver_plus, add check_migrations from Django - Improvement: show_urls, nested namespace support - Improvement: show_urls, allow to specify alternative urlconf - Improvement: show_urls, support i18n_patterns - Improvement: show_urls, use --language to filter on a particular language - Improvement: admin_generator, added docstrings to module - Improvement: shell_plus, allow cli arguments to be passed to ipython - Improvement: shell_plus, fixed PYTHONPATH bug when using django-admin shell_plus --notebook - Improvement: shell_plus, set application_name on PostgreSQL databases - Improvement: shell_plus, load user pypython config file - Improvement: CreationDateTimeField, use auto_now_add instead of default ModificationDateTimeField - Improvement: ModificationDateTimeField, use auto_now instead of pre_save method - Improvement: ForeignKeyAutocompleteAdmin, added ability to filter autocomplete query - Fix: shell_plus, support for pypython>=0.27 - Fix: shell_plus, load apps and models directly through the apps interface when available - Fix: shell_plus, use ipython start_ipython instead of embed - Fix: shell_plus, fix swalling ImportErrors with IPython 3 and higher - Fix: dumpscript, fix missing imports in dumped script - Fix: admin_generator, fix issues with Django 1.9 - Fix: template tags, move exception for import failure to inside of the template tags - Fix: reset_db, fix for Django 1.9 - Fix: runserver_plus, fix for Django 1.9 1.5.5 ----- Changes: - Fix: sqldiff, previous Django 1.8 fix was slightly broken 1.5.4 ----- Changes: - Improvement: syncdata, add skip-remove option - Improvement: logging, report how often mail was ratelimited - Fix: admin, Django 1.8 compatibility module_name is now called model_name - Fix: notes, Python 3.x fix force output of filter into list - Fix: sqldiff, fix for Django 1.8 1.5.3 ----- Changes: - New: ratelimiter, a simple ratelimiter filter for Python logging - Fix: various improvements for Django 1.8 - Fix: sync_s3, use os.walk instead of os.path.walk (py3 fix) - Improvement: pipchecker, use name instead of url_name to fix casing mismatches - Improvement: pipchecker, use https - Improvement: pipchecker, fix issues with new(er) pip versions - Docs: fixed a few typos - Docs: added documentation about NOTEBOOK_ARGUMENTS settings 1.5.2 ----- Changes: - New: sqldsn, prints Data Source Name for defined database(s) - Fix: graph_models, Django 1.8 support - Fix: highlighting tag, fix usage of is_safe - Fix: runscript, fix for runscript with AppConfig apps - Fix: sqldiff, KeyError when index is missing in database - Fix: sqldiff, multi column indexes was also counted as a single colomn index - Improvements: JSONField, Added try/catch for importing json/simplejson for Django 1.7 1.5.1 ----- Changes: - New: runserver_plus, add support for --extra-files parameter - Fix: Django 1.7 defined MIDDLEWARE_CLASSES for tests - Fix: shell_plus, problem when auto-loading modules with empty '__module__' property - Improvement: shell_plus, IPython 3.x support for notebooks - Improvement: tests, move to py.test and lots of other improvements - Improvement: create_app, add migrations folder - Improvement: tox.ini, refactored to be more DRY - Improvement: runserver_plus, also reload on changes to translation files - Improvement: runserver_plus, add reloader_interval support - Improvement: create_template_tags, removed unused command line option - Docs: print_user_for_session, add note about SESSION_ENGINE - Docs: runserver_plus, added section about IO calls and CPU usage 1.5.0 ----- Changes: - Fix: various fixes for Django 1.8 - Improvement: shell_plus, autodetect vi mode by looking at $EDITOR shell env setting - Improvement: shell_plus, print which shell is being used at verbosity > 1 - Improvement: shell_plus, added --no-browser option for IPython notebooks - Improvement: tox.ini, updated to latest Django versions - Docs: add reference to JSONField in documentation - Docs: fixed various typo's and links in docs and changelog - Docs: added some basic use cases to README - Docs: added information for companies or people wanting to donate towards the project - Fix: graphmodels, fix for python3 - Fix: dumpscript, fix check for missing import_helper module in Python 3 - Fix: runprofileserver, explicitly close file to avoid error on windows - Fix: json field, migration issues when adding new JSONField to existing model - Fix: runjobs, fix python3 issues 1.4.9 ----- Changes: - New: drop_test_database, drops the test database - New: command_signals, git commit -a -m 'bumped version number' (see docs) - Bugfix: runserver_plus, removed empty lines when logging on Python 3 1.4.8 ----- Changes: - Bugfix: validators, fix NoWhitespaceValidator __eq__ check 1.4.7 ----- Changes: - New: validators.py, NoControlCharactersValidator and NoWhitespaceValidator - New: EmailNotificationCommand class, email exceptions from Django Commands - Improvement: runserver_plus, enable threading by default and added --nothreading - Improvement: runscript, better detection when import error occured in script - Improvement: runscript, use EmailNotificationCommand class - Deprecation: deprecated UUIDField since Django 1.8 will have a native version. - Removed: completely remove support for automatically finding project root. 1.4.6 ----- Changes: - Improvement: sqldiff, fix for dbcolumn not used in few places when generating the sqldiff - Fix: sqldiff, backwards compatibility fix for Django 1.4 - Fix: ForeignKey Field, handling of __str__ instead of __unicode__ in python3 1.4.5 ----- Changes: - New: clear_cache, Clear django cache, useful when testing or deploying - Improvement: AutoSlugField, add the possibility to define a custom slugify function - Improvement: shell_plus --notebook, add a big warning when the notebook extension is not going to be loaded - Improvement: setup.py, add pypy classifier - Improvement: readme, add pypy badges - Fix: admin_generator, Fixed Python 3 __unicode__/__str__ compatibility 1.4.4 ----- Changes: - Fix: admin_generator, fix ImproperlyConfigured exception on Django 1.7 - Improvement: Remove "requires_model_validation" and "requires_system_checks" in commands which set the default value 1.4.1 ----- Changes: - New: shell_plus, Added python-prompt-toolkit integration for shell_plus - New: shell_plus, Added --ptipython (PYPython + IPython) - Improvement: reset_db, output traceback to easy debugging in case of error - Improvement: dumpscript, add --autofield to dumpscript to include autofields in export - Improvement: show_urls, Include namespace in URL name - Improvement: show_urls, Allow multiple decorators on the show_urls command - Improvement: runscript, show script errors with verbosity > 1 - Fix: jobs, daily_cleanup job use clearsessions for Django 1.5 and later - Fix: shell_plus, refactored importing and selecting shells to avoid polluted exception - Fix: shell_plus, Fix model loading for sentry 1.4.0 ----- Changes: - New admin_generator, can generate a admin.py file from models - Improvement: sqldiff, use the same exit codes as diff uses - Improvement: sqldiff, add support for unsigned numeric fields - Improvement: sqldiff, add NOT NULL support for MySQL - Improvement: sqldiff, add proper AUTO_INCREMENT support for MySQL - Improvement: sqldiff, detect tables for which no model exists - Improvement: travis.yml, add pypy to tests - Fix: sqldiff, fix for mysql misreported field lengths - Fix: sqldiff, in PG custom int primary keys would be mistaking for serial - Fix: sqldiff, use Django 1.7 db_parameters() for detect check constraints - Fix: update_permissions, Django 1.7 support - Fix: encrypted fields, fix for Django 1.7 migrations 1.3.11 ------ Changes: - Improvement: sqldiff, show differences for not managed tables - Improvement: show_urls -f aligned, 3 spaces between columns - Improvement: reset_db, support mysql options files in reset_db - Fix: sqldiff, Fixed bug with --output_text option and notnull-differ text - Fix: reset_db, Fix for PostgreSQL databases with dashes, dots, etc in the name - Fix: dumpscript, AttributeError for datefields that are None - Docs: Adding RUNSERVERPLUS_SERVER_ADDRESS_PORT to docs 1.3.10 ------ Changes: - Fix: show_urls, fix bug in new formatter when column is empty 1.3.9 ----- Changes: - Feature: shell_plus, add --kernel option to start as standalone IPython kernel - Feature: reset_db, Programmatically determine PostGIS template - Feature: sqldiff, add support for PointField and MultiPolygonField - Test: renamed test app - Fix: runserver_plus, --print-sql for Django 1.7 - Fix: shell_plus, --print-sql for Django 1.7 - Fix: show_urls, add support for functions that use functools.partial - Fix: show_urls, add formatter for aligned output (will most likely become future default) - Fix: shell_plus / notebook, support for Django 1.7 - Docs: various fixes and improvements - Cleanup: Remove work arounds for Django 0.96 and earlier 1.3.8 ----- Changes: - Feature: show_urls, add option to specify dense or verbose output format - Improvement: better support for django 1.7 migrations - Improvement: better support for django's admin docs - BugFix: runjob, job_name and app_name was swapped in error message - Docs: Update link to chinese docs - Python3: unreferenced_files, fix python3 compatibility - Python3: pipchecker, fix python3 compatibility 1.3.7 ----- Changes: - Reinstated: clean_pyc and compile_pyc commands, these now depends on BASE_DIR in settings.py as per Django 1.6. We urge everybody to include a BASE_DIR settings in their project file! auto-detecting the project-root is now deprecated and will be removed in 1.4.0. - I18N: Added russian locale - Docs: runscript, Add section about passing arguments to scripts - Python3: show_url, Fixed to AttributeError 'func_globals' - Deprecated: clean_pyc, compile_pyc, Auto-detecting project root 1.3.6 ----- Changes: - Additional version bump because we mistakenly already uploaded version 1.3.5 of the wheel package with the code of 1.3.4 1.3.5 ----- Changes: - Feature: Django-Extensions is now also distributed as a Wheel package - Improvement: dumpscript, improved the readability of comments in generated script - Improvement: sqldiff, backported get_constraints() for PostgreSQL - Improvement: shell_plus, consistent colorization - BugFix: encrypted fields, there is no decoding to unicode in Python 3 - BugFix: shell_plus, importing modules failed in some edge cases - Django 1.7: included Django 1.7 in test suite - Python 3.4: included Python 3.4 in test suite 1.3.4 ----- Changes: - Feature: Start maintaining a CHANGELOG file in the repository - Feature: ActivatorModelManager now has an ActivatorQuerySet - Feature: Add a deconstruct() method for future Django 1.7 migration compatibility - Feature: show_urls, now support --language for i18n_patterns - Feature: show_urls, now shows the decoraters set on a view function - Feature: graph_models, now support --include-models to restrict the graph to specified models - Feature: print_settings, allow to specify the settings you want to see - Improvement: graph_models, use '//' instead of '#' as comment character in dot files - Improvement: graph_models, added error message for abstract models without explicit relations - Improvement: JSONField, use python's built-in json support by default with fallback on django.utils.simplejson - Improvement: PostgreSQLUUIDField, parse value into UUID type before sending it to the database - Improvement: Use django.JQuery in autocomplete.js if available - Improvement: use "a not in b" instead of "not a in b" in the entire codebase - Removed: clean_pyc command since it does not work correctly in many cases - Removed: sync_media_s3 command in favor of sync_s3 - BugFix: syncdata, use pk instead of id for identifying primary key of objects - BugFix: sync_s3, use safer content type per default - BugFix: export_emails, filtering on groups - BugFix: print_user_for_session, use USERNAME_FIELD if defined - BugFix: update_permission, fixed TypeError issue - BugFix: JSONField, do not coerse a json string into a python list - BugFix: import json issue by using absolute imports - BugFix: add minimal version number to six (>=1.2) - Docs: graph_models, Added some documentation about using dot templates - Docs: reset_db, short description on SQL DDL used - Docs: Added specific list of supported Python and Django versions - Docs: Add link to GoDjango screencast - Docs: Add ShortUUIDField to docs - Python3: fixes to graph_models and export_emails for Python3 compatibility 1.3.3 ----- Changes: - Docs: Made it clearer that Django Extensions requires Django 1.4 or higher - Translations: FR Updated - Python3: Fix for shell_plus 1.3.0 ----- Changes: - Feature: SQLDiff much better notnull detection - Feature: reset_db add option to explicit set the PostGreSQL owner of the newly created DB - Feature: shell_plus added support for MongoEngine - Feature: sync_s3 enable syncing to other cloud providers compatible with s3 - Improvement: ForeignKeyAutocompleteAdmin add option to limit queryset - BugFix: graph_models fix issue with models without primary key - BugFix: graph_models fix UnicodeDecodeError using --verbose-names - BugFix: dumpscript fix problems with date/datetimes by saving them now as ISO8601 - Docs: many improvements - Docs: Chinese translation !!! - Python3: various improvements - Tests: add Django 1.6 django-extensions-django-extensions-ad01551/CONTRIBUTING.md000066400000000000000000000025151477606640500234030ustar00rootroot00000000000000# Contributing to Django Extensions There are many ways to contribute to the project. You may improve the documentation, address a bug, add some feature to the code or do something else. All sort of contributions are welcome. ## Development To start development on this project, fork this repository and follow the following instructions. ```bash # clone the forked repository $ git clone YOUR_FORKED_REPO_URL # create a virtual environment $ python3 -m venv venv # activate the virtual environment $ source venv/bin/activate # install django-extensions in development mode (venv) $ pip install -e . # install dependencies (venv) $ pip install Django -r requirements-dev.txt # for accessing the GUI portion of the test application (venv) $ export DJANGO_EXTENSIONS_DATABASE_NAME="db.sqlite3" # you may change if you want to use any other database # run migrations (venv) $ python manage.py migrate # start the development server (venv) $ python manage.py runserver ``` ## Testing To run tests against a particular `python` and `django` version installed inside your virtual environment, you may use: ```bash (venv) $ pytest # `python manage.py test` or `make test` also work ``` To run tests against all supported `python` and `django` versions, you may run: ```bash # install dependency (venv) $ pip install tox # run tests (venv) $ tox ``` django-extensions-django-extensions-ad01551/LICENSE000066400000000000000000000020411477606640500221510ustar00rootroot00000000000000Copyright (c) 2007 Michael Trier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. django-extensions-django-extensions-ad01551/MANIFEST.in000066400000000000000000000005361477606640500227110ustar00rootroot00000000000000recursive-include django_extensions/conf *.tmpl recursive-include django_extensions/templates *.dot *.html recursive-include django_extensions/static * recursive-include django_extensions/locale *.po *.mo recursive-include docs * include LICENSE include README.rst include CHANGELOG.md include tox.ini manage.py Makefile recursive-include tests *.py django-extensions-django-extensions-ad01551/Makefile000066400000000000000000000023461477606640500226140ustar00rootroot00000000000000help: @echo "clean - remove all build, test, coverage and Python artifacts" @echo "clean-build - remove build artifacts" @echo "clean-pyc - remove Python file artifacts" @echo "clean-test - remove test and coverage artifacts" @echo "compile-catalog - compile translation catalogs" @echo "test - run tests quickly with the default Python" @echo "coverage - check code coverage quickly with the default Python" @echo "install - install the package to the active Python's site-packages" clean: clean-test clean-build clean-pyc clean-build: rm -fr build/ rm -fr dist/ rm -fr .eggs/ find . -name '*.egg-info' -exec rm -fr {} + find . -name '*.egg' -exec rm -fr {} + clean-pyc: find . -name '*.pyc' -exec rm -f {} + find . -name '*.pyo' -exec rm -f {} + find . -name '*~' -exec rm -f {} + find . -name '__pycache__' -exec rm -fr {} + clean-test: rm -fr .cache/ rm -fr .tox/ rm -f .coverage rm -fr htmlcov/ compile-catalog: for loc in django_extensions/locale/*; do \ pybabel compile --directory django_extensions/locale/ --locale $$(basename $$loc) --domain django --statistics || exit 1; \ done test: pytest django_extensions tests coverage: test coverage report -i -m coverage html install: clean python -m pip install . django-extensions-django-extensions-ad01551/README.rst000066400000000000000000000106271477606640500226440ustar00rootroot00000000000000=================== Django Extensions =================== .. image:: https://img.shields.io/pypi/l/django-extensions.svg :target: https://raw.githubusercontent.com/django-extensions/django-extensions/master/LICENSE .. image:: https://github.com/django-extensions/django-extensions/actions/workflows/compile_catalog.yml/badge.svg :target: https://github.com/django-extensions/django-extensions/actions .. image:: https://github.com/django-extensions/django-extensions/actions/workflows/linters.yml/badge.svg :target: https://github.com/django-extensions/django-extensions/actions .. image:: https://github.com/django-extensions/django-extensions/actions/workflows/precommit.yml/badge.svg :target: https://github.com/django-extensions/django-extensions/actions .. image:: https://github.com/django-extensions/django-extensions/actions/workflows/pytest.yml/badge.svg :target: https://github.com/django-extensions/django-extensions/actions .. image:: https://github.com/django-extensions/django-extensions/actions/workflows/security.yml/badge.svg :target: https://github.com/django-extensions/django-extensions/actions .. image:: https://img.shields.io/pypi/v/django-extensions.svg :target: https://pypi.python.org/pypi/django-extensions/ :alt: Latest PyPI version .. image:: https://img.shields.io/pypi/wheel/django-extensions.svg :target: https://pypi.python.org/pypi/django-extensions/ :alt: Supports Wheel format .. image:: https://coveralls.io/repos/django-extensions/django-extensions/badge.svg?branch=master :target: https://coveralls.io/r/django-extensions/django-extensions?branch=master :alt: Coverage Django Extensions is a collection of custom extensions for the Django Framework. Getting Started =============== The easiest way to figure out what Django Extensions are all about is to watch the `excellent screencast by Eric Holscher`__ (`watch the video on vimeo`__). In a couple minutes Eric walks you through a half a dozen command extensions. There is also a `short screencast on GoDjango's Youtube Channel`__ to help show you even more. Requirements ============ Django Extensions requires Django 4.2 or later. Getting It ========== You can get Django Extensions by using pip:: $ pip install django-extensions If you want to install it from source, grab the git repository from GitHub:: $ git clone git://github.com/django-extensions/django-extensions.git $ cd django-extensions $ pip install . Installing It ============= To enable `django_extensions` in your project you need to add it to `INSTALLED_APPS` in your projects `settings.py` file: .. code-block:: python INSTALLED_APPS = ( ... 'django_extensions', ... ) Using It ======== Generate (and view) a graphviz graph of app models:: $ python manage.py graph_models -a -o myapp_models.png Produce a tab-separated list of `(url_pattern, view_function, name)` tuples for a project:: $ python manage.py show_urls Check templates for rendering errors:: $ python manage.py validate_templates Run the enhanced django shell:: $ python manage.py shell_plus Run the enhanced django runserver, (requires Werkzeug install):: $ python manage.py runserver_plus Getting Involved ================ Open Source projects can always use more help. Fixing a problem, documenting a feature, adding translation in your language. If you have some time to spare and like to help us, here are the places to do so: - GitHub: https://github.com/django-extensions/django-extensions - Mailing list: https://groups.google.com/group/django-extensions - Translations: https://www.transifex.com/projects/p/django-extensions/ Documentation ============= You can view documentation online at: - https://django-extensions.readthedocs.io Or you can look at the docs/ directory in the repository. Support ======= Django Extensions is free and always will be. It is developed and maintained by developers in an Open Source manner. Any support is welcome. You could help by writing documentation, pull-requests, report issues and/or translations. Please remember that nobody is paid directly to develop or maintain Django Extensions so we do have to divide our time between putting food on the table, family, this project and the rest of life :-) __ https://ericholscher.com/blog/2008/sep/12/screencast-django-command-extensions/ __ https://vimeo.com/1720508 __ https://www.youtube.com/watch?v=1F6G3ONhr4k django-extensions-django-extensions-ad01551/django_extensions/000077500000000000000000000000001477606640500246705ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/django_extensions/__init__.py000066400000000000000000000002121477606640500267740ustar00rootroot00000000000000# -*- coding: utf-8 -*- from django.utils.version import get_version VERSION = (4, 1, 0, "final", 0) __version__ = get_version(VERSION) django-extensions-django-extensions-ad01551/django_extensions/admin/000077500000000000000000000000001477606640500257605ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/django_extensions/admin/__init__.py000066400000000000000000000162241477606640500300760ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Autocomplete feature for admin panel # import operator from functools import update_wrapper, reduce from typing import Tuple, Dict, Callable # NOQA from django.apps import apps from django.http import HttpResponse, HttpResponseNotFound from django.conf import settings from django.db import models from django.db.models.query import QuerySet from django.utils.encoding import smart_str from django.utils.translation import gettext as _ from django.utils.text import get_text_list from django.contrib import admin from django_extensions.admin.widgets import ForeignKeySearchInput class ForeignKeyAutocompleteAdminMixin: """ Admin class for models using the autocomplete feature. There are two additional fields: - related_search_fields: defines fields of managed model that have to be represented by autocomplete input, together with a list of target model fields that are searched for input string, e.g.: related_search_fields = { 'author': ('first_name', 'email'), } - related_string_functions: contains optional functions which take target model instance as only argument and return string representation. By default __unicode__() method of target object is used. And also an optional additional field to set the limit on the results returned by the autocomplete query. You can set this integer value in your settings file using FOREIGNKEY_AUTOCOMPLETE_LIMIT or you can set this per ForeignKeyAutocompleteAdmin basis. If any value is set the results will not be limited. """ related_search_fields = {} # type: Dict[str, Tuple[str]] related_string_functions = {} # type: Dict[str, Callable] autocomplete_limit = getattr(settings, "FOREIGNKEY_AUTOCOMPLETE_LIMIT", None) def get_urls(self): from django.urls import path def wrap(view): def wrapper(*args, **kwargs): return self.admin_site.admin_view(view)(*args, **kwargs) return update_wrapper(wrapper, view) return [ path( "foreignkey_autocomplete/", wrap(self.foreignkey_autocomplete), name="%s_%s_autocomplete" % (self.model._meta.app_label, self.model._meta.model_name), ) ] + super().get_urls() def foreignkey_autocomplete(self, request): """ Search in the fields of the given related model and returns the result as a simple string to be used by the jQuery Autocomplete plugin """ query = request.GET.get("q", None) app_label = request.GET.get("app_label", None) model_name = request.GET.get("model_name", None) search_fields = request.GET.get("search_fields", None) object_pk = request.GET.get("object_pk", None) try: to_string_function = self.related_string_functions[model_name] except KeyError: to_string_function = lambda x: x.__str__() if search_fields and app_label and model_name and (query or object_pk): def construct_search(field_name): # use different lookup methods depending on the notation if field_name.startswith("^"): return "%s__istartswith" % field_name[1:] elif field_name.startswith("="): return "%s__iexact" % field_name[1:] elif field_name.startswith("@"): return "%s__search" % field_name[1:] else: return "%s__icontains" % field_name model = apps.get_model(app_label, model_name) queryset = model._default_manager.all() data = "" if query: for bit in query.split(): or_queries = [ models.Q( **{construct_search(smart_str(field_name)): smart_str(bit)} ) for field_name in search_fields.split(",") ] other_qs = QuerySet(model) other_qs.query.select_related = queryset.query.select_related other_qs = other_qs.filter(reduce(operator.or_, or_queries)) queryset = queryset & other_qs additional_filter = self.get_related_filter(model, request) if additional_filter: queryset = queryset.filter(additional_filter) if self.autocomplete_limit: queryset = queryset[: self.autocomplete_limit] data = "".join( [str("%s|%s\n") % (to_string_function(f), f.pk) for f in queryset] ) elif object_pk: try: obj = queryset.get(pk=object_pk) except Exception: # FIXME: use stricter exception checking pass else: data = to_string_function(obj) return HttpResponse(data, content_type="text/plain") return HttpResponseNotFound() def get_related_filter(self, model, request): """ Given a model class and current request return an optional Q object that should be applied as an additional filter for autocomplete query. If no additional filtering is needed, this method should return None. """ return None def get_help_text(self, field_name, model_name): searchable_fields = self.related_search_fields.get(field_name, None) if searchable_fields: help_kwargs = { "model_name": model_name, "field_list": get_text_list(searchable_fields, _("and")), } return ( _( "Use the left field to do %(model_name)s lookups " "in the fields %(field_list)s." ) % help_kwargs ) return "" def formfield_for_dbfield(self, db_field, request, **kwargs): """ Override the default widget for Foreignkey fields if they are specified in the related_search_fields class attribute. """ if ( isinstance(db_field, models.ForeignKey) and db_field.name in self.related_search_fields ): help_text = self.get_help_text( db_field.name, db_field.remote_field.model._meta.object_name ) if kwargs.get("help_text"): help_text = str("%s %s") % (kwargs["help_text"], help_text) kwargs["widget"] = ForeignKeySearchInput( db_field.remote_field, self.related_search_fields[db_field.name] ) kwargs["help_text"] = help_text return super().formfield_for_dbfield(db_field, request, **kwargs) class ForeignKeyAutocompleteAdmin(ForeignKeyAutocompleteAdminMixin, admin.ModelAdmin): pass class ForeignKeyAutocompleteTabularInline( ForeignKeyAutocompleteAdminMixin, admin.TabularInline ): pass class ForeignKeyAutocompleteStackedInline( ForeignKeyAutocompleteAdminMixin, admin.StackedInline ): pass django-extensions-django-extensions-ad01551/django_extensions/admin/filter.py000066400000000000000000000035561477606640500276300ustar00rootroot00000000000000# -*- coding: utf-8 -*- from django.contrib.admin import FieldListFilter from django.contrib.admin.utils import prepare_lookup_value from django.utils.translation import gettext_lazy as _ class NullFieldListFilter(FieldListFilter): def __init__(self, field, request, params, model, model_admin, field_path): self.lookup_kwarg = "{0}__isnull".format(field_path) super().__init__(field, request, params, model, model_admin, field_path) lookup_choices = self.lookups(request, model_admin) self.lookup_choices = () if lookup_choices is None else list(lookup_choices) def expected_parameters(self): return [self.lookup_kwarg] def value(self): return self.used_parameters.get(self.lookup_kwarg, None) def lookups(self, request, model_admin): return ( ("1", _("Yes")), ("0", _("No")), ) def choices(self, cl): yield { "selected": self.value() is None, "query_string": cl.get_query_string({}, [self.lookup_kwarg]), "display": _("All"), } for lookup, title in self.lookup_choices: yield { "selected": self.value() == prepare_lookup_value(self.lookup_kwarg, lookup), "query_string": cl.get_query_string( { self.lookup_kwarg: lookup, }, [], ), "display": title, } def queryset(self, request, queryset): if self.value() is not None: kwargs = {self.lookup_kwarg: self.value()} return queryset.filter(**kwargs) return queryset class NotNullFieldListFilter(NullFieldListFilter): def lookups(self, request, model_admin): return ( ("0", _("Yes")), ("1", _("No")), ) django-extensions-django-extensions-ad01551/django_extensions/admin/widgets.py000066400000000000000000000064411477606640500300050ustar00rootroot00000000000000# -*- coding: utf-8 -*- import urllib from django import forms from django.contrib.admin.sites import site from django.contrib.admin.widgets import ForeignKeyRawIdWidget from django.template.loader import render_to_string from django.templatetags.static import static from django.urls import reverse from django.utils.safestring import mark_safe from django.utils.text import Truncator class ForeignKeySearchInput(ForeignKeyRawIdWidget): """ Widget for displaying ForeignKeys in an autocomplete search input instead in a django-extensions-django-extensions-ad01551/django_extensions/templatetags/000077500000000000000000000000001477606640500273625ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/django_extensions/templatetags/__init__.py000066400000000000000000000000001477606640500314610ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/django_extensions/templatetags/debugger_tags.py000066400000000000000000000011241477606640500325340ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ Make debugging Django templates easier. Example: {% load debugger_tags %} {{ object|ipdb }} """ from django import template register = template.Library() @register.filter def ipdb(obj): # pragma: no cover """Interactive Python debugger filter.""" __import__("ipdb").set_trace() return obj @register.filter def pdb(obj): """Python debugger filter.""" __import__("pdb").set_trace() return obj @register.filter def wdb(obj): # pragma: no cover """Web debugger filter.""" __import__("wdb").set_trace() return obj django-extensions-django-extensions-ad01551/django_extensions/templatetags/highlighting.py000066400000000000000000000060371477606640500324070ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ Similar to syntax_color.py but this is intended more for being able to copy+paste actual code into your Django templates without needing to escape or anything crazy. Example: {% load highlighting %}

check out this code

{% highlight 'python' 'Excerpt: blah.py' %} def need_food(self): print("Love is than &death&") {% endhighlight %} """ from django import template from django.template import ( Context, Node, Template, TemplateSyntaxError, Variable, ) from django.template.defaultfilters import stringfilter from django.utils.safestring import mark_safe try: from pygments import highlight as pyghighlight from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter HAS_PYGMENTS = True except ImportError: # pragma: no cover HAS_PYGMENTS = False register = template.Library() @register.filter(is_safe=True) @stringfilter def parse_template(value): return mark_safe(Template(value).render(Context())) class CodeNode(Node): def __init__(self, language, nodelist, name=""): self.language = Variable(language) self.nodelist = nodelist if name: self.name = Variable(name) else: self.name = None def render(self, context): code = self.nodelist.render(context).strip() lexer = get_lexer_by_name(self.language.resolve(context)) formatter = HtmlFormatter(linenos=False) html = "" if self.name: name = self.name.resolve(context) html = '
%s
' % name return html + pyghighlight(code, lexer, formatter) @register.tag def highlight(parser, token): """ Tag to put a highlighted source code
 block in your code.
    This takes two arguments, the language and a little explaination message
    that will be generated before the code.  The second argument is optional.

    Your code will be fed through pygments so you can use any language it
    supports.

    Usage::

      {% load highlighting %}
      {% highlight 'python' 'Excerpt: blah.py' %}
      def need_food(self):
          print("Love is colder than death")
      {% endhighlight %}

    """
    if not HAS_PYGMENTS:  # pragma: no cover
        raise ImportError("Please install 'pygments' library to use highlighting.")
    nodelist = parser.parse(("endhighlight",))
    parser.delete_first_token()
    bits = token.split_contents()[1:]
    if len(bits) < 1:
        raise TemplateSyntaxError("'highlight' statement requires an argument")
    return CodeNode(bits[0], nodelist, *bits[1:])
django-extensions-django-extensions-ad01551/django_extensions/templatetags/indent_text.py000066400000000000000000000033261477606640500322650ustar00rootroot00000000000000# -*- coding: utf-8 -*-
from django import template

register = template.Library()


class IndentByNode(template.Node):
    def __init__(self, nodelist, indent_level, if_statement):
        self.nodelist = nodelist
        self.indent_level = template.Variable(indent_level)
        if if_statement:
            self.if_statement = template.Variable(if_statement)
        else:
            self.if_statement = None

    def render(self, context):
        indent_level = self.indent_level.resolve(context)
        if self.if_statement:
            try:
                if_statement = bool(self.if_statement.resolve(context))
            except template.VariableDoesNotExist:
                if_statement = False
        else:
            if_statement = True
        output = self.nodelist.render(context)
        if if_statement:
            indent = " " * indent_level
            output = indent + indent.join(output.splitlines(True))
        return output


@register.tag
def indentby(parser, token):
    """
    Add indentation to text between the tags by the given indentation level.

    {% indentby  [if ] %}
    ...
    {% endindentby %}

    Arguments:
      indent_level - Number of spaces to indent text with.
      statement - Only apply indent_level if the boolean statement evalutates to True.
    """
    args = token.split_contents()
    largs = len(args)
    if largs not in (2, 4):
        raise template.TemplateSyntaxError("indentby tag requires 1 or 3 arguments")
    indent_level = args[1]
    if_statement = None
    if largs == 4:
        if_statement = args[3]
    nodelist = parser.parse(("endindentby",))
    parser.delete_first_token()
    return IndentByNode(nodelist, indent_level, if_statement)
django-extensions-django-extensions-ad01551/django_extensions/templatetags/syntax_color.py000066400000000000000000000062041477606640500324620ustar00rootroot00000000000000# -*- coding: utf-8 -*-
r"""
Template filter for rendering a string with syntax highlighting.
It relies on Pygments to accomplish this.

Some standard usage examples (from within Django templates).
Coloring a string with the Python lexer:

    {% load syntax_color %}
    {{ code_string|colorize:"python" }}

You may use any lexer in Pygments. The complete list of which
can be found [on the Pygments website][1].

[1]: https://pygments.org/docs/lexers/

You may also have Pygments attempt to guess the correct lexer for
a particular string. However, if may not be able to choose a lexer,
in which case it will simply return the string unmodified. This is
less efficient compared to specifying the lexer to use.

    {{ code_string|colorize }}

You may also render the syntax highlighted text with line numbers.

    {% load syntax_color %}
    {{ some_code|colorize_table:"html+django" }}
    {{ let_pygments_pick_for_this_code|colorize_table }}

Please note that before you can load the ``syntax_color`` template filters
you will need to add the ``django_extensions.utils`` application to the
``INSTALLED_APPS``setting in your project's ``settings.py`` file.
"""

import os

from django import template
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe

try:
    from pygments import highlight
    from pygments.formatters import HtmlFormatter
    from pygments.lexers import get_lexer_by_name, guess_lexer, ClassNotFound

    HAS_PYGMENTS = True
except ImportError:  # pragma: no cover
    HAS_PYGMENTS = False

__author__ = "Will Larson "


register = template.Library()


def pygments_required(func):
    """Raise ImportError if pygments is not installed."""

    def wrapper(*args, **kwargs):
        if not HAS_PYGMENTS:  # pragma: no cover
            raise ImportError("Please install 'pygments' library to use syntax_color.")
        rv = func(*args, **kwargs)
        return rv

    return wrapper


@pygments_required
@register.simple_tag
def pygments_css():
    return HtmlFormatter().get_style_defs(".highlight")


def generate_pygments_css(path=None):
    path = os.path.join(path or os.getcwd(), "pygments.css")
    f = open(path, "w")
    f.write(pygments_css())
    f.close()


def get_lexer(value, arg):
    if arg is None:
        return guess_lexer(value)
    return get_lexer_by_name(arg)


@pygments_required
@register.filter(name="colorize")
@stringfilter
def colorize(value, arg=None):
    try:
        return mark_safe(highlight(value, get_lexer(value, arg), HtmlFormatter()))
    except ClassNotFound:
        return value


@pygments_required
@register.filter(name="colorize_table")
@stringfilter
def colorize_table(value, arg=None):
    try:
        return mark_safe(
            highlight(value, get_lexer(value, arg), HtmlFormatter(linenos="table"))
        )
    except ClassNotFound:
        return value


@pygments_required
@register.filter(name="colorize_noclasses")
@stringfilter
def colorize_noclasses(value, arg=None):
    try:
        return mark_safe(
            highlight(value, get_lexer(value, arg), HtmlFormatter(noclasses=True))
        )
    except ClassNotFound:
        return value
django-extensions-django-extensions-ad01551/django_extensions/templatetags/widont.py000066400000000000000000000036451477606640500312500ustar00rootroot00000000000000# -*- coding: utf-8 -*-
import re

from django.template import Library
from django.utils.encoding import force_str


register = Library()
re_widont = re.compile(r"\s+(\S+\s*)$")
re_widont_html = re.compile(
    r"([^<>\s])\s+([^<>\s]+\s*)(]*>|$)",
    re.IGNORECASE,
)


@register.filter
def widont(value, count=1):
    """
    Add an HTML non-breaking space between the final two words of the string to
    avoid "widowed" words.

    Examples:

    >>> print(widont('Test   me   out'))
    Test   me out

    >>> print("'",widont('It works with trailing spaces too  '), "'")
    ' It works with trailing spaces too   '

    >>> print(widont('NoEffect'))
    NoEffect
    """

    def replace(matchobj):
        return force_str(" %s" % matchobj.group(1))

    for i in range(count):
        value = re_widont.sub(replace, force_str(value))
    return value


@register.filter
def widont_html(value):
    """
    Add an HTML non-breaking space between the final two words at the end of
    (and in sentences just outside of) block level tags to avoid "widowed"
    words.

    Examples:

    >>> print(widont_html('

Here is a simple example

Single

'))

Here is a simple example

Single

>>> print(widont_html('

test me
out

Ok?

Not in a p

and this

'))

test me
out

Ok?

Not in a p

and this

>>> print(widont_html('leading text

test me out

trailing text')) leading text

test me out

trailing text """ # noqa: E501 def replace(matchobj): return force_str("%s %s%s" % matchobj.groups()) return re_widont_html.sub(replace, force_str(value)) if __name__ == "__main__": def _test(): import doctest doctest.testmod() _test() django-extensions-django-extensions-ad01551/django_extensions/utils/000077500000000000000000000000001477606640500260305ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/django_extensions/utils/__init__.py000066400000000000000000000001061477606640500301360ustar00rootroot00000000000000# -*- coding: utf-8 -*- from .internal_ips import InternalIPS # NOQA django-extensions-django-extensions-ad01551/django_extensions/utils/deprecation.py000066400000000000000000000002341477606640500306760ustar00rootroot00000000000000# -*- coding: utf-8 -*- class MarkedForDeprecationWarning(DeprecationWarning): pass class RemovedInNextVersionWarning(DeprecationWarning): pass django-extensions-django-extensions-ad01551/django_extensions/utils/dia2django.py000066400000000000000000000276271477606640500304220ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ Author Igor Támara igor@tamarapatino.org Use this little program as you wish, if you include it in your work, let others know you are using it preserving this note, you have the right to make derivative works, Use it at your own risk. Tested to work on(etch testing 13-08-2007): Python 2.4.4 (#2, Jul 17 2007, 11:56:54) [GCC 4.1.3 20070629 (prerelease) (Debian 4.1.2-13)] on linux2 """ import codecs import gzip import re import sys from xml.dom.minidom import Node, parseString dependclasses = ["User", "Group", "Permission", "Message"] # Type dictionary translation types SQL -> Django tsd = { "text": "TextField", "date": "DateField", "varchar": "CharField", "int": "IntegerField", "float": "FloatField", "serial": "AutoField", "boolean": "BooleanField", "numeric": "FloatField", "timestamp": "DateTimeField", "bigint": "IntegerField", "datetime": "DateTimeField", "time": "TimeField", "bool": "BooleanField", } # convert varchar -> CharField v2c = re.compile(r"varchar\((\d+)\)") def find_index(fks, id_): """ Look for the id on fks, fks is an array of arrays, each array has on [1] the id of the class in a dia diagram. When not present returns None, else it returns the position of the class with id on fks """ for i, _ in fks.items(): if fks[i][1] == id_: return i return None def addparentstofks(rels, fks): """ Get a list of relations, between parents and sons and a dict of clases named in dia, and modifies the fks to add the parent as fk to get order on the output of classes and replaces the base class of the son, to put the class parent name. """ for j in rels: son = find_index(fks, j[1]) parent = find_index(fks, j[0]) fks[son][2] = fks[son][2].replace("models.Model", parent) if parent not in fks[son][0]: fks[son][0].append(parent) def dia2django(archivo): models_txt = "" f = codecs.open(archivo, "rb") # dia files are gzipped data = gzip.GzipFile(fileobj=f).read() ppal = parseString(data) # diagram -> layer -> object -> UML - Class -> name, # (attribs : composite -> name,type) datos = ( ppal.getElementsByTagName("dia:diagram")[0] .getElementsByTagName("dia:layer")[0] .getElementsByTagName("dia:object") ) clases = {} herit = [] imports = str("") for i in datos: # Look for the classes if i.getAttribute("type") == "UML - Class": myid = i.getAttribute("id") for j in i.childNodes: if j.nodeType == Node.ELEMENT_NODE and j.hasAttributes(): if j.getAttribute("name") == "name": actclas = ( j.getElementsByTagName("dia:string")[0] .childNodes[0] .data[1:-1] ) myname = "\nclass %s(models.Model) :\n" % actclas clases[actclas] = [[], myid, myname, 0] if j.getAttribute("name") == "attributes": for ll in j.getElementsByTagName("dia:composite"): if ll.getAttribute("type") == "umlattribute": # Look for the attribute name and type for k in ll.getElementsByTagName("dia:attribute"): if k.getAttribute("name") == "name": nc = ( k.getElementsByTagName("dia:string")[0] .childNodes[0] .data[1:-1] ) elif k.getAttribute("name") == "type": tc = ( k.getElementsByTagName("dia:string")[0] .childNodes[0] .data[1:-1] ) elif k.getAttribute("name") == "value": val = ( k.getElementsByTagName("dia:string")[0] .childNodes[0] .data[1:-1] ) if val == "##": val = "" elif ( k.getAttribute("name") == "visibility" and k.getElementsByTagName("dia:enum")[ 0 ].getAttribute("val") == "2" ): if ( tc.replace(" ", "") .lower() .startswith("manytomanyfield(") ): # If we find a class not in our model that # is marked as being to another model newc = tc.replace(" ", "")[16:-1] if dependclasses.count(newc) == 0: dependclasses.append(newc) if ( tc.replace(" ", "") .lower() .startswith("foreignkey(") ): # If we find a class not in our model that # is marked as being to another model newc = tc.replace(" ", "")[11:-1] if dependclasses.count(newc) == 0: dependclasses.append(newc) # Mapping SQL types to Django varch = v2c.search(tc) if tc.replace(" ", "").startswith("ManyToManyField("): myfor = tc.replace(" ", "")[16:-1] if actclas == myfor: # In case of a recursive type, we use 'self' tc = tc.replace(myfor, "'self'") elif clases[actclas][0].count(myfor) == 0: # Adding related class if myfor not in dependclasses: # In case we are using Auth classes or # external via protected dia visibility clases[actclas][0].append(myfor) tc = "models." + tc if len(val) > 0: tc = tc.replace(")", "," + val + ")") elif tc.find("Field") != -1: if tc.count("()") > 0 and len(val) > 0: tc = "models.%s" % tc.replace( ")", "," + val + ")" ) else: tc = "models.%s(%s)" % (tc, val) elif tc.replace(" ", "").startswith("ForeignKey("): myfor = tc.replace(" ", "")[11:-1] if actclas == myfor: # In case of a recursive type, we use 'self' tc = tc.replace(myfor, "'self'") elif clases[actclas][0].count(myfor) == 0: # Adding foreign classes if myfor not in dependclasses: # In case we are using Auth classes clases[actclas][0].append(myfor) tc = "models." + tc if len(val) > 0: tc = tc.replace(")", "," + val + ")") elif varch is None: tc = ( "models." + tsd[tc.strip().lower()] + "(" + val + ")" ) else: tc = ( "models.CharField(max_length=" + varch.group(1) + ")" ) if len(val) > 0: tc = tc.replace(")", ", " + val + " )") if not (nc == "id" and tc == "AutoField()"): clases[actclas][2] += " %s = %s\n" % (nc, tc) elif i.getAttribute("type") == "UML - Generalization": mycons = ["A", "A"] a = i.getElementsByTagName("dia:connection") for j in a: if len(j.getAttribute("to")): mycons[int(j.getAttribute("handle"))] = j.getAttribute("to") print(mycons) if "A" not in mycons: herit.append(mycons) elif i.getAttribute("type") == "UML - SmallPackage": a = i.getElementsByTagName("dia:string") for j in a: if len(j.childNodes[0].data[1:-1]): imports += str( "from %s.models import *" % j.childNodes[0].data[1:-1] ) addparentstofks(herit, clases) # Ordering the appearance of classes # First we make a list of the classes each classs is related to. ordered = [] for j, k in clases.items(): k[2] += '\n def __str__(self):\n return u""\n' for fk in k[0]: if fk not in dependclasses: clases[fk][3] += 1 ordered.append([j] + k) i = 0 while i < len(ordered): mark = i j = i + 1 while j < len(ordered): if ordered[i][0] in ordered[j][1]: mark = j j += 1 if mark == i: i += 1 else: # swap ( ordered[i] , ordered[mark]) to make ordered[i] to be at the end if ordered[i][0] in ordered[mark][1] and ordered[mark][0] in ordered[i][1]: # Resolving simplistic circular ForeignKeys print( "Not able to resolve circular ForeignKeys between %s and %s" % (ordered[i][1], ordered[mark][0]) ) break a = ordered[i] ordered[i] = ordered[mark] ordered[mark] = a if i == len(ordered) - 1: break ordered.reverse() if imports: models_txt = str(imports) for i in ordered: models_txt += "%s\n" % str(i[3]) return models_txt if __name__ == "__main__": if len(sys.argv) == 2: dia2django(sys.argv[1]) else: print(" Use:\n \n " + sys.argv[0] + " diagram.dia\n\n") django-extensions-django-extensions-ad01551/django_extensions/utils/internal_ips.py000066400000000000000000000036401477606640500310740ustar00rootroot00000000000000# -*- coding: utf-8 -*- from collections.abc import Container import ipaddress import itertools class InternalIPS(Container): """ InternalIPS allows to specify CIDRs for INTERNAL_IPS. It takes an iterable of ip addresses or ranges. Inspiration taken from netaddr.IPSet, please use it if you can since it support more advanced features like optimizing ranges and lookups. """ __slots__ = ["_cidrs"] def __init__(self, iterable, sort_by_size=False): """ Constructor. :param iterable: (optional) an iterable containing IP addresses and subnets. :param sort_by_size: sorts internal list according to size of ip ranges, largest first. """ self._cidrs = [] for address in iterable: self._cidrs.append(ipaddress.ip_network(address)) if sort_by_size: self._cidrs = sorted(self._cidrs) def __contains__(self, address): """ :param ip: An IP address or subnet. :return: ``True`` if IP address or subnet is a member of this InternalIPS set. """ address = ipaddress.ip_address(address) for cidr in self._cidrs: if address in cidr: return True return False def __hash__(self): """ Raises ``TypeError`` if this method is called. """ raise TypeError("InternalIPS containers are unhashable!") def __len__(self): """ :return: the cardinality of this InternalIPS set. """ return sum(cidr.num_addresses for cidr in self._cidrs) def __iter__(self): """ :return: an iterator over the IP addresses within this IP set. """ return itertools.chain(*self._cidrs) def iter_cidrs(self): """ :return: an iterator over individual IP subnets within this IP set. """ return sorted(self._cidrs) django-extensions-django-extensions-ad01551/django_extensions/validators.py000066400000000000000000000076671477606640500274320ustar00rootroot00000000000000# -*- coding: utf-8 -*- import unicodedata import binascii from django.core.exceptions import ValidationError from django.utils.deconstruct import deconstructible from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ @deconstructible class NoControlCharactersValidator: message = _("Control Characters like new lines or tabs are not allowed.") code = "no_control_characters" whitelist = None def __init__(self, message=None, code=None, whitelist=None): if message: self.message = message if code: self.code = code if whitelist: self.whitelist = whitelist def __call__(self, value): value = force_str(value) whitelist = self.whitelist category = unicodedata.category for character in value: if whitelist and character in whitelist: continue if category(character)[0] == "C": params = {"value": value, "whitelist": whitelist} raise ValidationError(self.message, code=self.code, params=params) def __eq__(self, other): return ( isinstance(other, NoControlCharactersValidator) and (self.whitelist == other.whitelist) and (self.message == other.message) and (self.code == other.code) ) @deconstructible class NoWhitespaceValidator: message = _("Leading and Trailing whitespaces are not allowed.") code = "no_whitespace" def __init__(self, message=None, code=None, whitelist=None): if message: self.message = message if code: self.code = code def __call__(self, value): value = force_str(value) if value != value.strip(): params = {"value": value} raise ValidationError(self.message, code=self.code, params=params) def __eq__(self, other): return ( isinstance(other, NoWhitespaceValidator) and (self.message == other.message) and (self.code == other.code) ) @deconstructible class HexValidator: messages = { "invalid": _("Only a hex string is allowed."), "length": _("Invalid length. Must be %(length)d characters."), "min_length": _("Ensure that there are more than %(min)s characters."), "max_length": _("Ensure that there are no more than %(max)s characters."), } code = "hex_only" def __init__( self, length=None, min_length=None, max_length=None, message=None, code=None ): self.length = length self.min_length = min_length self.max_length = max_length if message: self.message = message else: self.message = self.messages["invalid"] if code: self.code = code def __call__(self, value): value = force_str(value) if self.length and len(value) != self.length: raise ValidationError( self.messages["length"], code="hex_only_length", params={"length": self.length}, ) if self.min_length and len(value) < self.min_length: raise ValidationError( self.messages["min_length"], code="hex_only_min_length", params={"min": self.min_length}, ) if self.max_length and len(value) > self.max_length: raise ValidationError( self.messages["max_length"], code="hex_only_max_length", params={"max": self.max_length}, ) try: binascii.unhexlify(value) except (TypeError, binascii.Error): raise ValidationError(self.messages["invalid"], code="hex_only") def __eq__(self, other): return ( isinstance(other, HexValidator) and (self.message == other.message) and (self.code == other.code) ) django-extensions-django-extensions-ad01551/docs/000077500000000000000000000000001477606640500220775ustar00rootroot00000000000000django-extensions-django-extensions-ad01551/docs/AUTHORS000066400000000000000000000020001477606640500231370ustar00rootroot00000000000000The following individuals have contributed to this project Antonio Cavedoni - For the GraphViz stuff (https://cavedoni.com/) Ludvig Ericson (toxic) Collin Grady (magus) Gabriel Grant (gabrielgrant) Rob Hudson (robhudson) Jannis Leidel (leidel) Brian Rosner (brosner) Michael Trier (empty) Doug Napoleone (dougn) Bas van Oostveen (trbs) David Krauth (dakrauth) Will Larson (lethain) - syntax_color template filters. Patrick Altman (paltman) - patched sync_media_s3 Chris Beaven (smileychris) - widont filter qMax - various graph_model patches Tyson Clugg (tclugg) - patched sqldiff Domen Kožar (iElectric) - staticfiles patch improvement Ceesjan Luiten (quinox) - original staticfiles patch Camilo Nova (camilonova) Wiktor Kołodziej (viciu) Marc Tudurí (marctc) Rick van Hattem (WoLpH) Rodolphe Quiédeville (rodo) Nik Nyby (nikolas) Joshua Miller (thecardcheat) Piotr Domański (domandinho) Please see https://github.com/django-extensions/django-extensions/graphs/contributors for a more complete list of contributors. django-extensions-django-extensions-ad01551/docs/Makefile000066400000000000000000000045071477606640500235450ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html web pickle htmlhelp latex changes linkcheck help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " changes to make an overview over all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" clean: -rm -rf _build/* html: mkdir -p _build/html _build/doctrees _static $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html @echo @echo "Build finished. The HTML pages are in _build/html." pickle: mkdir -p _build/pickle _build/doctrees $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle @echo @echo "Build finished; now you can process the pickle files." web: pickle json: mkdir -p _build/json _build/doctrees $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: mkdir -p _build/htmlhelp _build/doctrees $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in _build/htmlhelp." latex: mkdir -p _build/latex _build/doctrees $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex @echo @echo "Build finished; the LaTeX files are in _build/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." changes: mkdir -p _build/changes _build/doctrees $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes @echo @echo "The overview file is in _build/changes." linkcheck: mkdir -p _build/linkcheck _build/doctrees $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in _build/linkcheck/output.txt." django-extensions-django-extensions-ad01551/docs/admin_extensions.rst000066400000000000000000000063741477606640500262120ustar00rootroot00000000000000Admin Extensions ================ :synopsis: Admin Extensions * *ForeignKeyAutocompleteAdmin* - ForeignKeyAutocompleteAdmin will enable the admin app to show ForeignKey fields with an search input field. The search field is rendered by the ForeignKeySearchInput form widget and uses jQuery to do configurable autocompletion. * *ForeignKeyAutocompleteStackedInline*, *ForeignKeyAutocompleteTabularInline* - in the same fashion of the *ForeignKeyAutocompleteAdmin* these two classes enable a search input field for ForeignKey fields in AdminInline classes. Deprecation ------------ Django 2.0 now contains similar functionality as *ForeignKeyAutocompleteAdmin* therefore we are deprecating this extension and highly encouraging everyone to update to it. This code will be removed in the near future when support for Django older then 2.0 is dropped. More on this: https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields Known Issues ------------ * SECURITY ISSUE: Autocompletion does not check permissions nor the requested models on the autocompletion view. This can be used by users with access to the admin to expose data from other models. Please be aware and careful when using *ForeignKeyAutocompleteAdmin*. * The current version of the *ForeignKeyAutocompleteAdmin* has issues with recent Django versions. * We strongly suggest project using this extension to update to Django 2.0 and use the native *autocomplete_fields*. Example Usage ------------- To enable the Admin Autocomplete you can follow this code example in your admin.py file: :: from django.contrib import admin from foo.models import Permission from django_extensions.admin import ForeignKeyAutocompleteAdmin class PermissionAdmin(ForeignKeyAutocompleteAdmin): # User is your FK attribute in your model # first_name and email are attributes to search for in the FK model related_search_fields = { 'user': ('first_name', 'email'), } fields = ('user', 'avatar', 'is_active') ... admin.site.register(Permission, PermissionAdmin) If you are using django-reversion you should follow this code example: :: from django.contrib import admin from foo.models import MyVersionModel from reversion.admin import VersionAdmin from django_extensions.admin import ForeignKeyAutocompleteAdmin class MyVersionModelAdmin(VersionAdmin, ForeignKeyAutocompleteAdmin): ... admin.site.register(MyVersionModel, MyVersionModelAdmin) If you need to limit the autocomplete search, you can override the ``get_related_filter`` method of the admin. For example if you want to allow non-superusers to attach attachments only to articles they own you can use:: class AttachmentAdmin(ForeignKeyAutocompleteAdmin): ... def get_related_filter(self, model, request): user = request.user if not issubclass(model, Article) or user.is_superuser(): return super(AttachmentAdmin, self).get_related_filter( model, request ) return Q(owner=user) Note that this does not protect your application from malicious attempts to circumvent it (e.g. sending fabricated requests via cURL). django-extensions-django-extensions-ad01551/docs/admin_generator.rst000066400000000000000000000070721477606640500257750ustar00rootroot00000000000000admin_generator =============== :synopsis: Generate automatic Django Admin classes by providing an app name. Outputs source code at STDOUT. Generating automatically the admin for a given app -------------------------------------------------- You have to provide the app_name you want the admin to be generated. :: $ python manage.py admin_generator Example ------- Given the app name "brody", with the models: :: from django.contrib.auth import get_user_model from django.contrib.auth.models import User from django.db import models from django.utils.translation import gettext_lazy as _ from isbn_field import ISBNField class Author(models.Model): first_name = models.CharField(max_length=30, verbose_name=_('First name')) last_name = models.CharField(max_length=40, verbose_name=_('Last name')) def __str__(self): return '{} {}'.format(self.first_name, self.last_name) class Meta: verbose_name = _('Author') verbose_name_plural = _('Authors') class Tag(models.Model): word = models.CharField(max_length=35, verbose_name=_('Word')) slug = models.CharField(max_length=50, verbose_name=_('Slug')) def __str__(self): return self.word class Meta: verbose_name = _('Tag') verbose_name_plural = _('Tags') class Book(models.Model): title = models.CharField(max_length=40, verbose_name=_('Title')) cover = models.ImageField(upload_to='book-covers', verbose_name=_('Cover'), blank=True) tags = models.ManyToManyField(Tag, verbose_name=_('Tags'), related_name='books') authors = models.ManyToManyField(Author, verbose_name=_('Authors'), related_name='books') publication_date = models.DateField(verbose_name=_('Publication date')) isbn = ISBNField(verbose_name=_('ISBN code')) def __str__(self): return self.title class Meta: verbose_name = _('Book') verbose_name_plural = _('Books') class Borrow(models.Model): user = models.OneToOneField(get_user_model(), verbose_name=_('Usuario'), on_delete=models.PROTECT) borrow_date = models.DateField(verbose_name=_('Borrow date')) returned_date = models.DateField(verbose_name=_('Returned date'), blank=True, null=True) book = models.ForeignKey(Book, verbose_name=_('Book'), on_delete=models.PROTECT) class Meta: verbose_name = _('Borrow') verbose_name_plural = _('Borrows') def __str__(self): return '{}_{}'.format(self.user, self.borrow_date) the following command: :: $ python manage.py admin_generator brody will output to STDOUT the following code: :: # -*- coding: utf-8 -*- from django.contrib import admin from .models import Author, Tag, Book, Borrow @admin.register(Author) class AuthorAdmin(admin.ModelAdmin): list_display = ('id', 'first_name', 'last_name') @admin.register(Tag) class TagAdmin(admin.ModelAdmin): list_display = ('id', 'word', 'slug') search_fields = ('slug',) @admin.register(Book) class BookAdmin(admin.ModelAdmin): list_display = ('id', 'title', 'cover', 'publication_date', 'isbn') list_filter = ('publication_date',) raw_id_fields = ('tags', 'authors') @admin.register(Borrow) class BorrowAdmin(admin.ModelAdmin): list_display = ('id', 'user', 'borrow_date', 'returned_date', 'book') list_filter = ('user', 'borrow_date', 'returned_date', 'book') django-extensions-django-extensions-ad01551/docs/command_extensions.rst000066400000000000000000000152551477606640500265360ustar00rootroot00000000000000Command Extensions ================== :synopsis: Command Extensions .. toctree:: :maxdepth: 3 shell_plus create_template_tags delete_squashed_migrations dumpscript runscript export_emails generate_password graph_models list_model_info list_signals mail_debug managestate merge_model_instances print_settings reset_db runprofileserver runserver_plus sync_s3 syncdata sqldiff sqlcreate sqldsn validate_templates admin_generator * :doc:`shell_plus` - An enhanced version of the Django shell. It will autoload all your models making it easy to work with the ORM right away. * :doc:`admin_generator` - Generate automatic Django Admin classes by providing an app name. Outputs source code at STDOUT. * *clean_pyc* - Remove all python bytecode compiled files from the project * *create_command* - Creates a command extension directory structure within the specified application. This makes it easy to get started with adding a command extension to your application. * :doc:`create_template_tags` - Creates a template tag directory structure within the specified application. * *create_jobs* - Creates a Django jobs command directory structure for the given app name in the current directory. This is part of the impressive jobs system. * *clear_cache* - Clear django cache, useful when testing or deploying. * *compile_pyc* - Compile python bytecode files for the project. * *describe_form* - Used to display a form definition for a model. Copy and paste the contents into your forms.py and you're ready to go. * :doc:`delete_squashed_migrations` - Deletes leftover migrations after squashing and converts squashed migration to a normal one. * :doc:`dumpscript ` - Generates a Python script that will repopulate the database using objects. The advantage of this approach is that it is easy to understand, and more flexible than directly populating the database, or using XML. * `export_emails`_ - export the email addresses for your users in one of many formats. Currently supports Address, Google, Outlook, LinkedIn, and VCard formats. * *find_template* - Finds the location of the given template by resolving its path * *generate_secret_key* - Creates a new secret key that you can put in your settings.py module. * `graph_models`_ - Creates a GraphViz_ dot file. You need to send this output to a file yourself. Great for graphing your models. Pass multiple application names to combine all the models into a single dot file. * `list_model_info`_ - Lists out all the fields and methods for models in installed apps. This is helpful when you don't remember how to refer to a related field or want to quickly identify the fields and methods available in a particular model. * :doc:`mail_debug` - Starts a mail server which echos out the contents of the email instead of sending it. Requires `aiosmtpd`_ to be installed. * :doc:`merge_model_instances` - Merges duplicate model instances by reassigning related model references to a chosen primary model instance. * *notes* - Show all annotations like TODO, FIXME, BUG, HACK, WARNING, NOTE or XXX in your py and HTML files. * *passwd* - DEPRECATED: Use Django's ``changepassword``. * `print_settings`_ - Similar to ``diffsettings`` but shows *selected* active Django settings or *all* if no args passed. * *print_user_for_session* - Print the user information for the provided session key. this is very helpful when trying to track down the person who experienced a site crash. It seems this works only if setting ``SESSION_ENGINE`` is ``'django.contrib.sessions.backends.db'`` (default value). * *drop_test_database* - Drops the test database. Usefull when running Django test via some automated system (BuildBot, Jenkins, etc) and making sure that the test database is always dropped at the end. * *raise_test_exception* - Raises a test exception via command. Useful for debugging error reporters such as Sentry. * :doc:`reset_db` - Resets a database (currently sqlite3, mysql, postgres). Uses "DROP DATABASE" and "CREATE DATABASE". * *runjob* - Run a single maintenance job. Part of the jobs system. * *runjobs* - Runs scheduled maintenance jobs. Specify hourly, daily, weekly, monthly. Part of the jobs system. * :doc:`runprofileserver ` - Starts *runserver* with hotshot/profiling tools enabled. I haven't had a chance to check this one out, but it looks really cool. * `runscript`_ - Runs a script in the django context. * `runserver_plus`_ - The standard runserver stuff but with the Werkzeug debugger baked in. Requires Werkzeug_. This one kicks ass. * *set_fake_emails* - Give all users a new email based on their account data ("%(username)s@example.com" by default). Possible parameters are: username, first_name, last_name. *DEBUG only* * *set_fake_passwords* - Sets all user passwords to a common value (*password* by default). *DEBUG only*. * *show_template_tags* - Displays template tags and filters available in the current project. * *show_urls* - Displays the url routes that are defined in your project. Very crude at this point. * :doc:`sqldiff` - Prints the (approximated) difference between an app's models and what is in the database. This is very nice, but also very experimental at the moment. It can not catch everything but it's a great sanity check. * :doc:`sqlcreate` - Generates the SQL to create your database for you, as specified in settings.py. * :doc:`sqldsn` - Reads the Django settings and extracts the parameters needed to connect to databases using other programs. * `sync_s3`_ - Copies files found in settings.MEDIA_ROOT to S3. Optionally can also gzip CSS and Javascript files and set the Content-Encoding header, and also set a far future expires header for browser caching. * :doc:`syncdata` - Makes the current database have the same data as the fixture(s), no more, no less. * *unreferenced_files* - Prints a list of all files in MEDIA_ROOT that are not referenced in the database. * *update_permissions* - Reloads permissions for specified apps, or all apps if no args are specified. * :doc:`validate_templates` - Validate templates on syntax and compile errors. * *set_default_site* - Set parameters of the default `django.contrib.sites` Site using `name` and `domain` or `system-fqdn`. .. _`export_emails`: export_emails.html .. _`graph_models`: graph_models.html .. _`list_model_info`: list_model_info.html .. _`print_settings`: print_settings.html .. _`runscript`: runscript.html .. _`runserver_plus`: runserver_plus.html .. _`sync_s3`: sync_s3.html .. _GraphViz: https://www.graphviz.org/ .. _Werkzeug: https://werkzeug.palletsprojects.com/ .. _`aiosmtpd`: https://github.com/aio-libs/aiosmtpd django-extensions-django-extensions-ad01551/docs/command_signals.rst000066400000000000000000000057031477606640500257740ustar00rootroot00000000000000Command Signals =============== :synopsis: Signals fired before and after a command is executed. A signal is thrown pre/post each management command allowing your application to hook into each commands execution. Basic Example ------------- An example hooking into show_template_tags: :: from django_extensions.management.signals import pre_command, post_command from django_extensions.management.commands.show_template_tags import Command def pre_receiver(sender, args, kwargs): # I'm executed prior to the management command def post_receiver(sender, args, kwargs, outcome): # I'm executed after the management command pre_command.connect(pre_receiver, Command) post_command.connect(post_receiver, Command) Custom Permissions For All Models --------------------------------- You can use the post signal to hook into the ``update_permissions`` command so that you can add your own permissions to each model. For instance, lets say you want to add ``list`` and ``view`` permissions to each model. You could do this by adding them to the ``permissions`` tuple inside your models ``Meta`` class but this gets pretty tedious. An easier solution is to hook into the ``update_permissions`` call, as follows; :: from django.db.models.signals import post_syncdb from django.contrib.contenttypes.models import ContentType from django.contrib.auth.models import Permission from django_extensions.management.signals import post_command from django_extensions.management.commands.update_permissions import Command as UpdatePermissionsCommand def add_permissions(sender, **kwargs): """ Add view and list permissions to all content types. """ # for each of our content types for content_type in ContentType.objects.all(): for action in ['view', 'list']: # build our permission slug codename = "%s_%s" % (action, content_type.model) try: Permission.objects.get(content_type=content_type, codename=codename) # Already exists, ignore except Permission.DoesNotExist: # Doesn't exist, add it Permission.objects.create(content_type=content_type, codename=codename, name="Can %s %s" % (action, content_type.name)) print "Added %s permission for %s" % (action, content_type.name) post_command.connect(add_permissions, UpdatePermissionsCommand) Each time ``update_permissions`` is called ``add_permissions`` will be called which ensures there are view and list permissions to all content types. Using pre/post signals on your own commands ------------------------------------------- The signals are implemented using a decorator on the handle method of a management command, thus using this functionality in your own application is trivial: :: from django_extensions.management.utils import signalcommand class Command(BaseCommand): @signalcommand def handle(self, *args, **kwargs): ... ... django-extensions-django-extensions-ad01551/docs/conf.py000066400000000000000000000147731477606640500234120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # django-extensions documentation build configuration file, created by # sphinx-quickstart on Wed Apr 1 20:39:40 2009. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import os import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.append(os.path.abspath("..")) from django_extensions import VERSION, __version__ from django.utils.version import get_docs_version # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8' # The master toctree document. master_doc = "index" # General information about the project. project = "django-extensions" copyright = "Copyright (C) 2008-2025 Michael Trier, Bas van Oostveen and contributors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = get_docs_version(VERSION) # The full version, including alpha/beta/rc tags. release = __version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. # unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_use_modindex = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = "django-extensionsdoc" # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). # latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). # latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ( "index", "django-extensions.tex", "django-extensions Documentation", "Michael Trier, Bas van Oostveen, and contributors", "manual", ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # Additional stuff for the LaTeX preamble. # latex_preamble = '' # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_use_modindex = True django-extensions-django-extensions-ad01551/docs/create_template_tags.rst000066400000000000000000000010261477606640500270040ustar00rootroot00000000000000create_template_tags ==================== :synopsis: Creates a template tag directory structure within the specified application. Usage ----- Create templatetags directory for *foobar* app:: $ python manage.py create_template_tags foobar it will create directory structure:: foobar/ __init__.py models.py templatetags/ __init__.py foobar_tags.py you can pass custom tags filename by providing ``--name`` argument:: $ python manage.py create_template_tags foobar --name custom_tags django-extensions-django-extensions-ad01551/docs/creating_release.txt000066400000000000000000000020261477606640500261340ustar00rootroot00000000000000Creating a release ================== :synopsis: Creating a django-extensions release How to make a new release ------------------------- Get a fresh copy:: $ git clone git@github.com:django-extensions/django-extensions.git $ cd django-extensions Change version numbers in django_extensions/__init__.py and docs/conf.py:: $ vi django_extensions/__init__.py (1 occurance) Run tests:: $ ruff check $ ruff format --check $ tox --recreate Commit:: $ git commit -m v0.4.1 django_extensions/__init__.py docs/conf.py Tag it:: $ git tag 0.4.1 Remove old build directory (if exists):: $ rm -r build dist Install build dependency:: $ pip install build Prepare the release tarballs:: $ python -m build Upload release to pypi:: $ twine upload -i key-identity -s dist/* Bumb version number to new in-development pre version:: $ vi django_extensions/__init__.py $ git commit -m 'bumped version number' django_extensions/__init__.py Push changes back to github:: $ git push --tags $ git push django-extensions-django-extensions-ad01551/docs/debugger_tags.rst000066400000000000000000000010171477606640500254320ustar00rootroot00000000000000Debugger Tags ============= :synopsis: Allows you to use debugger breakpoints on Django templates. Introduction ------------ These templatetags make debugging Django templates easier. You can choose between ipdb, pdb or wdb filters. Usage ----- Make sure that you load `debugger_tags`:: {% load debugger_tags %} Now, you're ready to use debugger filters inside a template:: {% for object in object_list %} {{ object|ipdb }} {% endfor %} When rendering the template an ipdb session will be started. django-extensions-django-extensions-ad01551/docs/delete_squashed_migrations.rst000066400000000000000000000020661477606640500302300ustar00rootroot00000000000000delete_squashed_migrations ========================== :synopsis: Deletes leftover migrations after squashing and converts squashed migration to a normal one. Deletes leftover migrations after squashing and converts squashed migration to a normal one by removing the replaces attribute. This automates the clean up procedure outlined at the end of the `Django migration squashing documentation`__. Modifies your source tree! Use with care! __ MigrationSquashingDocs_ Example Usage ------------- With *django-extensions* installed you cleanup squashed migrations using the *delete_squashed_migrations* command:: # Delete leftover migrations from the first squashed migration found in myapp $ ./manage.py delete_squashed_migrations myapp # As above but non-interactive $ ./manage.py --noinput delete_squashed_migrations myapp # Explicitly specify the squashed migration to clean up $ ./manage.py delete_squashed_migrations myapp 0001_squashed .. _MigrationSquashingDocs: https://docs.djangoproject.com/en/dev/topics/migrations/#migration-squashing django-extensions-django-extensions-ad01551/docs/dumpscript.rst000066400000000000000000000047341477606640500250330ustar00rootroot00000000000000dumpscript ========== :synopsis: Generates a standalone Python script that will repopulate the database using objects. The `dumpscript` command generates a standalone Python script that will repopulate the database using objects. The advantage of this approach is that it is easy to understand, and more flexible than directly populating the database, or using XML. Why? ---- There are a few benefits to this: * less drama with model evolution: foreign keys handled naturally without IDs, new and removed columns are ignored * edit script to create 1,000s of generated entries using for loops, generated names, python modules etc. For example, an edited script can populate the database with test data:: for i in xrange(2000): poll = Poll() poll.question = "Question #%d" % i poll.pub_date = date(2001,01,01) + timedelta(days=i) poll.save() Real databases will probably be bigger and more complicated so it is useful to enter some values using the admin interface and then edit the generated scripts. Features -------- * *ForeignKey* and *ManyToManyFields* (using python variables, not object IDs) * Self-referencing *ForeignKey* (and M2M) fields * Sub-classed models * *ContentType* fields and generic relationships * Recursive references * *AutoFields* are excluded * Parent models are only included when no other child model links to it * Individual models can be referenced How? ---- To dump the data from all the models in a given Django app (`appname`):: $ ./manage.py dumpscript appname > scripts/testdata.py To dump the data from just a single model (`appname.ModelName`):: $ ./manage.py dumpscript appname.ModelName > scripts/testdata.py To reset a given app, and reload with the saved data:: $ ./manage.py reset appname $ ./manage.py runscript testdata Note: Runscript needs *scripts* to be a module, so create the directory and a *__init__.py* file. Caveats ------- Naming conflicts ~~~~~~~~~~~~~~~~ Please take care that when naming the output files these filenames do not clash with other names in your import path. For instance, if the appname is the same as the script name, an importerror can occur because rather than importing the application modules it tries to load the modules from the dumpscript file itself. Examples:: # Wrong $ ./manage.py dumpscript appname > dumps/appname.py # Right $ ./manage.py dumpscript appname > dumps/appname_all.py # Right $ ./manage.py dumpscript appname.Somemodel > dumps/appname_somemodel.py django-extensions-django-extensions-ad01551/docs/export_emails.rst000066400000000000000000000065371477606640500255170ustar00rootroot00000000000000export_emails ============= :synopsis: export the email addresses for your users in one of many formats Most Django sites include a registered user base. There are times when you would like to import these e-mail addresses into other systems (generic mail program, Gmail, Google Docs invites, give edit permissions, LinkedIn Group pre-approved listing, etc.). The export_emails command extension gives you this ability. Exported users can be filtered by Group name association. Example Usage ------------- :: # Export all the addresses in the '"First Last" ;' format. $ ./manage.py export_emails > addresses.txt :: # Export users from the group 'Attendees' in the linked in pre-approve Group csv format. $ ./manage.py export_emails -g Attendees -f linkedin pycon08.csv :: # Create a csv file importable by Gmail or Google Docs $ ./manage.py export_emails --format=google google.csv Supported Formats ----------------- address ^^^^^^^ This is the default basic text format. Each entry is on its own line in the format:: "First Last" ; This can be used with all known mail programs (that I know about anyway). google ^^^^^^ A CSV (comma separated value) format which Google applications can import. This can be used to import directly into Gmail, a Gmail mailing group, Google Docs invite (to read), Google Docs grant edit permissions, Google Calendar invites, etc. Only two columns are supplied. One for the person's name and one for the email address. This is also nice for importing into spreadsheets. outlook ^^^^^^^ A CSV (comma separated value) format which Outlook can parse and import. Supplies all the columns that Outlook 'requires', but only the name and email address are supplied. linkedin ^^^^^^^^ A CSV (comma separated value) format which can be imported by `LinkedIn Groups`_ to pre-approve a list of people for joining the group. This supplies 3 columns: first name, last name, and email address. This is the best generic csv file for importing into spreadsheets as well. vcard ^^^^^ A vCard format which Apple Address Book can parse and import. Settings -------- There are a couple of settings keys which can be configured in `settings.py`. Below the default values are shown: :: EXPORT_EMAILS_ORDER_BY = ['last_name', 'first_name', 'username', 'email'] EXPORT_EMAILS_FIELDS = ['last_name', 'first_name', 'username', 'email'] EXPORT_EMAILS_FULL_NAME_FUNC = None EXPORT_EMAILS_ORDER_BY ^^^^^^^^^^^^^^^^^^^^^^ Specifies the `order_by(...)` clause on the query being done into the database to retrieve the users. This determines the order of the output. EXPORT_EMAILS_FIELDS ^^^^^^^^^^^^^^^^^^^^ Specifies which fields will be selected from the database. This is most useful in combination with `EXPORT_EMAILS_FULL_NAME_FUNC` to select other fields you might want to use inside the custom function or when using a custom User model which does not have fields like 'first_name' and 'last_name'. EXPORT_EMAILS_FULL_NAME_FUNC ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A function to use to create a full name based on the database fields selected by `EXPORT_EMAILS_FULL_NAME_FUNC`. The default implementation can be looked up in https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/commands/export_emails.py#L23 .. _`LinkedIn Groups`: https://www.linkedin.com/static?key=groups_info django-extensions-django-extensions-ad01551/docs/field_extensions.rst000066400000000000000000000113241477606640500261740ustar00rootroot00000000000000Field Extensions ================ :synopsis: Field Extensions Database model field extensions. AutoSlugField ------------- AutoSlugField will automatically create a unique slug incrementing an appended number on the slug until it is unique. Inspired by SmileyChris' Unique Slugify snippet. AutoSlugField takes a `populate_from` argument that specifies which field, list of fields, or model method the slug will be populated from, for instance:: slug = AutoSlugField(populate_from=['title', 'description', 'get_author_name']) `populate_from` can traverse a ForeignKey relationship by using Django ORM syntax:: slug = AutoSlugField(populate_from=['related_model__title', 'related_model__get_readable_name']) AutoSlugField uses Django's slugify_ function by default to "slugify" ``populate_from`` field. .. _slugify: https://docs.djangoproject.com/en/dev/ref/utils/#django.utils.text.slugify To provide custom "slugify" function you could either provide the function as an argument to :py:class:`~AutoSlugField` or define your ``slugify_function`` method within a model. 1. ``slugify_function`` as an argument to :py:class:`~AutoSlugField`. .. code-block:: python # models.py from django.db import models from django_extensions.db.fields import AutoSlugField def my_slugify_function(content): return content.replace('_', '-').lower() class MyModel(models.Model): title = models.CharField(max_length=42) slug = AutoSlugField(populate_from='title', slugify_function=my_slugify_function) 2. ``slugify_function`` as a method within a model class. .. code-block:: python # models.py from django.db import models from django_extensions.db.fields import AutoSlugField class MyModel(models.Model): title = models.CharField(max_length=42) slug = AutoSlugField(populate_from='title') def slugify_function(self, content): return content.replace('_', '-').lower() **Important.** If you both provide ``slugify_function`` in a model class and pass ``slugify_function`` to :py:class:`~AutoSlugField` field, then model's ``slugify_function`` method will take precedence. RandomCharField --------------- AutoRandomCharField will automatically create a unique random character field with the specified length. By default upper/lower case and digits are included as possible characters. Given a length of 8 that yields 3.4 million possible combinations. A 12 character field would yield about 2 billion. Below are some examples:: >>> RandomCharField(length=8, unique=True) BVm9GEaE >>> RandomCharField(length=4, include_alpha=False) 7097 >>> RandomCharField(length=12, include_punctuation=True) k[ZS.TR,0LHO >>> RandomCharField(length=12, lowercase=True, include_digits=False) pzolbemetmok CreationDateTimeField --------------------- A ``DateTimeField`` that will automatically set its date when the object is first saved to the database. Works in the same way as the auto_now_add keyword. ModificationDateTimeField ------------------------- A ``DateTimeField`` that will automatically set its date when an object is saved to the database. Works in the same way as the auto_now keyword. It is possible to preserve the current timestamp by setting update_modified to False:: >>> example = MyTimeStampedModel.objects.get(pk=1) >>> print example.modified datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=) >>> example.save(update_modified=False) >>> print example.modified datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=) >>> example.save() >>> print example.modified datetime.datetime(2016, 4, 8, 14, 25, 43, 123456, tzinfo=) It is also possible to set the attribute directly on the model, for example when you don't use the TimeStampedModel provided in this package, or when you are in a migration:: >>> example = MyCustomModel.objects.get(pk=1) >>> print example.modified datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=) >>> example.update_modified=False >>> example.save() >>> print example.modified datetime.datetime(2016, 3, 18, 10, 3, 39, 740349, tzinfo=) ShortUUIDField --------------- A ``CharField`` which transparently generates a UUID and pass it to base57. It result in shorter 22 characters values useful e.g. for concise, unambiguous URLS. It's possible to get shorter values with length parameter: they are not Universal Unique any more but probability of collision is still low. JSONField --------- A generic ``TextField`` that neatly serializes/unserializes JSON objects seamlessly. Django 1.9 introduces a native JSONField for PostgreSQL, which is preferred for PostgreSQL users on Django 1.9 and above. django-extensions-django-extensions-ad01551/docs/generate_password.rst000066400000000000000000000014521477606640500263470ustar00rootroot00000000000000generate_password ================= :synopsis: Generates a new password that can be used for a user password. Introduction ------------- Generate password is a handy command to generate a new password which can be used for a user password. This uses Python's secret module `Recipes and best practices`_ to generate a password. There are two options. You can specify the length of password with the option ``--length``. If you don't specify ``--length``, a default value of 16 is applied. Using ``--complex`` will add punctuation to the aphabet of characters which the password will be generated from. Usage ----- Run :: $ python manage.py generate_password [--length=] [--complex] .. _Recipes and best practices: https://docs.python.org/3/library/secrets.html#recipes-and-best-practices django-extensions-django-extensions-ad01551/docs/graph_models.rst000066400000000000000000000117311477606640500253000ustar00rootroot00000000000000Graph models ============ :synopsis: Renders a graphical overview of your project or specified apps. Creates a GraphViz_ dot file for the specified app names based on their models.py. You can pass multiple app names and they will all be combined into a single model. Output is usually directed to a dot file. Several options are available: grouping models, including inheritance, excluding models and columns, and changing the layout when rendering to an output image. With the latest revisions it's also possible to specify an output file if pygraphviz_ is installed and render directly to an image or other supported file-type. Selecting a library ------------------- You need to select the library to generate the image. You can do so by passing the --pygraphviz or --pydot parameter, depending on which library you want to use. When neither of the command line parameters are given the default is to try and load pygraphviz or pydot (in that order) to generate the image. To install pygraphviz you usually need to run this command:: $ pip install pygraphviz It is possible you can't install it because it needs some C extensions to build. In that case you can try other methods to install or you can use PyDot. To install pydot you need to run this command:: $ pip install pyparsing pydot Installation should be fast and easy. Remember to install this exact version of pyparsing, otherwise it's possible you get this error: Couldn't import dot_parser, loading of dot files will not be possible. Default Settings ---------------- The option GRAPH_MODELS = {} can be used in the settings file to specify default options:: GRAPH_MODELS = { 'all_applications': True, 'group_models': True, } It uses the same names as on the command line only with the leading two dashes removed and the other dashes replaced by underscores. You can specify a list of applications with the *app_labels* key:: GRAPH_MODELS = { 'app_labels': ["myapp1", "myapp2", "auth"], } Templates --------- Django templates are used to generate the dot code. This in turn can be drawn into a image by libraries like *pygraphviz* or *pydot*. You can extend or override the templates if needed. Templates used: - django_extensions/graph_models/digraph.dot - django_extensions/graph_models/label.dot - django_extensions/graph_models/relation.dot Documentation on how to create dot files can be found here: https://www.graphviz.org/documentation/ .. warning:: Modifying Django's default templates behaviour might break *graph_models* Please be aware that if you use any *template_loaders* or extensions that change the way templates are rendered that this can cause *graph_models* to fail. An example of this is the Django app *django-template-minifier* this automatically removed the newlines before/after template tags even for non-HTML templates which leads to a malformed file. Example Usage ------------- With *django-extensions* installed you can create a dot-file or an image by using the *graph_models* command:: # Create a dot file $ ./manage.py graph_models -a > my_project.dot :: # Create a PNG image file called my_project_visualized.png with application grouping $ ./manage.py graph_models -a -g -o my_project_visualized.png # Same example but with explicit selection of pygraphviz or pydot $ ./manage.py graph_models --pygraphviz -a -g -o my_project_visualized.png $ ./manage.py graph_models --pydot -a -g -o my_project_visualized.png :: # Create a dot file for only the 'foo' and 'bar' applications of your project $ ./manage.py graph_models foo bar > my_project.dot :: # Create a graph for only certain models $ ./manage.py graph_models -a -I Foo,Bar -o my_project_subsystem.png :: # Create a graph excluding certain models $ ./manage.py graph_models -a -X Foo,Bar -o my_project_sans_foo_bar.png :: # Create a graph including models matching a given pattern and excluding some of them # It will first select the included ones, then filter out the ones to exclude $ ./manage.py graph_models -a -I Product* -X *Meta -o my_project_products_sans_meta.png :: # Create a graph without showing its edges' labels $ ./manage.py graph_models -a --hide-edge-labels -o my_project_sans_foo_bar.png :: # Create a graph with 'normal' arrow shape for relations $ ./manage.py graph_models -a --arrow-shape normal -o my_project_sans_foo_bar.png :: # Create a graph with colored edges for relations with on_delete settings $ ./manage.py graph_models -a --color-code-deletions -o my_project_colored.png :: # Create a graph with different layout direction, # supported directions: "TB", "LR", "BT", "RL" $ ./manage.py graph_models -a --rankdir BT -o my_project_sans_foo_bar.png :: # Create a graph with different edges ordering, # supported orders: "in", "out" $ ./manage.py graph_models -a --ordering in -o my_project_sans_foo_bar.png .. _GraphViz: https://www.graphviz.org/ .. _pygraphviz: https://pygraphviz.github.io/ .. _pydot: https://pypi.python.org/pypi/pydot django-extensions-django-extensions-ad01551/docs/index.rst000066400000000000000000000044021477606640500237400ustar00rootroot00000000000000.. django-extensions documentation master file, created by sphinx-quickstart on Wed Apr 1 20:39:40 2009. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to the django-extensions documentation! =============================================== Django Extensions is a collection of custom extensions for the Django Framework. These include management commands, additional database fields, admin extensions and much more. `这篇文档当然还有中文版 `_ Getting Started =============== The easiest way to figure out what Django Extensions are all about is to watch the `excellent screencast by Eric Holscher`__ (`Direct Vimeo link`__). In a couple minutes Eric walks you through a half a dozen command extensions. Getting it ========== You can get Django Extensions by using pip:: $ pip install django-extensions If you want to install it from source, grab the git repository and install:: $ git clone git://github.com/django-extensions/django-extensions.git $ cd django-extensions $ pip install . Then you will need to add the *django_extensions* application to the ``INSTALLED_APPS`` setting of your Django project *settings.py* file. For more detailed instructions check out our :doc:`installation_instructions`. Enjoy. Compatibility with versions of Python and Django ================================================= We follow the Django guidelines for supported Python and Django versions. See more at `Django Supported Versions `_ This might mean the django-extensions may work with older or unsupported versions but we do not guarantee it and most likely will not fix bugs related to incompatibilities with older versions. Contents ======== .. toctree:: :maxdepth: 2 installation_instructions admin_extensions command_extensions command_signals debugger_tags field_extensions jobs_scheduling model_extensions permissions utilities validators Indices and tables ================== * :ref:`search` __ https://ericholscher.com/blog/2008/sep/12/screencast-django-command-extensions/ __ https://vimeo.com/1720508 django-extensions-django-extensions-ad01551/docs/installation_instructions.rst000066400000000000000000000037071477606640500301650ustar00rootroot00000000000000Installation instructions ========================= :synopsis: Installing django-extensions Installing ---------- You can use pip to install django-extensions for usage:: $ pip install django-extensions Development ----------- Django-extensions is hosted on github:: https://github.com/django-extensions/django-extensions Source code can be accessed by performing a Git clone. Tracking the development version of *django command extensions* should be pretty stable and will keep you up-to-date with the latest fixes. $ pip install -e git+https://github.com/django-extensions/django-extensions.git#egg=django-extensions You find the sources in src/django-extensions now. You can verify that the application is available on your PYTHONPATH by opening a python interpreter and entering the following commands: :: >>> import django_extensions >>> django_extensions.VERSION (0, 8) Keep in mind that the current code in the git repository may be different from the packaged release. It may contain bugs and backwards-incompatible changes but most likely also new goodies to play with. Configuration ------------- You will need to add the *django_extensions* application to the INSTALLED_APPS setting of your Django project *settings.py* file.:: INSTALLED_APPS = ( ... 'django_extensions', ) This will make sure that Django finds the additional management commands provided by *django-extensions*. The next time you invoke *./manage.py help* you should be able to see all the newly available commands. Some commands or options require additional applications or python libraries, for example: * 'export_emails' will require the *python vobject* module to create vcard files. * 'graph_models' requires *pygraphviz* to render directly to image file. If the given application or python library is not installed on your system (or not in the python path) the executed command will raise an exception and inform you of the missing dependency. django-extensions-django-extensions-ad01551/docs/jobs_scheduling.rst000066400000000000000000000050061477606640500257740ustar00rootroot00000000000000Jobs Scheduling =============== :synopsis: Documentation on creating/using jobs in Django-extensions Creating jobs works much like management commands work in Django. Setup ----- Run :: $ python manage.py create_jobs to make a ``jobs`` directory inside of an application. The ``jobs`` directory will have the following tree:: jobs ├── daily │   └── __init__.py ├── hourly │   └── __init__.py ├── monthly │   └── __init__.py ├── weekly │   └── __init__.py ├── yearly │   └── __init__.py ├── __init__.py └── sample.py Create a job ------------ A job is a Python script with a mandatory ``BaseJob`` class which extends from ``MinutelyJob``, ``QuarterHourlyJob``, ``HourlyJob``, ``DailyJob``, ``WeeklyJob``, ``MonthlyJob`` or ``Yearly``. It has one method that must be implemented called ``execute``, which is called when the job is run. The directories ``hourly``, ``daily``, ``monthly``, ``weekly`` and ``yearly`` are used only to for organisation purpose. Note: If you want to use ``QuarterHourlyJob`` or ``Minutely`` job, create python package with name ``quarter_hourly`` or ``minutely`` respectively (similar to ``hourly`` or ``daily`` package). To create your first job you can start copying ``sample.py``. Remember to replace ``BaseJob`` with ``MinutelyJob``, ``QuarterHourlyJob``, ``HourlyJob``, ``DailyJob``, ``WeeklyJob``, ``MonthlyJob`` or ``Yearly``. Some simple examples are provided by the `django_extensions.jobs package `_. Note that each job should be in a new python script (within respective directory) and the class implementing the cron should be named ``Job``. Also, ``__init__.py`` file is not used for identifying jobs. Run a job --------- The following commands are related to jobs: * ``create_jobs``, create the directory structure for jobs * ``runjob``, run a single job * ``runjobs``, run all hourly/daily/weekly/monthly jobs Use "runjob(s) -l" to list all jobs recognized. Jobs do not run automatically! You must either run a job manually specifying the exact time on which the command is to be run, or use crontab: :: @hourly /path/to/my/project/manage.py runjobs hourly :: @daily /path/to/my/project/manage.py runjobs daily :: @weekly /path/to/my/project/manage.py runjobs weekly :: @monthly /path/to/my/project/manage.py runjobs monthly django-extensions-django-extensions-ad01551/docs/list_model_info.rst000066400000000000000000000040751477606640500260050ustar00rootroot00000000000000list_model_info =============== :synopsis: Lists out all the fields and methods for models in installed apps. Introduction ------------ When working with large projects or when returning to a code base after some time away, it can be challenging to remember all of the fields and methods associated with your models. This command makes it easy to see: * what fields are available * how they are referred to in queries * each field's class * each field's representation in the database * what methods are available * method signatures Commandline arguments ^^^^^^^^^^^^^^^^^^^^^ You can configure the output in a number of ways. :: # Show each field's class $ ./manage.py list_model_info --field-class :: # Show each field's database type representation $ ./manage.py list_model_info --db-type :: # Show each method's signature $ ./manage.py list_model_info --signature :: # Show all model methods, including private methods and django's default methods $ ./manage.py list_model_info --all-methods :: # Output only information for a single model, specifying the app and model using dot notation $ ./manage.py list_model_info --model users.User You can combine arguments. for instance, to list all methods and show the method signatures for the User model within the users app:: $ ./manage.py list_model_info --all --signature --model users.User Settings Configuration ^^^^^^^^^^^^^^^^^^^^^^ You can specify default values in your settings.py to simplify running this command. .. tip:: Commandline arguments override the following settings, allowing you to change options on the fly. To show each field's class:: MODEL_INFO_FIELD_CLASS = True To show each field's database type representation:: MODEL_INFO_DB_TYPE = True To show each method's signature:: MODEL_INFO_SIGNATURE = True To show all model methods, including private methods and django's default methods:: MODEL_INFO_ALL_METHODS = True To output only information for a single model, specify the app and model using dot notation:: MODEL_INFO_MODEL = 'users.User' django-extensions-django-extensions-ad01551/docs/list_signals.rst000066400000000000000000000004771477606640500253340ustar00rootroot00000000000000list_signals ============ :synopsis: Lists all signals defined in the project grouped by model and signal type Example Usage ------------- With *django-extensions* installed you can review all defined handlers using *list_signals* command:: # As above but non-interactive $ ./manage.py list_signals django-extensions-django-extensions-ad01551/docs/mail_debug.rst000066400000000000000000000043241477606640500247240ustar00rootroot00000000000000mail_debug ========== :synopsis: Starts a mail server which echos out the contents of the email instead of sending it. Installation ------------ This command requires installation of `aiosmtpd`_. You can get it from PyPI with:: pip install aiosmtpd .. _`aiosmtpd`: https://github.com/aio-libs/aiosmtpd Usage ----- You can start the mail server with the command:: $ python manage.py mail_debug Now accepting mail at 127.0.0.1:1025 -- use CONTROL-C to quit By default, it will start a process listening on port 1025 on local host. Assuming your Django settings ``EMAIL_HOST`` and ``EMAIL_PORT`` are configured to point to the same IP and port, in another terminal, open the Django shell and run .. code-block:: python from django.core.mail import send_mail send_mail( "Subject here", "Here is the message.", "from@example.com", ["to@example.com"], fail_silently=False, ) If you go back to the terminal with the ``mail_debug`` command is running, you should see the email coming through:: ---------- MESSAGE FOLLOWS ---------- Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Subject here From: from@example.com To: to@example.com Date: Sun, 19 Jan 2025 12:21:47 -0000 Message-ID: <173728930732.90349.12519699486821706188@1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa> X-Peer: 127.0.0.1 Here is the message. ------------ END MESSAGE ------------ Arguments --------- You can specify a different port by passing it as argument to the command:: $ python manage.py mail_debug 1026 Now accepting mail at 127.0.0.1:1026 -- use CONTROL-C to quit You can also pass the host + port separated by a colon, e.g.:: $ python manage.py mail_debug 192.168.1.1:1234 Now accepting mail at 192.168.1.1:1234 -- use CONTROL-C to quit Options ------- The command also accepts the following options: * ``--output``: Specifies an output file to send a copy of all messages (not flushed immediately). * ``--use-settings``: Uses EMAIL_HOST and HOST_PORT from Django settings. This option is ignored if the address or port is passed as an argument django-extensions-django-extensions-ad01551/docs/managestate.rst000066400000000000000000000046071477606640500251310ustar00rootroot00000000000000managestate =========== :synopsis: Saves current applied migrations to a file or applies migrations from this file. The `managestate` command fetches last applied migrations from a specified database and saves them to a specified file. After that, you may easily apply saved migrations. The advantage of this approach is that you may have at hand several database states and quickly switch between them. Why? ---- While you develop several features or fix some bugs at the same time you often meet the situation when you need to apply or unapply database migrations before you check out to another feature/bug branch. You always need to view current migrations by `showmigrations`, then apply or unapply it manually using `migrate` and there is no problem if you work with one Django app. But when there is more than one, it starts to annoy. To forget about the problem and quickly switch between branches use the `managestate` command. How? ---- To dump current migrations use:: $ ./manage.py managestate dump A state will be saved to `managestate.json` just about the following:: { "default": { "admin": "0003_logentry_add_action_flag_choices", "auth": "0012_alter_user_first_name_max_length", "contenttypes": "0002_remove_content_type_name", "sessions": "0001_initial", "sites": "0002_alter_domain_unique", "myapp": "zero" }, "updated_at": "2021-06-27 10:42:50.364070" } As you see, migrations have been saved as the state called "default". You can specify it using the positional argument:: $ ./manage.py managestate dump my_feature_branch Then migrations will be added to `managestate.json` under the key "my_feature_branch". To change the filename use `-f` or `--filename` flag. When you load a state from a file, you may also use all arguments defined for the `migrate` command. Examples -------- Save an initial database state of the branch "master/main" before developing features:: $ ./manage.py managestate dump master Check out to your branch, develop your feature, and dump its state when you are going to get reviewed:: $ ./manage.py managestate dump super-feature Check out to the "master" branch back and rollback a database state with just one command:: $ ./manage.py managestate load master If you need to add some improvements to your feature, just use:: $ ./manage.py managestate load super-feature django-extensions-django-extensions-ad01551/docs/merge_model_instances.rst000066400000000000000000000015611477606640500271620ustar00rootroot00000000000000merge_model_instances ========================== :synopsis: Merges duplicate model instances by reassigning related model references to a chosen primary model instance. *Note: This management command is in beta. Use with care, and make sure to test thoroughly before implementing.* Allows the user to choose a model to de-duplicate and a field on which to de-duplicate model instances. Provides an interactive session with the user to select the model to de-duplicate and the field on which to de-duplicate model instances. After merging model instances to one instance, deletes the merged model instances. Use with care! Example Usage ------------- With *django-extensions* installed you merge model instances using the *merge_model_instances* command:: # Delete leftover migrations from the first squashed migration found in myapp $ ./manage.py merge_model_instances django-extensions-django-extensions-ad01551/docs/model_extensions.rst000066400000000000000000000047401477606640500262150ustar00rootroot00000000000000Model Extensions ================ :synopsis: Model Extensions Introduction ------------ Django Extensions provides you a set of Abstract Base Classes for models that implements commonly used patterns like holding the model's creation and last modification dates. Database Model Extensions ------------------------- * *ActivatorModel* - Abstract Base Class that provides a ``status``, ``activate_date``, and ``deactivate_date`` fields. The ``status`` field is an ``IntegerField`` whose value is chosen from a tuple of choices - active and inactive - defaulting to active. This model also exposes a custom manager, allowing the user to easily query for active or inactive objects. E.g.: ``Model.objects.active()`` returns all instances of ``Model`` that have an active status. * *TitleDescriptionModel* - This Abstract Base Class model provides ``title`` and ``description`` fields. The ``title`` field is ``CharField`` with a maximum length of 255 characters, non-nullable. ``description``. On the other hand, ``description`` is a nullable ``TextField``. * *TimeStampedModel* - An Abstract Base Class model that provides self-managed ``created`` and ``modified`` fields. Both of the fields are customly defined in Django Extensions as ``CreationDateTimeField`` and ``ModificationDateTimeField``. Those fields are subclasses of Django's ``DateTimeField`` and will store the value of ``django.utils.timezone.now()`` on the model's creation and modification, respectively * *TitleSlugDescriptionModel* - An Abstract Base Class model that, like the ``TitleDescriptionModel``, provides ``title`` and ``description`` fields but also provides a self-managed ``slug`` field which populates from the title. That field's class is a custom defined `AutoSlugField `_, based on Django's ``SlugField``. By default, it uses ``-`` as a separator, is unique and does not accept blank values. It is possible to customize ``slugify_function`` by defining your custom function within a model: .. code-block:: python # models.py from django.db import models from django_extensions.db.models import TitleSlugDescriptionModel class MyModel(TitleSlugDescriptionModel, models.Model): def slugify_function(self, content): """ This function will be used to slugify the title (default `populate_from` field) """ return content.replace('_', '-').lower() See `AutoSlugField docs `_ for more details. django-extensions-django-extensions-ad01551/docs/permissions.rst000066400000000000000000000023321477606640500252040ustar00rootroot00000000000000Permissions ============== :synopsis: Permissions Mixins to limit access and model instances in a view. Introduction ------------ Django Extensions offers mixins for Class Based Views that make it easier to query and limit access to certain views. Current Mixins --------------------------------- * *ModelUserFieldPermissionMixin* - A Class Based View mixin that limits the accessibility to the view based on the "owner" of the view. This will check if the currently logged in user (``self.request.user``) matches the owner of the model instance. By default, the "owner" will be called "user". .. code-block:: python # models.py from django.db import models from django.conf import settings class MyModel(models.Model): author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete = models.CASCADE) content = models.TextField() .. code-block:: python # views.py from django.views.generic import UpdateView from django_extensions.auth.mixins import ModelUserFieldPermissionMixin from .models import MyModel class MyModelUpdateView(ModelUserFieldPermissionMixin, UpdateView): model = MyModel template_name = 'mymodels/update.html' model_permission_user_field = 'author' django-extensions-django-extensions-ad01551/docs/print_settings.rst000066400000000000000000000065511477606640500257140ustar00rootroot00000000000000print_settings ============== :synopsis: Django management command similar to ``diffsettings`` but shows *selected* active Django settings or *all* if no args passed. Introduction ------------ Django comes with a ``diffsettings`` command that shows how your project's settings differ from the Django defaults. Sometimes it is useful to just see the settings that are in effect for your project. This is particularly true if you have a more complex system for settings than just a single :file:`settings.py` file. For example, you might have settings files that import other settings file, such as dev, test, and production settings files that source a base settings file. This command also supports dumping the data in a few different formats. More Info --------------- The simplest way to run it is with no arguments:: $ python manage.py print_settings Some variations:: $ python manage.py print_settings --format=json $ python manage.py print_settings --format=yaml # Requires PyYAML $ python manage.py print_settings --format=pprint $ python manage.py print_settings --format=text $ python manage.py print_settings --format=value Show just selected settings:: $ python manage.py print_settings DEBUG INSTALLED_APPS $ python manage.py print_settings DEBUG INSTALLED_APPS --format=pprint $ python manage.py print_settings INSTALLED_APPS --format=value It is also possible to use shell-style wildcards:: $ python manage.py print_settings TIME* $ python manage.py print_settings *_DIRS STATIC* $ python manage.py print_settings INSTALLED_???? Yielding an error when a settings does not exist:: $ ./manage.py print_settings -f INSTALLED_APPZ CommandError: INSTALLED_APPZ not found in settings. For more info, take a look at the built-in help:: $ python manage.py print_settings --help usage: manage.py print_settings [-h] [-f] [--format FORMAT] [--indent INDENT] [--version] [-v {0,1,2,3}] [--settings SETTINGS] [--pythonpath PYTHONPATH] [--traceback] [--no-color] [--force-color] [--skip-checks] [setting [setting ...]] Print the active Django settings. positional arguments: setting Specifies setting to be printed. optional arguments: -h, --help show this help message and exit -f, --fail Fail if invalid setting name is given. --format FORMAT Specifies output format. --indent INDENT Specifies indent level for JSON and YAML --version show program's version number and exit -v {0,1,2,3}, --verbosity {0,1,2,3} Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output --settings SETTINGS The Python path to a settings module, e.g. "myproject.settings.main". If this isn't provided, the DJANGO_SETTINGS_MODULE environment variable will be used. --pythonpath PYTHONPATH A directory to add to the Python path, e.g. "/home/djangoprojects/myproject". --traceback Raise on CommandError exceptions --no-color Don't colorize the command output. --force-color Force colorization of the command output. --skip-checks Skip system checks. django-extensions-django-extensions-ad01551/docs/requirements.txt000066400000000000000000000000531477606640500253610ustar00rootroot00000000000000django sphinx>=8,<9 sphinx-rtd-theme>=3,<4 django-extensions-django-extensions-ad01551/docs/reset_db.rst000066400000000000000000000040241477606640500244200ustar00rootroot00000000000000reset_db ======== :synopsis: Fully resets your database by running DROP DATABASE and CREATE DATABASE Django command that resets your Django database, removing all data from all tables. This allows you to run all migrations again. By default the command will prompt you to confirm that all data will be deleted. This can be turned off with the ``--noinput``-argument. Supported engines ----------------- The command detects whether you're using a SQLite, MySQL, or Postgres database by looking up your Django database engine in the following lists. :: DEFAULT_SQLITE_ENGINES = ( 'django.db.backends.sqlite3', 'django.db.backends.spatialite', ) DEFAULT_MYSQL_ENGINES = ( 'django.db.backends.mysql', 'django.contrib.gis.db.backends.mysql', 'mysql.connector.django', ) DEFAULT_POSTGRESQL_ENGINES = ( 'django.db.backends.postgresql', 'django.db.backends.postgresql_psycopg2', 'django.db.backends.postgis', 'django.contrib.gis.db.backends.postgis', 'psqlextra.backend', 'django_zero_downtime_migrations.backends.postgres', 'django_zero_downtime_migrations.backends.postgis', ) If the engine you're using is not listed above, check the optional settings section below. Example Usage ------------- :: # Reset the DB so that it contains no data and migrations can be run again $ ./manage.py reset_db mybucket :: # Don't ask for a confirmation before doing the reset $ ./manage.py reset_db --noinput :: # Use a different user and password than the one from settings.py $ ./manage.py reset_db --user db_root --password H4rd2Guess Optional settings ----------------- It is possible to use a Django DB engine not in the lists above -- to do that add the approriate setting as shown below to your Django settings file:: # settings.py DJANGO_EXTENSIONS_RESET_DB_SQLITE_ENGINES = ['your_custom_sqlite_engine'] DJANGO_EXTENSIONS_RESET_DB_MYSQL_ENGINES = ['your_custom_mysql_engine'] DJANGO_EXTENSIONS_RESET_DB_POSTGRESQL_ENGINES = ['your_custom_postgres_engine'] django-extensions-django-extensions-ad01551/docs/runprofileserver.rst000066400000000000000000000071221477606640500262470ustar00rootroot00000000000000RunProfileServer ================ *We recommend that before you start profiling any language or framework you learn enough about it so that you feel comfortable with digging into its internals.* *Without sufficient knowledge it will not only be (very) hard but you're likely to make wrong assumptions (and fixes). As a rule of thumb, clean, well written code will help you a lot more than overzealous micro-optimizations will.* *This document is work in progress. If you feel you can help with better/clearer or additional information about profiling Django please leave a comment.* Introduction ------------ *runprofileserver* starts Django's runserver command with hotshot/profiling tools enabled. It will save .prof files containing the profiling information into the --prof-path directory. Note that for each request made one profile data file is saved. By default the profile-data-files are saved in /tmp use the --prof-path option to specify your own target directory. Saving the data in a meaningful directory structure helps to keep your profile data organized and keeps /tmp uncluttered. (Yes this probably malfunctions systems such as Windows where /tmp does not exist) To define profile filenames use --prof-file option. Default format is "{path}.{duration:06d}ms.{time}" (Python `Format Specification `_ is used). Examples: * "{time}-{path}-{duration}ms" - to order profile-data-files by request time * "{duration:06d}ms.{path}.{time}" - to order by request duration Profiler choice --------------- *runprofileserver* supports two profilers: *hotshot* and *cProfile*. Both come with the standard Python library but *cProfile* is more recent and may not be available on all systems. For this reason, *hotshot* is the default profiler. However, *hotshot* `is not maintained anymore `_ and using *cProfile* is usually the recommended way. If it is available on your system, you can use it with the option ``--use-cprofile``. Example:: $ mkdir /tmp/my-profile-data $ ./manage.py runprofileserver --use-cprofile --prof-path=/tmp/my-profile-data If you used the default profiler but are not able to open the profiling results with the ``pstats`` module or with your profiling GUI of choice because of an error "*ValueError: bad marshal data (unknown type code)*", try using *cProfile* instead. KCacheGrind ----------- Recent versions of *runprofileserver* have an option to save the profile data into a KCacheGrind compatible format. So you can use the excellent KCacheGrind tool for analyzing the profile data. Example:: $ mkdir /tmp/my-profile-data $ ./manage.py runprofileserver --kcachegrind --prof-path=/tmp/my-profile-data Validating models... 0 errors found Django version X.Y.Z, using settings 'complete_project.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C. [13/Nov/2008 06:29:38] "GET / HTTP/1.1" 200 41107 [13/Nov/2008 06:29:39] "GET /site_media/base.css?743 HTTP/1.1" 200 17227 [13/Nov/2008 06:29:39] "GET /site_media/logo.png HTTP/1.1" 200 3474 [13/Nov/2008 06:29:39] "GET /site_media/jquery.js HTTP/1.1" 200 31033 [13/Nov/2008 06:29:39] "GET /site_media/heading.png HTTP/1.1" 200 247 [13/Nov/2008 06:29:39] "GET /site_media/base.js HTTP/1.1" 200 751 $ kcachegrind /tmp/my-profile-data/root.12574391.592.prof Links ----- * https://code.djangoproject.com/wiki/ProfilingDjango * https://rk.edu.pl/en/django-profiling-hotshot-and-kcachegrind/ * https://simonwillison.net/2008/May/22/debugging/ django-extensions-django-extensions-ad01551/docs/runscript.rst000066400000000000000000000135171477606640500246710ustar00rootroot00000000000000RunScript ============= :synopsis: Runs a script in the Django context. Introduction ------------ The runscript command lets you run an arbitrary set of python commands within the Django context. It offers the same usability and functionality as running a set of commands in shell accessed by:: $ python manage.py shell Getting Started --------------- This example assumes you have followed the tutorial for Django 1.8+, and created a polls app containing a ``Question`` model. We will create a script that deletes all of the questions from the database. To get started create a scripts directory in your project root, next to manage.py:: $ mkdir scripts $ touch scripts/__init__.py Note: The *__init__.py* file is necessary so that the folder is picked up as a python package. Next, create a python file with the name of the script you want to run within the scripts directory:: $ touch scripts/delete_all_questions.py This file must implement a *run()* function. This is what gets called when you run the script. You can import any models or other parts of your django project to use in these scripts. For example:: # scripts/delete_all_questions.py from polls.models import Question def run(): # Fetch all questions questions = Question.objects.all() # Delete questions questions.delete() Note: You can put a script inside a *scripts* folder in any of your apps too. Usage ----- To run any script you use the command *runscript* with the name of the script that you want to run. For example:: $ python manage.py runscript delete_all_questions Note: The command first checks for scripts in your apps i.e. *app_name/scripts* folder and runs them before checking for and running scripts in the *project_root/scripts* folder. You can have multiple scripts with the same name and they will all be run sequentially. Passing arguments ----------------- You can pass arguments from the command line to your script by passing a space separated list of values with ``--script-args``. For example:: $ python manage.py runscript delete_all_questions --script-args staleonly The list of argument values gets passed as arguments to your *run()* function. For example:: # scripts/delete_all_questions.py from datetime import timedelta from django.utils import timezone from polls.models import Question def run(*args): # Get all questions questions = Question.objects.all() if 'staleonly' in args: # Only get questions more than 100 days old questions = questions.filter(pub_date__lt=timezone.now() - timedelta(days=100)) # Delete questions questions.delete() Setting execution directory --------------------------- You can set scripts execution directory using ``--chdir`` option or ``settings.RUNSCRIPT_CHDIR``. You can also set scripts execution directory policy using ``--dir-policy`` option or ``settings.RUNSCRIPT_CHDIR_POLICY``. It can be one of the following: * **none** - start all scripts in current directory. * **each** - start all scripts in their directories. * **root** - start all scripts in ``BASE_DIR`` directory. Assume this simplified directory structure:: django_project_dir/ ├-first_app/ │ └-scripts/ │ ├-first_script.py ├-second_app/ │ └-scripts/ │ ├-second_script.py ├-manage.py ├-other_folder/ │ └-some_file.py Assume you are in ``other_folder`` directory. You can set execution directory for both scripts using this command:: $ python ../manage.py runscript first_script second_script --chdir /django_project_dir/second_app # scripts will be executed from second_app directory You can run both scripts with ``NONE`` policy using this command:: $ python ../manage.py runscript first_script second_script --dir-policy none # scripts will be executed from other_folder directory You can run both scripts with ``EACH`` policy using this command:: $ python ../manage.py runscript first_script second_script --dir-policy each # first_script will be executed from first_app and second script will be executed from second_app You can run both scripts with ``ROOT`` policy using this command:: $ python ../manage.py runscript first_script second_script --dir-policy root # scripts will be executed from django_project_dir directory Errors and exit codes --------------------- If an exception is encountered the execution of the scripts will stop, a traceback is shown and the command will return an exit code. To control the exit-code you can either use `CommandError("something went terribly wrong", returncode=123)` in your script or has the `run(...)` function return the exit_code. Where any exit code other then 0 will indicate failure, just like regular shell commands. This means you can use `runscript` in your CI/CD pipelines or other automated scripts and it should behave like any other shell command. Continue on errors ------------------ If you want runscript to continue running scripts even if errors occurs you can set `-c`:: $ python manage.py runscript delete_all_questions another_script --continue-on-error This will continue running 'another_script' even if an exception was raised or exit code was returned in 'delete_all_questions'. When all the scripts has been run `runscript` will exit with the last non-zero exit code. Note: It is possible to do `raise CommandError(..., returncode=0)` which will lead to an exception with exit code 0. Debugging --------- If an exception occurs you will get a traceback by default. You can use `CommandError` in the same way as with other custom management commands. To get a traceback from a `CommandError` specify ``--traceback``. For example:: $ python manage.py runscript delete_all_questions --traceback If you do not want to see tracebacks at all you can specify:: $ python manage.py runscript delete_all_questions --no-traceback django-extensions-django-extensions-ad01551/docs/runserver_plus.rst000066400000000000000000000225441477606640500257360ustar00rootroot00000000000000RunServerPlus ============= :synopsis: RunServerPlus-typical runserver with Werkzeug debugger baked in Introduction ------------ This item requires that you have the `Werkzeug WSGI utilities` installed. Included with Werkzeug_ is a kick ass debugger that renders nice debugging tracebacks and adds an AJAX based debugger (which allows code execution in the context of the traceback’s frames). Additionally it provides a nice access view to the source code. Getting Started --------------- To get started we just use the *runserver_plus* command instead of the normal *runserver* command:: $ python manage.py runserver_plus * Running on http://127.0.0.1:8000/ * Restarting with reloader... Validating models... 0 errors found Django version X.Y.Z, using settings 'screencasts.settings' Development server is running at http://127.0.0.1:8000/ Using the Werkzeug debugger (https://werkzeug.palletsprojects.com/) Quit the server with CONTROL-C. Note: all normal runserver options apply. In other words, if you need to change the port number or the host information, you can do so like you would normally. Usage ----- Instead of the default Django traceback page, the Werkzeug traceback page will be shown when an exception occurs. .. image:: https://f.cloud.github.com/assets/202559/1261027/2637f826-2c22-11e3-83c6-646acc87808b.png :alt: werkzeug-traceback Along with the typical traceback information we have a couple of options. These options appear when hovering over a particular traceback line. Notice that two buttons appear to the right: .. image:: https://f.cloud.github.com/assets/202559/1261035/558ad0ee-2c22-11e3-8ddd-6678d84d77e7.png :alt: werkzeug-options The options are: View Source ^^^^^^^^^^^ This displays the source underneath the traceback: .. image:: https://f.cloud.github.com/assets/202559/1261036/583c8c42-2c22-11e3-9eb9-5c16b8732512.png :alt: werkzeug-source Being able to view the source file is handy because it provides more context information around the error. The actual traceback areas are highlighted so they are easy to spot. One awkward aspect of the UI is that the page is not scrolled to the bottom. At first I thought nothing was happening because of this. Interactive Debugging Console ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clicking on this button opens up a new pane under the traceback line you're on. This is the money shot: .. image:: https://f.cloud.github.com/assets/202559/1261037/5d12eda6-2c22-11e3-802a-2639ff8813fa.png :alt: werkzeug-debugger An ajax based console appears in the pane and you can start debugging. Notice in the screenshot above I did a `print environ` to see what was in the environment parameter coming into the function. *WARNING*: This should *never* be used in any kind of production environment. Not even for a quick problem check. I cannot emphasize this enough. The interactive debugger allows you to evaluate python code right against the server. You've been warned. .. _`Werkzeug WSGI utilities`: https://werkzeug.palletsprojects.com/ SSL ^^^ runserver_plus also supports SSL, so that you can easily debug bugs that pop up when https is used. To use SSL simply provide a file name for certificates; a key and certificate file will be automatically generated:: $ python manage.py runserver_plus --cert-file cert.crt Validating models... 0 errors found Django version X.Y.Z, using settings 'mysite.settings' Development server is running at http://127.0.0.1:8000/ Using the Werkzeug debugger (https://werkzeug.palletsprojects.com/) Quit the server with CONTROL-C. * Running on https://127.0.0.1:8000/ * Restarting with reloader Validating models... 0 errors found Django version X.Y.Z, using settings 'mysite.settings' Development server is running at http://127.0.0.1:8000/ Using the Werkzeug debugger (https://werkzeug.palletsprojects.com/) Quit the server with CONTROL-C. After running this command, your web application can be accessed through https://127.0.0.1:8000. You will also find that two files are created in the current working directory: a key file and a certificate file. If you run the above command again, these certificate files will be reused so that you do not have to keep accepting the self-generated certificates from your browser every time. You can also provide a specific file for the certificate to be used if you already have one:: $ python manage.py runserver_plus --cert-file /tmp/cert.crt Note that you need the OpenSSL library to use SSL, and Werkzeug 0.9 or later if you want to reuse existing certificates. To install OpenSSL:: $ pip install pyOpenSSL Certificates paths ^^^^^^^^^^^^^^^^^^ You can configure different paths to .crt and .key files. At least one of ``--cert-file`` or ``--key-file`` must be defined to use SSL. You can set path to .crt file using ``--cert-file`` option or deprecated ``--cert`` option which is currently an alias for ``--cert-file``. If this option is not set than runserver_plus assumes that, this file is in the same directory as file from ``--key-file`` option. You can set path to .key file using ``--key-file`` option. If this option is not set than runserver_plus assumes that, this file is in the same directory as file from ``--cert-file`` option. If you want to create new files, than you can pass file name without extension. Proper files with this name and .crt and .key extensions will be created. Configuration ^^^^^^^^^^^^^ The `RUNSERVERPLUS_SERVER_ADDRESS_PORT` setting can be configured to specify which address and port the development server should bind to. If you find yourself frequently starting the server with:: $ python manage.py runserver_plus 0.0.0.0:8000 You can use settings to automatically default your development to an address/port:: RUNSERVERPLUS_SERVER_ADDRESS_PORT = '0.0.0.0:8000' To ensure Werkzeug can log to the console, you may need to add the following to your settings:: LOGGING = { ... 'handlers': { ... 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { ... 'werkzeug': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }, }, } Other configuration options and their defaults include: :: # Truncate SQL queries to this many characters (None means no truncation) RUNSERVER_PLUS_PRINT_SQL_TRUNCATE = 1000 # After how many seconds auto-reload should scan for updates in poller-mode RUNSERVERPLUS_POLLER_RELOADER_INTERVAL = 1 # Werkzeug reloader type [auto, watchdog, or stat] RUNSERVERPLUS_POLLER_RELOADER_TYPE = 'auto' # Add extra files to watch RUNSERVER_PLUS_EXTRA_FILES = [] # Do not watch files matching any of these patterns RUNSERVER_PLUS_EXCLUDE_PATTERNS = [] IO Calls and CPU Usage ^^^^^^^^^^^^^^^^^^^^^^ As noted in gh625_ `runserver_plus` can be seen to use a lot of CPU and generate many I/O when idle. This is due to the way Werkzeug_ has implemented the auto reload capability. It supports two ways of doing auto reloading either via `stat polling` or `file system events`. The `stat polling` approach is pretty brute force and continously issues `stat` system calls which causes the CPU and IO load. If possible try to install the Watchdog_ package, this should automatically cause Werkzeug_ to use `file system events` whenever possible. You can read more about this in `Werkzeug documentation `_ You can also increase the poll interval when using `stat polling` from the default of 1 second. This will decrease the CPU load at the expense of file edits taking longer to pick up. This can be set two ways, in the django settings file:: RUNSERVERPLUS_POLLER_RELOADER_INTERVAL = 5 or as a commad line argument:: $ python manage.py runserver_plus --reloader-interval 5 Debugger PIN ------------ .. epigraph:: The following text about the debugger PIN is taken verbatim from the Werkzeug `documentation about its debugger PIN `_. Starting with Werkzeug 0.11 the debugger is additionally protected by a PIN. This is a security helper to make it less likely for the debugger to be exploited in production as it has happened to people to keep the debugger active. The PIN based authentication is enabled by default. When the debugger comes up, on first usage it will prompt for a PIN that is printed to the command line. The PIN is generated in a stable way that is specific to the project. In some situations it might be not possible to generate a stable PIN between restarts in which case an explicit PIN can be provided through the environment variable WERKZEUG_DEBUG_PIN. This can be set to a number and will become the PIN. This variable can also be set to the value off to disable the PIN check entirely. The PIN can also be disabled by passing the argument ``--nopin`` when calling the runserver_plus command. If the PIN is entered too many times incorrectly the server needs to be restarted. **This feature is not supposed to entirely secure the debugger. It’s intended to make it harder for an attacker to exploit the debugger. Never enable the debugger in production.** .. _gh625: https://github.com/django-extensions/django-extensions/issues/625 .. _Werkzeug: https://werkzeug.palletsprojects.com/ .. _Watchdog: https://pypi.python.org/pypi/watchdog django-extensions-django-extensions-ad01551/docs/shell_plus.rst000066400000000000000000000351171477606640500250120ustar00rootroot00000000000000shell_plus ========== :synopsis: Django shell with autoloading of the apps database models and subclasses of user-defined classes. Interactive Python Shells ------------------------- There is support for three different types of interactive python shells. IPython:: $ ./manage.py shell_plus --ipython bpython:: $ ./manage.py shell_plus --bpython ptpython:: $ ./manage.py shell_plus --ptpython Python:: $ ./manage.py shell_plus --plain It is possible to directly add command line arguments to the underlying Python shell using ``--``:: $ ./manage.py shell_plus --ipython -- --profile=foo The default resolution order is: ptpython, bpython, ipython, python. You can also set the configuration option SHELL_PLUS to explicitly specify which version you want. :: # Always use IPython for shell_plus SHELL_PLUS = "ipython" It is also possible to use `IPython Notebook`_, an interactive Python shell which uses a web browser as its user interface, as an alternative shell:: $ ./manage.py shell_plus --notebook Or with JupyterLab (a more feature-rich variant of Jupyter Notebook):: $ ./manage.py shell_plus --lab In addition to being savable, IPython Notebooks can be updated (while running) to reflect changes in a Django application's code with the menu command `Kernel > Restart`. Configuration ------------- Sometimes, models from your own apps and other people's apps have colliding names, or you may want to completely skip loading an app's models. Here are some examples of how to do that. Note: These settings are only used inside shell_plus and will not affect your environment. :: # Rename the automatic loaded module Messages in the app blog to blog_messages. SHELL_PLUS_MODEL_ALIASES = {'blog': {'Messages': 'blog_messages'},} :: # Prefix all automatically loaded models in the app blog with myblog. SHELL_PLUS_APP_PREFIXES = {'blog': 'myblog',} :: # Dont load the 'sites' app, and skip the model 'pictures' in the app 'blog' SHELL_PLUS_DONT_LOAD = ['sites', 'blog.pictures'] :: # Dont load any models SHELL_PLUS_DONT_LOAD = ['*'] You can also combine model_aliases and dont_load. When referencing nested modules, e.g. `somepackage.someapp.models.somemodel`, omit the package name and the reference to `models`. For example: :: SHELL_PLUS_DONT_LOAD = ['someapp.somemodel', ] # This works SHELL_PLUS_DONT_LOAD = ['somepackage.someapp.models.somemodel', ] # This does NOT work It is possible to ignore autoloaded modules when using manage.py, like:: $ ./manage.py shell_plus --dont-load app1 --dont-load app2.module1 Command line parameters and settings in the configuration file are merged, so you can safely append modules to ignore from the commandline for one-time usage. Other configuration options include: :: # Always use IPython for shell_plus SHELL_PLUS = "ipython" :: SHELL_PLUS_PRINT_SQL = True # Truncate sql queries to this number of characters (this is the default) SHELL_PLUS_PRINT_SQL_TRUNCATE = 1000 # To disable truncation of sql queries use SHELL_PLUS_PRINT_SQL_TRUNCATE = None # Specify sqlparse configuration options when printing sql queries to the console SHELL_PLUS_SQLPARSE_FORMAT_KWARGS = dict( reindent_aligned=True, truncate_strings=500, ) # Specify Pygments formatter and configuration options when printing sql queries to the console import pygments.formatters SHELL_PLUS_PYGMENTS_FORMATTER = pygments.formatters.TerminalFormatter SHELL_PLUS_PYGMENTS_FORMATTER_KWARGS = {} :: # Additional IPython arguments to use IPYTHON_ARGUMENTS = [] IPYTHON_KERNEL_DISPLAY_NAME = "Django Shell-Plus" # Additional Notebook arguments to use NOTEBOOK_ARGUMENTS = [] NOTEBOOK_KERNEL_SPEC_NAMES = ["python3", "python"] Collision resolvers ------------------- You don't have to worry about inaccessibility of models with conflicting names. If you have conflicting model names, all conflicts can be resolved automatically. All models will be available under shell_plus, some of them with intuitive aliases. This mechanism is highly configurable and you must only set ``SHELL_PLUS_MODEL_IMPORTS_RESOLVER``. You should set full path to collision resolver class. All predefined collision resolvers are in ``django_extensions.collision_resolvers`` module. Example:: SHELL_PLUS_MODEL_IMPORTS_RESOLVER = 'django_extensions.collision_resolvers.FullPathCR' All collision resolvers searches for models with the same name. If conflict is detected they decides, which model to choose. Some of them are creating aliases for all conflicting models. **Example** Suppose that we have two apps: - programming(with models Language and Framework) - workers(with models Language and Worker) 'workers' app is last in alphabetical order, but suppose that 'programming' app is occurs firstly in ``INSTALLED_APPS``. Collision resolvers won't change aliases for models Framework and Worker, because their names are unique. There are several types of collision resolvers: **LegacyCR** Default collision resolver. Model from last application in alphabetical order is selected:: from workers import Language **InstalledAppsOrderCR** Collision resolver which selects the first model from INSTALLED_APPS. You can set your own app priorities list subclassing him and overwriting ``APP_PRIORITIES`` field. This collision resolver will select a model from the first app on this list. If both app's are absent on this list, resolver will choose a model from the first app in alphabetical order:: from programming import Language **FullPathCR** Collision resolver which transform full model name to alias by changing dots to underscores. He also removes 'models' part of alias, because all models are in models.py files. Model from last application in alphabetical order is selected:: from programming import Language (as programming_Language) from workers import Language, Language (as workers_Language) **AppNamePrefixCR** Collision resolver which transform pair (app name, model_name) to alias ``{app_name}_{model_name}``. Model from last application in alphabetical order is selected. Result is different than FullPathCR, when model has app_label other than current app:: from programming import Language (as programming_Language) from workers import Language, Language (as workers_Language) **AppNameSuffixCR** Collision resolver which transform pair (app name, model_name) to alias ``{model_name}_{app_name}`` Model from last application in alphabetical order is selected:: from programming import Language (as Language_programming) from workers import Language, Language (as Language_workers) **AppNamePrefixCustomOrderCR** Collision resolver which is mixin of AppNamePrefixCR and InstalledAppsOrderCR. In case of collisions he sets aliases like AppNamePrefixCR, but sets the default model using InstalledAppsOrderCR:: from programming import Language, Language (as programming_Language) from workers import Language (as workers_Language) **AppNameSuffixCustomOrderCR** Collision resolver which is a mixin of AppNameSuffixCR and InstalledAppsOrderCR. In case of collisions he sets aliases like AppNameSuffixCR, but sets the default model using InstalledAppsOrderCR:: from programming import Language, Language (as Language_programming) from workers import Language (as Language_workers) **FullPathCustomOrderCR** Collision resolver which is a mixin of FullPathCR and InstalledAppsOrderCR. In case of collisions he sets aliases like FullPathCR, but sets the default model using InstalledAppsOrderCR:: from programming import Language, Language (as programming_Language) from workers import Language (as workers_Language) **AppLabelPrefixCR** Collision resolver which transform pair (app_label, model_name) to alias ``{app_label}_{model_name}`` This is very similar to ``AppNamePrefixCR`` but this may generate shorter names in the case of apps nested into several namespace (like Django's auth app):: # with AppNamePrefixCR from django.contrib.auth.models import Group (as django_contrib_auth_Group) # with AppLabelPrefixCR from django.contrib.auth.models import Group (as auth_Group) **AppLabelSuffixCR** Collision resolver which transform pair (app_label, model_name) to alias ``{model_name}_{app_label}`` Similar idea as the above, but based on ``AppNameSuffixCR``:: # with AppNamePrefixCR from django.contrib.auth.models import Group (as Group_django_contrib_auth) # with AppLabelSuffixCR from django.contrib.auth.models import Group (as Group_auth) Writing your custom collision resolver -------------------------------------- You can customize models import behaviour by subclassing one of the abstract collision resolvers: **PathBasedCR** Abstract resolver which transforms full model name into alias. To use him you need to overwrite transform_import function which should have one parameter. It will be a full model name. It should return valid alias as a str instance. **AppNameCR** Abstract collision resolver which transform pair (app name, model_name) to alias by changing dots to underscores. You must define ``MODIFICATION_STRING`` which should be string to format with two keyword arguments: app_name and model_name. For example: ``{app_name}_{model_name}``. Model from last application in alphabetical order is selected. You can mix PathBasedCR or AppNameCR with InstalledAppsOrderCR, but InstalledAppsOrderCR should be the second base class. **BaseCR** Abstract base collision resolver. All collision resolvers needs to inherit from this class. To write a custom collision resolver you need to overwrite the resolve_collisions function. It receives ``Dict[str, List[str]]`` where key is model name and values are full model names (full model name means: module + model_name). You should return ``Dict[str, str]``, where key is model name and value is full model name. Import Subclasses ------------------- If you want to load automatically all project subclasses of some base class, you can achieve this by setting ``SHELL_PLUS_SUBCLASSES_IMPORT`` option. It must be a list of either classes or strings containing paths to these classes. For example, if you want to load all your custom managers then you should provide:: from django.db.models import Manager SHELL_PLUS_SUBCLASSES_IMPORT = [Manager] Then shell_plus will load all your custom managers:: # Shell Plus Subclasses Imports from utils.managers import AbstractManager from myapp.managers import MyCustomManager from somewhere.else import MyOtherManager # django.db.models.Manager is not loaded because only project classes are. By default, all subclasses of your base class from all projects modules will be loaded. You can exclude some modules and all their submodules by passing ``SHELL_PLUS_SUBCLASSES_IMPORT_MODULES_BLACKLIST`` option:: SHELL_PLUS_SUBCLASSES_IMPORT_MODULES_BLACKLIST = ['utils', 'somewhere.else'] Elements of this list must be strings containing full modules paths. If these modules are excluded only ``MyCustomManager`` from ``myapp.managers`` will be loaded. If you are using ``SHELL_PLUS_SUBCLASSES_IMPORT`` shell_plus loads all project modules for finding subclasses. Sometimes it can lead to some errors(for example when we have an old unused module which contains syntax errors). Excluding these modules can help avoid shell_plus crashes in some situations. It is recommended to exclude all ``setup.py`` files. IPython Notebook ---------------- There are two settings that you can use to pass your custom options to the IPython Notebook in your Django settings. The first one is ``NOTEBOOK_ARGUMENTS`` that can be used to hold those options that available via:: $ ipython notebook -h For example:: NOTEBOOK_ARGUMENTS = [ '--ip', 'x.x.x.x', '--port', 'xx', ] Another one is ``IPYTHON_ARGUMENTS`` that for those options that available via:: $ ipython -h The Django settings module and database models are auto-loaded into the interactive shell's global namespace also for IPython Notebook. Auto-loading is done by a custom IPython extension which is activated by default by passing the ``--ext django_extensions.management.notebook_extension`` argument to the Notebook. If you need to pass custom options to the IPython Notebook, you can override the default options in your Django settings using the ``IPYTHON_ARGUMENTS`` setting. For example:: IPYTHON_ARGUMENTS = [ '--ext', 'django_extensions.management.notebook_extension', '--ext', 'myproject.notebook_extension', '--debug', ] To activate auto-loading, remember to either include the django-extensions' default notebook extension or copy its auto-loading code into your own extension. Note that the IPython Notebook feature doesn't currently honor the ``--dont-load`` option. .. _`IPython Notebook`: https://ipython.org/ipython-doc/dev/interactive/htmlnotebook.html Additional Imports ------------------ In addition to importing the models, you can specify other items to import by default. These can be specified with the settings ``SHELL_PLUS_IMPORTS``, ``SHELL_PLUS_PRE_IMPORTS`` and ``SHELL_PLUS_POST_IMPORTS``. The order of import loading is as follows: - ``SHELL_PLUS_PRE_IMPORTS`` - Subclasses (if enabled) - Models (if not disabled) - Default Django imports (if not disabled) - ``SHELL_PLUS_IMPORTS`` - ``SHELL_PLUS_POST_IMPORTS`` Example for in your ``settings.py`` file: :: SHELL_PLUS_IMPORTS = [ 'from module.submodule1 import class1, function2', 'from module.submodule2 import function3 as another1', 'from module.submodule3 import *', 'import module.submodule4', ] These symbols will be available as soon as the shell starts. Database application signature ------------------------------ If using PostgreSQL the ``application_name`` is set by default to ``django_shell`` to help identify queries made under shell_plus. SQL queries ------------------------- If the configuration option DEBUG is set to True, it is possible to print SQL queries as they're executed in shell_plus like:: $ ./manage.py shell_plus --print-sql You can also set the configuration option SHELL_PLUS_PRINT_SQL to omit the above command line option. :: # print SQL queries in shell_plus SHELL_PLUS_PRINT_SQL = True Printing SQL queries also comes with the possibility of specifying the maximum amount of characters to display: $ ./manage.py shell_plus --print-sql --truncate-sql `--truncate-sql` accepts an int value starting from 0 (which disables truncation). Defaults to 1000. You can also set the configuration option SHELL_PLUS_PRINT_SQL_TRUNCATE to omit the above command line option. :: # print SQL queries in shell_plus SHELL_PLUS_PRINT_SQL_TRUNCATE = None django-extensions-django-extensions-ad01551/docs/show_permissions.rst000066400000000000000000000037341477606640500262530ustar00rootroot00000000000000Show Permissions ================ :synopsis: Show all permissions for Django models Introduction ------------ The ``show_permissions`` management command lists all permissions for the models in your Django project. By default, it excludes built-in Django apps such as ``admin``, ``auth``, ``contenttypes``, and ``sessions``. This command is useful to quickly inspect the permissions assigned to models, especially when customizing permission logic or managing role-based access. Basic Usage ----------- .. code-block:: bash python manage.py show_permissions This will output the list of permissions for models in all installed apps **excluding** built-in Django apps. Examples -------- Show permissions for specific apps and models: .. code-block:: bash python manage.py show_permissions blog python manage.py show_permissions blog.Post Show permissions including built-in Django apps: .. code-block:: bash python manage.py show_permissions --all Show permissions for only a specific app using the `--app-label` option: .. code-block:: bash python manage.py show_permissions --app-label blog Options ------- * ``--all`` Include permissions for Django’s built-in apps (``admin``, ``auth``, ``contenttypes``, ``sessions``). * ``--app-label