Update venv

This commit is contained in:
Krzysztof Bonecki 2021-01-08 22:29:33 +01:00
parent 0c01443cf1
commit 30c8142ed6
269 changed files with 16269 additions and 0 deletions

View File

@ -0,0 +1,19 @@
Copyright (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.

View File

@ -0,0 +1,160 @@
Metadata-Version: 2.1
Name: django-extensions
Version: 3.1.0
Summary: Extensions for Django
Home-page: http://github.com/django-extensions/django-extensions
Author: Michael Trier
Author-email: mtrier@gmail.com
Maintainer: Bas van Oostveen
Maintainer-email: v.oostveen@gmail.com
License: MIT License
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 2.2
Classifier: Framework :: Django :: 3.0
Classifier: Framework :: Django :: 3.1
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Utilities
Requires-Python: >=3.5
===================
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://secure.travis-ci.org/django-extensions/django-extensions.svg?branch=master
:alt: Build Status
:target: http://travis-ci.org/django-extensions/django-extensions
.. 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 2.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 and run setup.py::
$ git clone git://github.com/django-extensions/django-extensions.git
$ cd django-extensions
$ python setup.py install
Installing It
=============
To enable `django_extensions` in your project you need to add it to `INSTALLED_APPS` in your projects
`settings.py` file::
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: http://groups.google.com/group/django-extensions
- Translations: https://www.transifex.net/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 development 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 :-)
__ http://ericholscher.com/blog/2008/sep/12/screencast-django-command-extensions/
__ http://vimeo.com/1720508
__ https://www.youtube.com/watch?v=1F6G3ONhr4k

View File

@ -0,0 +1,269 @@
django_extensions-3.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
django_extensions-3.1.0.dist-info/LICENSE,sha256=hfh-J08r7s6vlJVWdNgyPZ_B69b8NdSvzdOLVEygyyA,1057
django_extensions-3.1.0.dist-info/METADATA,sha256=s6kXf5nBkTspRmS5YFVVQvDe724Mhvw3heUNnWWS24E,5017
django_extensions-3.1.0.dist-info/RECORD,,
django_extensions-3.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions-3.1.0.dist-info/WHEEL,sha256=EVRjI69F5qVjm_YgqcTXPnTAv3BfSUr0WVAHuSP3Xoo,92
django_extensions-3.1.0.dist-info/top_level.txt,sha256=a-Shg8eC0Rl6_AoTRvqIUhzOFzQeCFU1Z7ee7myIYMg,18
django_extensions/__init__.py,sha256=UgrVIRBD1b4giDXwgcRs3XYQEKTuc9by2RG1QFSGCnc,533
django_extensions/__pycache__/__init__.cpython-37.pyc,,
django_extensions/__pycache__/apps.cpython-37.pyc,,
django_extensions/__pycache__/collision_resolvers.cpython-37.pyc,,
django_extensions/__pycache__/compat.cpython-37.pyc,,
django_extensions/__pycache__/import_subclasses.cpython-37.pyc,,
django_extensions/__pycache__/models.cpython-37.pyc,,
django_extensions/__pycache__/settings.cpython-37.pyc,,
django_extensions/__pycache__/validators.cpython-37.pyc,,
django_extensions/admin/__init__.py,sha256=-gJP3Ttnx-bAFgZLo7zguKH2FlSFNfL99hrpj4eysxc,6853
django_extensions/admin/__pycache__/__init__.cpython-37.pyc,,
django_extensions/admin/__pycache__/filter.cpython-37.pyc,,
django_extensions/admin/__pycache__/widgets.cpython-37.pyc,,
django_extensions/admin/filter.py,sha256=1MFZ71zlx1fp5QdKxOe3GpTu2yMKWeHOPxObLAk1JjU,1819
django_extensions/admin/widgets.py,sha256=7Auq1-VIsdbLW20tpVjEB2cAfL6YqDteHEwXr0gYcKE,3191
django_extensions/apps.py,sha256=oJlK-RUVkhL9ZKtjS3vKsEJJc17UmYbQMEdS8Ocbf3s,171
django_extensions/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/auth/__pycache__/__init__.cpython-37.pyc,,
django_extensions/auth/__pycache__/mixins.cpython-37.pyc,,
django_extensions/auth/mixins.py,sha256=t55Wjt2B0tSaW10liVHj8NSJb6yyKbmcGCJv8sQP89o,488
django_extensions/collision_resolvers.py,sha256=roO-zKNAt6PEcN6FZVl4scP6ujM73ppZw48dLMLUJrQ,10644
django_extensions/compat.py,sha256=xQT_I6tUhWYRvupMj10gxo9fvkwE47iZ0L_Ee0MKQXs,1930
django_extensions/conf/app_template/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/app_template/forms.py.tmpl,sha256=_K9nXjI1BEn-aPQYmNM9mcBwp21EnzAvtHF6lXeLQmY,55
django_extensions/conf/app_template/migrations/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/app_template/models.py.tmpl,sha256=Vjc0p2XbAPgE6HyTF6vll98A4eDhA5AvaQqsc4kQ9AQ,57
django_extensions/conf/app_template/urls.py.tmpl,sha256=nzK9G5Qi-8ECvgQ-5A5UhVYB9nmKTuWxKkrqWYgSzS4,69
django_extensions/conf/app_template/views.py.tmpl,sha256=F42JXgnqFqK0fajXeutyJJxwOszRxoLMNkIhfc4Z7KI,26
django_extensions/conf/command_template/management/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/command_template/management/commands/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/command_template/management/commands/sample.py.tmpl,sha256=VWqndBmkpZ5jw_3DrisYjXD76Si5lVSVcZlkifG57gs,306
django_extensions/conf/jobs_template/jobs/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/jobs_template/jobs/daily/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/jobs_template/jobs/hourly/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/jobs_template/jobs/monthly/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/jobs_template/jobs/sample.py.tmpl,sha256=r2cd8E0jNTKIJYQmPULuxjZFxzg1yrv72IHsipWkWtY,178
django_extensions/conf/jobs_template/jobs/weekly/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/jobs_template/jobs/yearly/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/template_tags_template/templatetags/__init__.py.tmpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/conf/template_tags_template/templatetags/sample.py.tmpl,sha256=IOMcdXaX3IBAawoGoteRYqF5Y2ggxsLweR5XZqxfpMk,59
django_extensions/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/db/__pycache__/__init__.cpython-37.pyc,,
django_extensions/db/__pycache__/models.cpython-37.pyc,,
django_extensions/db/fields/__init__.py,sha256=sd1YBoBKQOQNPmzT4dbnvL6zgnMN2l9PwOzkQCGFKbg,20607
django_extensions/db/fields/__pycache__/__init__.cpython-37.pyc,,
django_extensions/db/fields/__pycache__/json.cpython-37.pyc,,
django_extensions/db/fields/json.py,sha256=WfaRzlIwxCHgppPMAI1QOlq2WfDr5rsUMlFkpy6peTY,2862
django_extensions/db/models.py,sha256=i2Aa72Driz1LSf1ed4kFZqKK18ZZd8pkCAurUPQw6bg,3811
django_extensions/import_subclasses.py,sha256=sPRpMDQDobPnefJq7M9_B0Gn7-VcXofaWi4Maee7XFE,2291
django_extensions/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/jobs/__pycache__/__init__.cpython-37.pyc,,
django_extensions/jobs/daily/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/jobs/daily/__pycache__/__init__.cpython-37.pyc,,
django_extensions/jobs/daily/__pycache__/cache_cleanup.cpython-37.pyc,,
django_extensions/jobs/daily/__pycache__/daily_cleanup.cpython-37.pyc,,
django_extensions/jobs/daily/cache_cleanup.py,sha256=KcT78D0Y3a4orSlG0eTfh1HqebRn48iYXCxUkyuiww0,646
django_extensions/jobs/daily/daily_cleanup.py,sha256=r_NSWoDPWlR2GvubWt4GZIgjx24GBeNOfOlIRpRu1wI,388
django_extensions/jobs/hourly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/jobs/hourly/__pycache__/__init__.cpython-37.pyc,,
django_extensions/jobs/minutely/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/jobs/minutely/__pycache__/__init__.cpython-37.pyc,,
django_extensions/jobs/monthly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/jobs/monthly/__pycache__/__init__.cpython-37.pyc,,
django_extensions/jobs/weekly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/jobs/weekly/__pycache__/__init__.cpython-37.pyc,,
django_extensions/jobs/yearly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/jobs/yearly/__pycache__/__init__.cpython-37.pyc,,
django_extensions/locale/da/LC_MESSAGES/django.mo,sha256=R7WNKaXc0q4iM1cUsgzdbdRZ08r7m14EmM1znFTo1FI,797
django_extensions/locale/da/LC_MESSAGES/django.po,sha256=Zl33Wn5Sz6JsDUcbR_2aMtFCTqmDYz1XpXXsrY2GBl0,1667
django_extensions/locale/de/LC_MESSAGES/django.mo,sha256=kuhHiXWrfazxsvFzvENWfY5sN3XpLvy1-AKQ0jKOnAs,1227
django_extensions/locale/de/LC_MESSAGES/django.po,sha256=OLFLDJbZLPk3oK5DUcJ-V7eeBKZcHjlu_Vl0WTHW9F4,1755
django_extensions/locale/el/LC_MESSAGES/django.mo,sha256=0CafRFBnuy4QdqtoaipoKpONaVMvtfP1J_4eMBB2gAg,1581
django_extensions/locale/el/LC_MESSAGES/django.po,sha256=UC2b1GCXVnUteg1ZFqooRp6wkcxBufQGWCSZW8Hxndw,2116
django_extensions/locale/en/LC_MESSAGES/django.mo,sha256=9JJOWscsqQUH_P7IWH5P5MEJPDJjDGzGl-Zz5-xGDFo,367
django_extensions/locale/en/LC_MESSAGES/django.po,sha256=l27VRI3peRt_aKdlaQ7zVXj03wR2PfIex2X3SWrrSBc,2229
django_extensions/locale/es/LC_MESSAGES/django.mo,sha256=SH8ojro4wqhcR8yKM2vn9JVxTMbke7zwUjsc_W60jfA,1260
django_extensions/locale/es/LC_MESSAGES/django.po,sha256=euh9NBu3f-f-CuNgPGaJDebN0TbalfKKJ_X5q55VqA8,1788
django_extensions/locale/fr/LC_MESSAGES/django.mo,sha256=XIMBOSYt8pHAhP3pUBs1N-iKLn3e0LRgTNYe_ippr58,743
django_extensions/locale/fr/LC_MESSAGES/django.po,sha256=kU4F92g2mcd5y73onqKOM5F3V1YkIUk9ezu1OrKiQi0,1930
django_extensions/locale/hu/LC_MESSAGES/django.mo,sha256=7rWzOkIurHDcvi4uCgh4hkQjUpV182FSyjKZz6mIBFU,1242
django_extensions/locale/hu/LC_MESSAGES/django.po,sha256=SOHXX186PGybAII05VA5QRZvSjtXR9fLJpgS2acxwt8,1770
django_extensions/locale/id/LC_MESSAGES/django.mo,sha256=X3tKDCM5qiuVi5dYOnzxAxx6mQ3w-wTJBvP7_ENnHhg,1508
django_extensions/locale/id/LC_MESSAGES/django.po,sha256=a4dguUsySnXLdDDafyXcq2lXFmYN-DS6uoEOQQJGEV4,2243
django_extensions/locale/it/LC_MESSAGES/django.mo,sha256=y3dS8jT30b2P9il5kxQaCj_JgaLLCCkR_vLEllX8L0g,1247
django_extensions/locale/it/LC_MESSAGES/django.po,sha256=AENMGV_gkuUqp2gVWnENI5hlCtJipNykZkAWcvlRia0,1775
django_extensions/locale/ja/LC_MESSAGES/django.mo,sha256=5fTQjN83bExfQbkaAMq3zve2B3fEWkf6rF-QYGZf9fA,1397
django_extensions/locale/ja/LC_MESSAGES/django.po,sha256=CGrMk9hH64qBE_6NF-qPMwHpdfW57FwY3PlF0g0_g0M,1925
django_extensions/locale/pl/LC_MESSAGES/django.mo,sha256=G3yZYzIwUHJ0PK14VhRXxJaYSXRkBQWa4yfFwJyhSBs,2002
django_extensions/locale/pl/LC_MESSAGES/django.po,sha256=hVRdMxQmgRhtruCm66bZQVY-OIfSSYVBSJViuZNHB_4,2788
django_extensions/locale/pt/LC_MESSAGES/django.mo,sha256=F_q92e6dFwPbjvYWHNBvCjgd5mIj3_ezrHvCOFeUZCw,1262
django_extensions/locale/pt/LC_MESSAGES/django.po,sha256=oKucDPxqIFZAOeVa_mbvOsmXXwyTydd82_Z_pXpkfvI,1790
django_extensions/locale/pt_BR/LC_MESSAGES/django.mo,sha256=bN2RG97zI3S6qEuMmvbDvPCo4YSZ_KEY5UxviD9WzlA,1310
django_extensions/locale/pt_BR/LC_MESSAGES/django.po,sha256=VDIRUodyxJr4PDcgiOuR6o3k1Ss_4ge5rx0DZgk5QwY,2082
django_extensions/locale/ro/LC_MESSAGES/django.mo,sha256=8-8B-I7iFCGZKBj1XKMbMqQLl6Yg2W1IEG39miSI8Hk,1352
django_extensions/locale/ro/LC_MESSAGES/django.po,sha256=CWaWS2C08-8lNWMCtPSPvDj4xONYrD3UGx4QSWXuWgg,1891
django_extensions/locale/ru/LC_MESSAGES/django.mo,sha256=C_kjCXvZuZ2ZdiU8ffcjKwcnA-d5IiUTgpglX7JdD-U,2009
django_extensions/locale/ru/LC_MESSAGES/django.po,sha256=luenXP4hypDODQUVWowDSCkYW9VMF_9NBlTUVkAmB3o,3820
django_extensions/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/logging/__pycache__/__init__.cpython-37.pyc,,
django_extensions/logging/__pycache__/filters.cpython-37.pyc,,
django_extensions/logging/filters.py,sha256=02Yp6Xmcp5ORr-JweyG6xHBZZsOKD0DnqbgXHVewGSI,1126
django_extensions/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/management/__pycache__/__init__.cpython-37.pyc,,
django_extensions/management/__pycache__/base.cpython-37.pyc,,
django_extensions/management/__pycache__/color.cpython-37.pyc,,
django_extensions/management/__pycache__/debug_cursor.cpython-37.pyc,,
django_extensions/management/__pycache__/email_notifications.cpython-37.pyc,,
django_extensions/management/__pycache__/jobs.cpython-37.pyc,,
django_extensions/management/__pycache__/modelviz.cpython-37.pyc,,
django_extensions/management/__pycache__/mysql.cpython-37.pyc,,
django_extensions/management/__pycache__/notebook_extension.cpython-37.pyc,,
django_extensions/management/__pycache__/shells.cpython-37.pyc,,
django_extensions/management/__pycache__/signals.cpython-37.pyc,,
django_extensions/management/__pycache__/technical_response.cpython-37.pyc,,
django_extensions/management/__pycache__/utils.cpython-37.pyc,,
django_extensions/management/base.py,sha256=onLx3r71rBL0Io91s05V9yvXg4BGxvd9o3sYaMn4CIA,1431
django_extensions/management/color.py,sha256=rQcRJBfXdsV4LlM15dONb_n_rzRL2qXH1c1-WljiNcM,907
django_extensions/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/management/commands/__pycache__/__init__.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/admin_generator.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/clean_pyc.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/clear_cache.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/compile_pyc.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/create_command.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/create_jobs.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/create_template_tags.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/delete_squashed_migrations.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/describe_form.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/drop_test_database.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/dumpscript.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/export_emails.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/find_template.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/generate_password.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/generate_secret_key.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/graph_models.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/list_model_info.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/list_signals.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/mail_debug.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/merge_model_instances.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/notes.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/pipchecker.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/print_settings.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/print_user_for_session.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/reset_db.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/reset_schema.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/runjob.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/runjobs.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/runprofileserver.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/runscript.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/runserver_plus.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/set_default_site.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/set_fake_emails.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/set_fake_passwords.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/shell_plus.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/show_template_tags.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/show_urls.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/sqlcreate.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/sqldiff.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/sqldsn.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/sync_s3.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/syncdata.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/unreferenced_files.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/update_permissions.cpython-37.pyc,,
django_extensions/management/commands/__pycache__/validate_templates.cpython-37.pyc,,
django_extensions/management/commands/admin_generator.py,sha256=TAGUX36o-wxVmfXOzDhSuSqJcByjkNNR7BudhbKUQlk,11791
django_extensions/management/commands/clean_pyc.py,sha256=dArLJ7HXcJHoaXdfMAzNpQgcpMPGVQzAuDWLBDEChgU,1523
django_extensions/management/commands/clear_cache.py,sha256=y44-TSpULDtIwhpCsV7Ii2ofsYjNIgHrEPUixoDepsU,1486
django_extensions/management/commands/compile_pyc.py,sha256=YrXmZO2MNFkNfcCb4CAnppRR4_Ggkv_r76raA77xVxE,1241
django_extensions/management/commands/create_command.py,sha256=L9h1R2NlVK0C74dPXymaI7wmkWwh9piNEDKiUIEZPKk,3748
django_extensions/management/commands/create_jobs.py,sha256=d6-wAaKtes7A3GkJwxVso89PBuYnuiiT-XZyZcOU8YQ,2425
django_extensions/management/commands/create_template_tags.py,sha256=qQ32iY08O8yYjcXwyS2MQZGKbwr1lPL20itakud66K4,2823
django_extensions/management/commands/delete_squashed_migrations.py,sha256=_Ktv14Yw-w0YvmitUR-1TqZEJjP3uMEt-rDf8pVvV0A,7241
django_extensions/management/commands/describe_form.py,sha256=LSgGaFjL2mGs5aWoqQefaPXAvhmHoFGTLK5OX9kmpss,2737
django_extensions/management/commands/drop_test_database.py,sha256=SdsUMoJs-qlcy6umERHQ3B6p7eO4UDPYo6XTA4RAScI,5805
django_extensions/management/commands/dumpscript.py,sha256=yBec7XSgpkBHMX4Nas6usYHlXTtM5_wdzYYQGtbkJJQ,27651
django_extensions/management/commands/export_emails.py,sha256=AzR__ZLuVMBR0ZHtLIKI9FCwrjU9QBa5sJA3az-0uSk,5565
django_extensions/management/commands/find_template.py,sha256=k9Nj_Ll_LdL8dWz-n3eZV7XeYO8h-hRxCIb6ZkiQu-4,695
django_extensions/management/commands/generate_password.py,sha256=9IYh3FUVGucb2xJOPn4hZutkupPXVkZhwRXop0e_FT4,938
django_extensions/management/commands/generate_secret_key.py,sha256=83xqSJ7FQQJ04Psl5BnYj4RwG0cUUeqnvMKopk8QXo0,451
django_extensions/management/commands/graph_models.py,sha256=k9vpQZxxkCwUDRe5_UOkq-ATdWBdWyAIjFuetOUojmo,13180
django_extensions/management/commands/list_model_info.py,sha256=cfDVmVGNAUDLvgC0rSjRHhK4SX2ALofw6yhHXwVYr-A,6038
django_extensions/management/commands/list_signals.py,sha256=LIWtwMeJz8Pg1-JPSv9NNi4tsQc0xLr64bWlt7TazwE,2602
django_extensions/management/commands/mail_debug.py,sha256=9FeOfB5opR1IXbkHqPx6JriQq3qWbSzzofX-D-WVeX8,2894
django_extensions/management/commands/merge_model_instances.py,sha256=DeoGYz6OnVgprhx3O1gfB9egZ6HYqKk0jJSnFst616w,9552
django_extensions/management/commands/notes.py,sha256=3sEUcMYk2sNFlbVomXHBJajoQdpRFKlm2IC6AInXhx0,2716
django_extensions/management/commands/pipchecker.py,sha256=V5p9S9u0FN68buQCOeGr3g6zW-94ki3tVfzetW0bvko,14292
django_extensions/management/commands/print_settings.py,sha256=pEiCq41QZuoVg4_XtmXabrQquTBJX0TRGeLm1V8N3SM,2640
django_extensions/management/commands/print_user_for_session.py,sha256=r1Ot7yBsxOwYv8trFuKQVwBXTIUl3m-wyc-Hx_HZ1lA,2144
django_extensions/management/commands/reset_db.py,sha256=tSXzyMEiAJA6vU_o8wpMOINnjPcLZlAtd70G81dLdMw,7734
django_extensions/management/commands/reset_schema.py,sha256=aumuxdXbJanxllbulRBbl-OLNvRsxvWLraTUmHJ_a1g,2845
django_extensions/management/commands/runjob.py,sha256=OMeFDVJgYlTc7NO8aWS-2QgE3pPIwtd8tGrelviGVhE,1987
django_extensions/management/commands/runjobs.py,sha256=k3Um1dlGPuWIs7P9MPxNDNcCNq3pAdH7cV4xmmcJMRQ,3384
django_extensions/management/commands/runprofileserver.py,sha256=XBfJqovLmWnXUhdgprBbM8-vgOTm7dM2tZo3Z6OiTFk,11625
django_extensions/management/commands/runscript.py,sha256=-0nR_Kqs10V3ToB6w4YCTO4igKmmkBhNya__sXpNXlc,12005
django_extensions/management/commands/runserver_plus.py,sha256=wxZQVWMa0gbbEkG33iUk4PeJQAJSUF_yoHOXEM7GiLQ,21850
django_extensions/management/commands/set_default_site.py,sha256=LmNNKP84iryahh7cMAVwPlRcJ7EpFsoWTKUpjSxCezQ,2800
django_extensions/management/commands/set_fake_emails.py,sha256=fZtLNjEFHVre2XZOcbAHRM-C6_o-Zb7_FuQd9vPNLCs,3841
django_extensions/management/commands/set_fake_passwords.py,sha256=T3TlDt-z0VYAyoq0js7cWLqWqRy2_RZsRvq5t-l1e6Q,1731
django_extensions/management/commands/shell_plus.py,sha256=Q4itLhgf-GmbBMGndNRpVPi8uH9Mrdv7yAYNLrWo1Wc,21659
django_extensions/management/commands/show_template_tags.py,sha256=NAiUI80ak_4-szlphl-13RRVv__9MdyO52ELFqDnVvk,3909
django_extensions/management/commands/show_urls.py,sha256=uz5WNQcykAcmeOf70DDCi-AAUvMkLcmcT1BQ9oAtmi4,9135
django_extensions/management/commands/sqlcreate.py,sha256=iZ1nsCePzIbPlJKircrAJw_lFNTpAr8pkYwfC9QvqP8,4230
django_extensions/management/commands/sqldiff.py,sha256=B04cQQT-byyU7J9vtzKzV32GJdvrLlSFzAZRQFN6SSM,63193
django_extensions/management/commands/sqldsn.py,sha256=DB8W2v3D7wcXeGfCKSaAWyPLFnTYpd5aNW63fWt4dJw,5268
django_extensions/management/commands/sync_s3.py,sha256=mpz4BjbWJIgSpGKnGbovwzudr0agsErx19aBZfJ1iuY,15720
django_extensions/management/commands/syncdata.py,sha256=h7QKa0A2HSoTbWpS5U920B02l-Ou-bPr9d-a417ZPFI,9771
django_extensions/management/commands/unreferenced_files.py,sha256=SMQG4SXhSEkjxSuUteaXVTyJ4StmC9A9mZwYOQBzaco,1787
django_extensions/management/commands/update_permissions.py,sha256=0KDqKHO5ynSNYtyWkWC9K2uinuSsiAU-hJTy7XO3rnU,3033
django_extensions/management/commands/validate_templates.py,sha256=GrkhQJQBlGuNI634BLfBToSCirl3b4rh1EzL3OlNyg4,3627
django_extensions/management/debug_cursor.py,sha256=8f-JS1rt3O-EksKs5hIPB27xlAHQSmaj5icWCeOWqzw,4391
django_extensions/management/email_notifications.py,sha256=hHPG_1mzJDYf5jchevEOC-rAzhJGM5EOkgYmaRFpk_M,5360
django_extensions/management/jobs.py,sha256=nPYJH2n2jrjt38TMxBuftvMSHFpgn2hZSa_2XW4mw90,5043
django_extensions/management/modelviz.py,sha256=kOmEJ8m0EJGcq47hhdsBel6dHaCzIIUAYD-28pY0-go,17254
django_extensions/management/mysql.py,sha256=xUBDaNhnoGbOPjRtq5zkd5Z8NtmJLdS8MTlHVPigeHQ,1506
django_extensions/management/notebook_extension.py,sha256=h5-bWrDK8RkoblyiprJZjFRRqbin3Vj8W6PmBWI2KpM,324
django_extensions/management/shells.py,sha256=2eTZ6s9bSHAtR7u6-IroDuUQAcBGNYxBEhJAPCsxN_8,15410
django_extensions/management/signals.py,sha256=yWTcyz8hhcB-PLJKeH2UWOAypCIvaeijKy3CfNJ3ZhU,307
django_extensions/management/technical_response.py,sha256=FbMGGbFMHpwjc6SEQ3vZ0lNmIGL5TnCQzAeDzJzVqBQ,1758
django_extensions/management/utils.py,sha256=vEWTbV3PrUJwh4r5VK8WGkICTZlAx6uXqo2wypDFAVY,2259
django_extensions/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/mongodb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/mongodb/__pycache__/__init__.cpython-37.pyc,,
django_extensions/mongodb/__pycache__/models.cpython-37.pyc,,
django_extensions/mongodb/fields/__init__.py,sha256=a9HmyN0YjPG3MN9kM_m79l0fwVaIKWNXa6h3E2PdnvM,9341
django_extensions/mongodb/fields/__pycache__/__init__.cpython-37.pyc,,
django_extensions/mongodb/fields/__pycache__/json.cpython-37.pyc,,
django_extensions/mongodb/fields/json.py,sha256=ep3CuSkBE5LyixMbmFo2u_jK2D4J9aziIlCra5Fb-w8,2158
django_extensions/mongodb/models.py,sha256=BVvXqlgVEfWNUy19ykvlwD0qXv0B3gGcIiPi7RBcJjc,2405
django_extensions/settings.py,sha256=CdN-y7loiLzEyIicwj1OQPViTFZZQdXHNTnKxMipzg8,1079
django_extensions/static/django_extensions/css/jquery.autocomplete.css,sha256=3yUz9XJFKdXHv34Xe4QNWjA9ghEr2ieEoQ0KaO3e49Q,740
django_extensions/static/django_extensions/img/indicator.gif,sha256=0-OUTUZJRQ3uZqVcae7O0tgltsoaNJ9yx1_TeArj8AY,1553
django_extensions/static/django_extensions/js/jquery.ajaxQueue.js,sha256=IVCgQ2MMHxrmrHMc4Pu0TxdEaVhuQSofxotZgEffUdk,2911
django_extensions/static/django_extensions/js/jquery.autocomplete.js,sha256=5DV9zxN6TgVpbkscqlkoiK5qhEEGdmxV2v7d265QQog,36679
django_extensions/static/django_extensions/js/jquery.bgiframe.js,sha256=JLLyZyn1DRAFry-ikBRSrf0qfX6PsqTFkwnPu9jj68k,1820
django_extensions/templates/django_extensions/graph_models/django2018/digraph.dot,sha256=dqhYYv2LnG31IFxqooP5zplpABcQKxgSkLDdX1rL6EI,818
django_extensions/templates/django_extensions/graph_models/django2018/label.dot,sha256=vsKxchMm6DQVTPx8gFxijpHOGNJuqdItN2WEI8mvc14,1875
django_extensions/templates/django_extensions/graph_models/django2018/relation.dot,sha256=6KlECRFCmCmTTOQs5vYEr2sPWdDgiUbgH4ZkWLt_SjE,589
django_extensions/templates/django_extensions/graph_models/original/digraph.dot,sha256=D2Kh5rWOJcIFeXChDHm7hotL0sTqgnGQpghWDHkUyZM,823
django_extensions/templates/django_extensions/graph_models/original/label.dot,sha256=0-UHhFDl-XTkOr1wUAoEBd-xSfnAea922vUX0N1cCeQ,1697
django_extensions/templates/django_extensions/graph_models/original/relation.dot,sha256=Y-wvocs_14QreSILBv9ESWvnF6B3pUcrRrjx_q0oINk,591
django_extensions/templates/django_extensions/widgets/foreignkey_searchinput.html,sha256=8DhLt6B0oUlpVq1gSoPy4uImyJxUueUczwYHraZeKNg,2032
django_extensions/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
django_extensions/templatetags/__pycache__/__init__.cpython-37.pyc,,
django_extensions/templatetags/__pycache__/debugger_tags.cpython-37.pyc,,
django_extensions/templatetags/__pycache__/highlighting.cpython-37.pyc,,
django_extensions/templatetags/__pycache__/indent_text.cpython-37.pyc,,
django_extensions/templatetags/__pycache__/syntax_color.cpython-37.pyc,,
django_extensions/templatetags/__pycache__/widont.cpython-37.pyc,,
django_extensions/templatetags/debugger_tags.py,sha256=M6RUSObtGln_LQXDeu8m396auIOAsxdnJQa3AeV5T1I,596
django_extensions/templatetags/highlighting.py,sha256=v94urI9kE6-Z-2Cm0F5glgY-crh89fp0jdKsFNl_FOk,3224
django_extensions/templatetags/indent_text.py,sha256=ByaKtl7VaPBx_4PB3V-Bg9foY1zvraZ2VNHBh5gBdek,1751
django_extensions/templatetags/syntax_color.py,sha256=X6aMvDIxHHBt_AFaR4qXHAmafpPsitZshUN4_FiJ1Pc,3171
django_extensions/templatetags/widont.py,sha256=6uTu7oGT98rPy1TaTRUOE3A6LkLell_XyVIWPmt_uZo,1925
django_extensions/utils/__init__.py,sha256=Xb0RrRwc1dqCwkASV8I2MSLy14c_FhmE1HeaxxaeO1E,70
django_extensions/utils/__pycache__/__init__.cpython-37.pyc,,
django_extensions/utils/__pycache__/deprecation.cpython-37.pyc,,
django_extensions/utils/__pycache__/dia2django.cpython-37.pyc,,
django_extensions/utils/__pycache__/internal_ips.cpython-37.pyc,,
django_extensions/utils/deprecation.py,sha256=XfN9X_w6PGMvQ5JldtdYZyqSNvO5w9TTaST8nZvQl2U,155
django_extensions/utils/dia2django.py,sha256=YWerQ-Fh5qgH5C72riN3jrqT64BEF3u0L0H2dbUMgx0,10177
django_extensions/utils/internal_ips.py,sha256=O8XzFk_In7xSaSAtTjKMorSyib7GxiPTVeAapad80QM,1952
django_extensions/validators.py,sha256=mTPGQ5xVqo8ei4Zmuz8uusaI-sjVa2qLrPZpG_iB__g,3754

View File

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.35.1)
Root-Is-Purelib: true
Tag: py3-none-any

View File

@ -0,0 +1 @@
django_extensions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
VERSION = (3, 1, 0)
def get_version(version):
"""Dynamically calculate the version based on VERSION tuple."""
if len(version) > 2 and version[2] is not None:
if isinstance(version[2], int):
str_version = "%s.%s.%s" % version[:3]
else:
str_version = "%s.%s_%s" % version[:3]
else:
str_version = "%s.%s" % version[:2]
return str_version
__version__ = get_version(VERSION)
default_app_config = 'django_extensions.apps.DjangoExtensionsConfig'

View File

@ -0,0 +1,165 @@
# -*- 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, **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, **kwargs)
class ForeignKeyAutocompleteAdmin(ForeignKeyAutocompleteAdminMixin, admin.ModelAdmin):
pass
class ForeignKeyAutocompleteTabularInline(ForeignKeyAutocompleteAdminMixin, admin.TabularInline):
pass
class ForeignKeyAutocompleteStackedInline(ForeignKeyAutocompleteAdminMixin, admin.StackedInline):
pass

View File

@ -0,0 +1,53 @@
# -*- 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')),
)

View File

@ -0,0 +1,90 @@
# -*- 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 <select> box.
"""
# Set in subclass to render the widget with a different template
widget_template = None
# Set this to the patch of the search view
search_path = None
def _media(self):
js_files = [
static('django_extensions/js/jquery.bgiframe.js'),
static('django_extensions/js/jquery.ajaxQueue.js'),
static('django_extensions/js/jquery.autocomplete.js'),
]
return forms.Media(
css={'all': (static('django_extensions/css/jquery.autocomplete.css'), )},
js=js_files,
)
media = property(_media)
def label_for_value(self, value):
key = self.rel.get_related_field().name
obj = self.rel.model._default_manager.get(**{key: value})
return Truncator(obj).words(14, truncate='...')
def __init__(self, rel, search_fields, attrs=None):
self.search_fields = search_fields
super().__init__(rel, site, attrs)
def render(self, name, value, attrs=None, renderer=None):
if attrs is None:
attrs = {}
opts = self.rel.model._meta
app_label = opts.app_label
model_name = opts.object_name.lower()
related_url = reverse('admin:%s_%s_changelist' % (app_label, model_name))
if not self.search_path:
self.search_path = urllib.parse.urljoin(related_url, 'foreignkey_autocomplete/')
params = self.url_parameters()
if params:
url = '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in params.items()])
else:
url = ''
if 'class' not in attrs:
attrs['class'] = 'vForeignKeyRawIdAdminField'
# Call the TextInput render method directly to have more control
output = [forms.TextInput.render(self, name, value, attrs)]
if value:
label = self.label_for_value(value)
else:
label = ''
context = {
'url': url,
'related_url': related_url,
'search_path': self.search_path,
'search_fields': ','.join(self.search_fields),
'app_label': app_label,
'model_name': model_name,
'label': label,
'name': name,
}
output.append(render_to_string(self.widget_template or (
'django_extensions/widgets/%s/%s/foreignkey_searchinput.html' % (app_label, model_name),
'django_extensions/widgets/%s/foreignkey_searchinput.html' % app_label,
'django_extensions/widgets/foreignkey_searchinput.html',
), context))
output.reverse()
return mark_safe(''.join(output))

View File

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from django.apps import AppConfig
class DjangoExtensionsConfig(AppConfig):
name = 'django_extensions'
verbose_name = "Django Extensions"

View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.mixins import UserPassesTestMixin
class ModelUserFieldPermissionMixin(UserPassesTestMixin):
model_permission_user_field = 'user'
def get_model_permission_user_field(self):
return self.model_permission_user_field
def test_func(self):
model_attr = self.get_model_permission_user_field()
current_user = self.request.user
return current_user == getattr(self.get_queryset().first(), model_attr)

View File

@ -0,0 +1,265 @@
# -*- coding: utf-8 -*-
import inspect
import sys
from abc import abstractmethod, ABCMeta
from typing import ( # NOQA
Dict,
List,
Optional,
Tuple,
)
from django.utils.module_loading import import_string
class BaseCR(metaclass=ABCMeta):
"""
Abstract base collision resolver. All collision resolvers needs to inherit from this class.
To write custom collision resolver you need to overwrite 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.
"""
@classmethod
def get_app_name_and_model(cls, full_model_path): # type: (str) -> Tuple[str, str]
model_class = import_string(full_model_path)
return model_class._meta.app_config.name, model_class.__name__
@abstractmethod
def resolve_collisions(self, namespace): # type: (Dict[str, List[str]]) -> Dict[str, str]
pass
class LegacyCR(BaseCR):
""" Default collision resolver. Model from last application in alphabetical order is selected. """
def resolve_collisions(self, namespace):
result = {}
for name, models in namespace.items():
result[name] = models[-1]
return result
class AppsOrderCR(LegacyCR, metaclass=ABCMeta):
APP_PRIORITIES = None # type: List[str]
def resolve_collisions(self, namespace):
assert self.APP_PRIORITIES is not None, "You must define APP_PRIORITIES in your resolver class!"
result = {}
for name, models in namespace.items():
if len(models) > 0:
sorted_models = self._sort_models_depending_on_priorities(models)
result[name] = sorted_models[0][1]
return result
def _sort_models_depending_on_priorities(self, models): # type: (List[str]) -> List[Tuple[int, str]]
models_with_priorities = []
for model in models:
try:
app_name, _ = self.get_app_name_and_model(model)
position = self.APP_PRIORITIES.index(app_name)
except (ImportError, ValueError):
position = sys.maxsize
models_with_priorities.append((position, model))
return sorted(models_with_priorities)
class InstalledAppsOrderCR(AppsOrderCR):
"""
Collision resolver which selects first model from INSTALLED_APPS.
You can set your own app priorities list by subclassing him and overwriting APP_PRIORITIES field.
This collision resolver will select model from first app on this list.
If both app's are absent on this list, resolver will choose model from first app in alphabetical order.
"""
@property
def APP_PRIORITIES(self):
from django.conf import settings
return getattr(settings, 'INSTALLED_APPS', [])
class PathBasedCR(LegacyCR, metaclass=ABCMeta):
"""
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 full model name.
It should return valid alias as str instance.
"""
@abstractmethod
def transform_import(self, module_path): # type: (str) -> str
pass
def resolve_collisions(self, namespace):
base_imports = super(PathBasedCR, self).resolve_collisions(namespace)
for name, models in namespace.items():
if len(models) <= 1:
continue
for model in models:
new_name = self.transform_import(model)
assert isinstance(new_name, str), "result of transform_import must be str!"
base_imports[new_name] = model
return base_imports
class FullPathCR(PathBasedCR):
"""
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.
"""
def transform_import(self, module_path):
module, model = module_path.rsplit('.models', 1)
module_path = module + model
return module_path.replace('.', '_')
class AppNameCR(PathBasedCR, metaclass=ABCMeta):
"""
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.
"""
MODIFICATION_STRING = None # type: Optional[str]
def transform_import(self, module_path):
assert self.MODIFICATION_STRING is not None, "You must define MODIFICATION_STRING in your resolver class!"
app_name, model_name = self.get_app_name_and_model(module_path)
app_name = app_name.replace('.', '_')
return self.MODIFICATION_STRING.format(app_name=app_name, model_name=model_name)
class AppNamePrefixCR(AppNameCR):
"""
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.
"""
MODIFICATION_STRING = "{app_name}_{model_name}"
class AppNameSuffixCR(AppNameCR):
"""
Collision resolver which transform pair (app name, model_name) to alias "{model_name}_{app_name}"
Model from last application in alphabetical order is selected.
"""
MODIFICATION_STRING = "{model_name}_{app_name}"
class AppNamePrefixCustomOrderCR(AppNamePrefixCR, InstalledAppsOrderCR):
"""
Collision resolver which is mixin of AppNamePrefixCR and InstalledAppsOrderCR.
In case of collisions he sets aliases like AppNamePrefixCR, but sets default model using InstalledAppsOrderCR.
"""
pass
class AppNameSuffixCustomOrderCR(AppNameSuffixCR, InstalledAppsOrderCR):
"""
Collision resolver which is mixin of AppNameSuffixCR and InstalledAppsOrderCR.
In case of collisions he sets aliases like AppNameSuffixCR, but sets default model using InstalledAppsOrderCR.
"""
pass
class FullPathCustomOrderCR(FullPathCR, InstalledAppsOrderCR):
"""
Collision resolver which is mixin of FullPathCR and InstalledAppsOrderCR.
In case of collisions he sets aliases like FullPathCR, but sets default model using InstalledAppsOrderCR.
"""
pass
class AppLabelCR(PathBasedCR, metaclass=ABCMeta):
"""
Abstract collision resolver which transform pair (app_label, model_name) to alias.
You must define MODIFICATION_STRING which should be string to format with two keyword arguments:
app_label and model_name. For example: "{app_label}_{model_name}".
This is different from AppNameCR when the app is nested with several level of namespace:
Gives sites_Site instead of django_contrib_sites_Site
Model from last application in alphabetical order is selected.
"""
MODIFICATION_STRING = None # type: Optional[str]
def transform_import(self, module_path):
assert self.MODIFICATION_STRING is not None, "You must define MODIFICATION_STRING in your resolver class!"
model_class = import_string(module_path)
app_label, model_name = model_class._meta.app_label, model_class.__name__
return self.MODIFICATION_STRING.format(app_label=app_label, model_name=model_name)
class AppLabelPrefixCR(AppLabelCR):
"""
Collision resolver which transform pair (app_label, model_name) to alias "{app_label}_{model_name}".
Model from last application in alphabetical order is selected.
"""
MODIFICATION_STRING = "{app_label}_{model_name}"
class AppLabelSuffixCR(AppLabelCR):
"""
Collision resolver which transform pair (app_label, model_name) to alias "{model_name}_{app_label}".
Model from last application in alphabetical order is selected.
"""
MODIFICATION_STRING = "{model_name}_{app_label}"
class CollisionResolvingRunner:
def __init__(self):
pass
def run_collision_resolver(self, models_to_import):
# type: (Dict[str, List[str]]) -> Dict[str, List[Tuple[str, str]]]
dictionary_of_names = self._get_dictionary_of_names(models_to_import) # type: Dict[str, str]
return self._get_dictionary_of_modules(dictionary_of_names)
@classmethod
def _get_dictionary_of_names(cls, models_to_import): # type: (Dict[str, List[str]]) -> (Dict[str, str])
from django.conf import settings
collision_resolver_class = import_string(getattr(
settings, 'SHELL_PLUS_MODEL_IMPORTS_RESOLVER',
'django_extensions.collision_resolvers.LegacyCR'
))
cls._assert_is_collision_resolver_class_correct(collision_resolver_class)
result = collision_resolver_class().resolve_collisions(models_to_import)
cls._assert_is_collision_resolver_result_correct(result)
return result
@classmethod
def _assert_is_collision_resolver_result_correct(cls, result):
assert isinstance(result, dict), "Result of resolve_collisions function must be a dict!"
for key, value in result.items():
assert isinstance(key, str), "key in collision resolver result should be str not %s" % key
assert isinstance(value, str), "value in collision resolver result should be str not %s" % value
@classmethod
def _assert_is_collision_resolver_class_correct(cls, collision_resolver_class):
assert inspect.isclass(collision_resolver_class) and issubclass(
collision_resolver_class, BaseCR), "SHELL_PLUS_MODEL_IMPORTS_RESOLVER " \
"must be subclass of BaseCR!"
assert len(inspect.getfullargspec(collision_resolver_class.resolve_collisions).args) == 2, \
"resolve_collisions function must take one argument!"
@classmethod
def _get_dictionary_of_modules(cls, dictionary_of_names):
# type: (Dict[str, str]) -> Dict[str, List[Tuple[str, str]]]
dictionary_of_modules = {} # type: Dict[str, List[Tuple[str, str]]]
for alias, model in dictionary_of_names.items():
module_path, model_name = model.rsplit('.', 1)
dictionary_of_modules.setdefault(module_path, [])
dictionary_of_modules[module_path].append((model_name, alias))
return dictionary_of_modules

View File

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
from io import BytesIO
import csv
import codecs
import importlib
from django.conf import settings
#
# Django compatibility
#
def load_tag_library(libname):
"""
Load a templatetag library on multiple Django versions.
Returns None if the library isn't loaded.
"""
from django.template.backends.django import get_installed_libraries
from django.template.library import InvalidTemplateLibrary
try:
lib = get_installed_libraries()[libname]
lib = importlib.import_module(lib).register
return lib
except (InvalidTemplateLibrary, KeyError):
return None
def get_template_setting(template_key, default=None):
""" Read template settings """
templates_var = getattr(settings, 'TEMPLATES', None)
if templates_var:
for tdict in templates_var:
if template_key in tdict:
return tdict[template_key]
return default
class UnicodeWriter:
"""
CSV writer which will write rows to CSV file "f",
which is encoded in the given encoding.
We are using this custom UnicodeWriter for python versions 2.x
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
self.queue = BytesIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
self.writer.writerow([s.encode("utf-8") for s in row])
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
data = data.decode("utf-8")
# ... and reencode it into the target encoding
data = self.encoder.encode(data)
# write to the target stream
self.stream.write(data)
# empty queue
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)

View File

@ -0,0 +1,3 @@
from django import forms
# place form definition here

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,3 @@
from django.urls import include, path
# place app url patterns here

View File

@ -0,0 +1 @@
# Create your views here.

View File

@ -0,0 +1,11 @@
from django.core.management.base import {{ base_command }}
class Command({{ base_command }}):
help = "My shiny new management command."
def add_arguments(self, parser):
parser.add_argument('sample', nargs='+')
def handle(self, *args, **options):
raise NotImplementedError()

View File

@ -0,0 +1,9 @@
from django_extensions.management.jobs import BaseJob
class Job(BaseJob):
help = "My sample job."
def execute(self):
# executing empty sample job
pass

View File

@ -0,0 +1,3 @@
from django import template
register = template.Library()

View File

@ -0,0 +1,593 @@
# -*- coding: utf-8 -*-
"""
Django Extensions additional model fields
Some fields might require additional dependencies to be installed.
"""
import re
import string
try:
import uuid
HAS_UUID = True
except ImportError:
HAS_UUID = False
try:
import shortuuid
HAS_SHORT_UUID = True
except ImportError:
HAS_SHORT_UUID = False
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db.models import DateTimeField, CharField, SlugField, Q, UniqueConstraint
from django.db.models.constants import LOOKUP_SEP
from django.template.defaultfilters import slugify
from django.utils.crypto import get_random_string
from django.utils.encoding import force_str
MAX_UNIQUE_QUERY_ATTEMPTS = getattr(settings, 'EXTENSIONS_MAX_UNIQUE_QUERY_ATTEMPTS', 100)
class UniqueFieldMixin:
def check_is_bool(self, attrname):
if not isinstance(getattr(self, attrname), bool):
raise ValueError("'{}' argument must be True or False".format(attrname))
@staticmethod
def _get_fields(model_cls):
return [
(f, f.model if f.model != model_cls else None) for f in model_cls._meta.get_fields()
if not f.is_relation or f.one_to_one or (f.many_to_one and f.related_model)
]
def get_queryset(self, model_cls, slug_field):
for field, model in self._get_fields(model_cls):
if model and field == slug_field:
return model._default_manager.all()
return model_cls._default_manager.all()
def find_unique(self, model_instance, field, iterator, *args):
# exclude the current model instance from the queryset used in finding
# next valid hash
queryset = self.get_queryset(model_instance.__class__, field)
if model_instance.pk:
queryset = queryset.exclude(pk=model_instance.pk)
# form a kwarg dict used to implement any unique_together constraints
kwargs = {}
for params in model_instance._meta.unique_together:
if self.attname in params:
for param in params:
kwargs[param] = getattr(model_instance, param, None)
# for support django 2.2+
query = Q()
constraints = getattr(model_instance._meta, 'constraints', None)
if constraints:
unique_constraints = filter(
lambda c: isinstance(c, UniqueConstraint), constraints
)
for unique_constraint in unique_constraints:
if self.attname in unique_constraint.fields:
condition = {
field: getattr(model_instance, field, None)
for field in unique_constraint.fields
if field != self.attname
}
query &= Q(**condition)
new = next(iterator)
kwargs[self.attname] = new
while not new or queryset.filter(query, **kwargs):
new = next(iterator)
kwargs[self.attname] = new
setattr(model_instance, self.attname, new)
return new
class AutoSlugField(UniqueFieldMixin, SlugField):
"""
AutoSlugField
By default, sets editable=False, blank=True.
Required arguments:
populate_from
Specifies which field, list of fields, or model method
the slug will be populated from.
populate_from can traverse a ForeignKey relationship
by using Django ORM syntax:
populate_from = 'related_model__field'
Optional arguments:
separator
Defines the used separator (default: '-')
overwrite
If set to True, overwrites the slug on every save (default: False)
slugify_function
Defines the function which will be used to "slugify" a content
(default: :py:func:`~django.template.defaultfilters.slugify` )
It is possible to provide custom "slugify" function with
the ``slugify_function`` function in a model class.
``slugify_function`` function in a model class takes priority over
``slugify_function`` given as an argument to :py:class:`~AutoSlugField`.
Example
.. code-block:: python
# models.py
from django.db import models
from django_extensions.db.fields import AutoSlugField
class MyModel(models.Model):
def slugify_function(self, content):
return content.replace('_', '-').lower()
title = models.CharField(max_length=42)
slug = AutoSlugField(populate_from='title')
Inspired by SmileyChris' Unique Slugify snippet:
http://www.djangosnippets.org/snippets/690/
"""
def __init__(self, *args, **kwargs):
kwargs.setdefault('blank', True)
kwargs.setdefault('editable', False)
populate_from = kwargs.pop('populate_from', None)
if populate_from is None:
raise ValueError("missing 'populate_from' argument")
else:
self._populate_from = populate_from
if not callable(populate_from):
if not isinstance(populate_from, (list, tuple)):
populate_from = (populate_from, )
if not all(isinstance(e, str) for e in populate_from):
raise TypeError("'populate_from' must be str or list[str] or tuple[str], found `%s`" % populate_from)
self.slugify_function = kwargs.pop('slugify_function', slugify)
self.separator = kwargs.pop('separator', '-')
self.overwrite = kwargs.pop('overwrite', False)
self.check_is_bool('overwrite')
self.overwrite_on_add = kwargs.pop('overwrite_on_add', True)
self.check_is_bool('overwrite_on_add')
self.allow_duplicates = kwargs.pop('allow_duplicates', False)
self.check_is_bool('allow_duplicates')
self.max_unique_query_attempts = kwargs.pop('max_unique_query_attempts', MAX_UNIQUE_QUERY_ATTEMPTS)
super().__init__(*args, **kwargs)
def _slug_strip(self, value):
"""
Clean up a slug by removing slug separator characters that occur at
the beginning or end of a slug.
If an alternate separator is used, it will also replace any instances
of the default '-' separator with the new separator.
"""
re_sep = '(?:-|%s)' % re.escape(self.separator)
value = re.sub('%s+' % re_sep, self.separator, value)
return re.sub(r'^%s+|%s+$' % (re_sep, re_sep), '', value)
@staticmethod
def slugify_func(content, slugify_function):
if content:
return slugify_function(content)
return ''
def slug_generator(self, original_slug, start):
yield original_slug
for i in range(start, self.max_unique_query_attempts):
slug = original_slug
end = '%s%s' % (self.separator, i)
end_len = len(end)
if self.slug_len and len(slug) + end_len > self.slug_len:
slug = slug[:self.slug_len - end_len]
slug = self._slug_strip(slug)
slug = '%s%s' % (slug, end)
yield slug
raise RuntimeError('max slug attempts for %s exceeded (%s)' % (original_slug, self.max_unique_query_attempts))
def create_slug(self, model_instance, add):
slug = getattr(model_instance, self.attname)
use_existing_slug = False
if slug and not self.overwrite:
# Existing slug and not configured to overwrite - Short-circuit
# here to prevent slug generation when not required.
use_existing_slug = True
if self.overwrite_on_add and add:
use_existing_slug = False
if use_existing_slug:
return slug
# get fields to populate from and slug field to set
populate_from = self._populate_from
if not isinstance(populate_from, (list, tuple)):
populate_from = (populate_from, )
slug_field = model_instance._meta.get_field(self.attname)
slugify_function = getattr(model_instance, 'slugify_function', self.slugify_function)
# slugify the original field content and set next step to 2
slug_for_field = lambda lookup_value: self.slugify_func(
self.get_slug_fields(model_instance, lookup_value),
slugify_function=slugify_function
)
slug = self.separator.join(map(slug_for_field, populate_from))
start = 2
# strip slug depending on max_length attribute of the slug field
# and clean-up
self.slug_len = slug_field.max_length
if self.slug_len:
slug = slug[:self.slug_len]
slug = self._slug_strip(slug)
original_slug = slug
if self.allow_duplicates:
setattr(model_instance, self.attname, slug)
return slug
return self.find_unique(
model_instance, slug_field, self.slug_generator(original_slug, start))
def get_slug_fields(self, model_instance, lookup_value):
if callable(lookup_value):
# A function has been provided
return "%s" % lookup_value(model_instance)
lookup_value_path = lookup_value.split(LOOKUP_SEP)
attr = model_instance
for elem in lookup_value_path:
try:
attr = getattr(attr, elem)
except AttributeError:
raise AttributeError(
"value {} in AutoSlugField's 'populate_from' argument {} returned an error - {} has no attribute {}".format(
elem, lookup_value, attr, elem))
if callable(attr):
return "%s" % attr()
return attr
def pre_save(self, model_instance, add):
value = force_str(self.create_slug(model_instance, add))
return value
def get_internal_type(self):
return "SlugField"
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
kwargs['populate_from'] = self._populate_from
if not self.separator == '-':
kwargs['separator'] = self.separator
if self.overwrite is not False:
kwargs['overwrite'] = True
if self.allow_duplicates is not False:
kwargs['allow_duplicates'] = True
return name, path, args, kwargs
class RandomCharField(UniqueFieldMixin, CharField):
"""
RandomCharField
By default, sets editable=False, blank=True, unique=False.
Required arguments:
length
Specifies the length of the field
Optional arguments:
unique
If set to True, duplicate entries are not allowed (default: False)
lowercase
If set to True, lowercase the alpha characters (default: False)
uppercase
If set to True, uppercase the alpha characters (default: False)
include_alpha
If set to True, include alpha characters (default: True)
include_digits
If set to True, include digit characters (default: True)
include_punctuation
If set to True, include punctuation characters (default: False)
"""
def __init__(self, *args, **kwargs):
kwargs.setdefault('blank', True)
kwargs.setdefault('editable', False)
self.length = kwargs.pop('length', None)
if self.length is None:
raise ValueError("missing 'length' argument")
kwargs['max_length'] = self.length
self.lowercase = kwargs.pop('lowercase', False)
self.check_is_bool('lowercase')
self.uppercase = kwargs.pop('uppercase', False)
self.check_is_bool('uppercase')
if self.uppercase and self.lowercase:
raise ValueError("the 'lowercase' and 'uppercase' arguments are mutually exclusive")
self.include_digits = kwargs.pop('include_digits', True)
self.check_is_bool('include_digits')
self.include_alpha = kwargs.pop('include_alpha', True)
self.check_is_bool('include_alpha')
self.include_punctuation = kwargs.pop('include_punctuation', False)
self.check_is_bool('include_punctuation')
self.max_unique_query_attempts = kwargs.pop('max_unique_query_attempts', MAX_UNIQUE_QUERY_ATTEMPTS)
# Set unique=False unless it's been set manually.
if 'unique' not in kwargs:
kwargs['unique'] = False
super().__init__(*args, **kwargs)
def random_char_generator(self, chars):
for i in range(self.max_unique_query_attempts):
yield ''.join(get_random_string(self.length, chars))
raise RuntimeError('max random character attempts exceeded (%s)' % self.max_unique_query_attempts)
def in_unique_together(self, model_instance):
for params in model_instance._meta.unique_together:
if self.attname in params:
return True
return False
def pre_save(self, model_instance, add):
if not add and getattr(model_instance, self.attname) != '':
return getattr(model_instance, self.attname)
population = ''
if self.include_alpha:
if self.lowercase:
population += string.ascii_lowercase
elif self.uppercase:
population += string.ascii_uppercase
else:
population += string.ascii_letters
if self.include_digits:
population += string.digits
if self.include_punctuation:
population += string.punctuation
random_chars = self.random_char_generator(population)
if not self.unique and not self.in_unique_together(model_instance):
new = next(random_chars)
setattr(model_instance, self.attname, new)
return new
return self.find_unique(
model_instance,
model_instance._meta.get_field(self.attname),
random_chars,
)
def internal_type(self):
return "CharField"
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
kwargs['length'] = self.length
del kwargs['max_length']
if self.lowercase is True:
kwargs['lowercase'] = self.lowercase
if self.uppercase is True:
kwargs['uppercase'] = self.uppercase
if self.include_alpha is False:
kwargs['include_alpha'] = self.include_alpha
if self.include_digits is False:
kwargs['include_digits'] = self.include_digits
if self.include_punctuation is True:
kwargs['include_punctuation'] = self.include_punctuation
if self.unique is True:
kwargs['unique'] = self.unique
return name, path, args, kwargs
class CreationDateTimeField(DateTimeField):
"""
CreationDateTimeField
By default, sets editable=False, blank=True, auto_now_add=True
"""
def __init__(self, *args, **kwargs):
kwargs.setdefault('editable', False)
kwargs.setdefault('blank', True)
kwargs.setdefault('auto_now_add', True)
DateTimeField.__init__(self, *args, **kwargs)
def get_internal_type(self):
return "DateTimeField"
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if self.editable is not False:
kwargs['editable'] = True
if self.blank is not True:
kwargs['blank'] = False
if self.auto_now_add is not False:
kwargs['auto_now_add'] = True
return name, path, args, kwargs
class ModificationDateTimeField(CreationDateTimeField):
"""
ModificationDateTimeField
By default, sets editable=False, blank=True, auto_now=True
Sets value to now every time the object is saved.
"""
def __init__(self, *args, **kwargs):
kwargs.setdefault('auto_now', True)
DateTimeField.__init__(self, *args, **kwargs)
def get_internal_type(self):
return "DateTimeField"
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if self.auto_now is not False:
kwargs['auto_now'] = True
return name, path, args, kwargs
def pre_save(self, model_instance, add):
if not getattr(model_instance, 'update_modified', True):
return getattr(model_instance, self.attname)
return super().pre_save(model_instance, add)
class UUIDVersionError(Exception):
pass
class UUIDFieldMixin:
"""
UUIDFieldMixin
By default uses UUID version 4 (randomly generated UUID).
The field support all uuid versions which are natively supported by the uuid python module, except version 2.
For more information see: http://docs.python.org/lib/module-uuid.html
"""
DEFAULT_MAX_LENGTH = 36
def __init__(self, verbose_name=None, name=None, auto=True, version=4,
node=None, clock_seq=None, namespace=None, uuid_name=None, *args,
**kwargs):
if not HAS_UUID:
raise ImproperlyConfigured("'uuid' module is required for UUIDField. (Do you have Python 2.5 or higher installed ?)")
kwargs.setdefault('max_length', self.DEFAULT_MAX_LENGTH)
if auto:
self.empty_strings_allowed = False
kwargs['blank'] = True
kwargs.setdefault('editable', False)
self.auto = auto
self.version = version
self.node = node
self.clock_seq = clock_seq
self.namespace = namespace
self.uuid_name = uuid_name or name
super().__init__(verbose_name=verbose_name, *args, **kwargs)
def create_uuid(self):
if not self.version or self.version == 4:
return uuid.uuid4()
elif self.version == 1:
return uuid.uuid1(self.node, self.clock_seq)
elif self.version == 2:
raise UUIDVersionError("UUID version 2 is not supported.")
elif self.version == 3:
return uuid.uuid3(self.namespace, self.uuid_name)
elif self.version == 5:
return uuid.uuid5(self.namespace, self.uuid_name)
else:
raise UUIDVersionError("UUID version %s is not valid." % self.version)
def pre_save(self, model_instance, add):
value = super().pre_save(model_instance, add)
if self.auto and add and value is None:
value = force_str(self.create_uuid())
setattr(model_instance, self.attname, value)
return value
else:
if self.auto and not value:
value = force_str(self.create_uuid())
setattr(model_instance, self.attname, value)
return value
def formfield(self, **kwargs):
if self.auto:
return None
return super().formfield(**kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if kwargs.get('max_length', None) == self.DEFAULT_MAX_LENGTH:
del kwargs['max_length']
if self.auto is not True:
kwargs['auto'] = self.auto
if self.version != 4:
kwargs['version'] = self.version
if self.node is not None:
kwargs['node'] = self.node
if self.clock_seq is not None:
kwargs['clock_seq'] = self.clock_seq
if self.namespace is not None:
kwargs['namespace'] = self.namespace
if self.uuid_name is not None:
kwargs['uuid_name'] = self.name
return name, path, args, kwargs
class ShortUUIDField(UUIDFieldMixin, CharField):
"""
ShortUUIDFied
Generates concise (22 characters instead of 36), unambiguous, URL-safe UUIDs.
Based on `shortuuid`: https://github.com/stochastic-technologies/shortuuid
"""
DEFAULT_MAX_LENGTH = 22
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not HAS_SHORT_UUID:
raise ImproperlyConfigured("'shortuuid' module is required for ShortUUIDField. (Do you have Python 2.5 or higher installed ?)")
kwargs.setdefault('max_length', self.DEFAULT_MAX_LENGTH)
def create_uuid(self):
if not self.version or self.version == 4:
return shortuuid.uuid()
elif self.version == 1:
return shortuuid.uuid()
elif self.version == 2:
raise UUIDVersionError("UUID version 2 is not supported.")
elif self.version == 3:
raise UUIDVersionError("UUID version 3 is not supported.")
elif self.version == 5:
return shortuuid.uuid(name=self.namespace)
else:
raise UUIDVersionError("UUID version %s is not valid." % self.version)

View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
"""
JSONField automatically serializes most Python terms to JSON data.
Creates a TEXT field with a default value of "{}". See test_json.py for
more information.
from django.db import models
from django_extensions.db.fields import json
class LOL(models.Model):
extra = json.JSONField()
"""
import json
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
def dumps(value):
return DjangoJSONEncoder().encode(value)
def loads(txt):
return json.loads(txt)
class JSONDict(dict):
"""
Hack so repr() called by dumpdata will output JSON instead of
Python formatted data. This way fixtures will work!
"""
def __repr__(self):
return dumps(self)
class JSONList(list):
"""
Hack so repr() called by dumpdata will output JSON instead of
Python formatted data. This way fixtures will work!
"""
def __repr__(self):
return dumps(self)
class JSONField(models.TextField):
"""
JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly. Main thingy must be a dict object.
"""
def __init__(self, *args, **kwargs):
kwargs['default'] = kwargs.get('default', dict)
models.TextField.__init__(self, *args, **kwargs)
def get_default(self):
if self.has_default():
default = self.default
if callable(default):
default = default()
return self.to_python(default)
return super().get_default()
def to_python(self, value):
"""Convert our string value to JSON after we load it from the DB"""
if value is None or value == '':
return {}
if isinstance(value, str):
res = loads(value)
else:
res = value
if isinstance(res, dict):
return JSONDict(**res)
elif isinstance(res, list):
return JSONList(res)
return res
def get_prep_value(self, value):
if not isinstance(value, str):
return dumps(value)
return super(models.TextField, self).get_prep_value(value)
def from_db_value(self, value, expression, connection): # type: ignore
return self.to_python(value)
def get_db_prep_save(self, value, connection, **kwargs):
"""Convert our JSON object to a string before we save"""
if value is None and self.null:
return None
# default values come in as strings; only non-strings should be
# run through `dumps`
if not isinstance(value, str):
value = dumps(value)
return value
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if self.default == '{}':
del kwargs['default']
return name, path, args, kwargs

View File

@ -0,0 +1,134 @@
# -*- coding: utf-8 -*-
from django.db import models
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from django_extensions.db.fields import AutoSlugField, CreationDateTimeField, ModificationDateTimeField
class TimeStampedModel(models.Model):
"""
TimeStampedModel
An abstract base class model that provides self-managed "created" and
"modified" fields.
"""
created = CreationDateTimeField(_('created'))
modified = ModificationDateTimeField(_('modified'))
def save(self, **kwargs):
self.update_modified = kwargs.pop('update_modified', getattr(self, 'update_modified', True))
super().save(**kwargs)
class Meta:
get_latest_by = 'modified'
abstract = True
class TitleDescriptionModel(models.Model):
"""
TitleDescriptionModel
An abstract base class model that provides title and description fields.
"""
title = models.CharField(_('title'), max_length=255)
description = models.TextField(_('description'), blank=True, null=True)
class Meta:
abstract = True
class TitleSlugDescriptionModel(TitleDescriptionModel):
"""
TitleSlugDescriptionModel
An abstract base class model that provides title and description fields
and a self-managed "slug" field that populates from the title.
.. note ::
If you want to use custom "slugify" function, you could
define ``slugify_function`` which then will be used
in :py:class:`AutoSlugField` to slugify ``populate_from`` field.
See :py:class:`AutoSlugField` for more details.
"""
slug = AutoSlugField(_('slug'), populate_from='title')
class Meta:
abstract = True
class ActivatorQuerySet(models.query.QuerySet):
"""
ActivatorQuerySet
Query set that returns statused results
"""
def active(self):
""" Return active query set """
return self.filter(status=ActivatorModel.ACTIVE_STATUS)
def inactive(self):
""" Return inactive query set """
return self.filter(status=ActivatorModel.INACTIVE_STATUS)
class ActivatorModelManager(models.Manager):
"""
ActivatorModelManager
Manager to return instances of ActivatorModel: SomeModel.objects.active() / .inactive()
"""
def get_queryset(self):
""" Use ActivatorQuerySet for all results """
return ActivatorQuerySet(model=self.model, using=self._db)
def active(self):
"""
Return active instances of ActivatorModel:
SomeModel.objects.active(), proxy to ActivatorQuerySet.active
"""
return self.get_queryset().active()
def inactive(self):
"""
Return inactive instances of ActivatorModel:
SomeModel.objects.inactive(), proxy to ActivatorQuerySet.inactive
"""
return self.get_queryset().inactive()
class ActivatorModel(models.Model):
"""
ActivatorModel
An abstract base class model that provides activate and deactivate fields.
"""
INACTIVE_STATUS = 0
ACTIVE_STATUS = 1
STATUS_CHOICES = (
(INACTIVE_STATUS, _('Inactive')),
(ACTIVE_STATUS, _('Active')),
)
status = models.IntegerField(_('status'), choices=STATUS_CHOICES, default=ACTIVE_STATUS)
activate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for an immediate activation'))
deactivate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for indefinite activation'))
objects = ActivatorModelManager()
class Meta:
ordering = ('status', '-activate_date',)
abstract = True
def save(self, *args, **kwargs):
if not self.activate_date:
self.activate_date = now()
super().save(*args, **kwargs)

View File

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
from importlib import import_module
from inspect import (
getmembers,
isclass,
)
from pkgutil import walk_packages
from typing import ( # NOQA
Dict,
List,
Tuple,
Union,
)
from django.conf import settings
from django.utils.module_loading import import_string
class SubclassesFinder:
def __init__(self, base_classes_from_settings):
self.base_classes = []
for element in base_classes_from_settings:
if isinstance(element, str):
element = import_string(element)
self.base_classes.append(element)
def _should_be_imported(self, candidate_to_import): # type: (Tuple[str, type]) -> bool
for base_class in self.base_classes:
if issubclass(candidate_to_import[1], base_class):
return True
return False
def collect_subclasses(self): # type: () -> Dict[str, List[Tuple[str, str]]]
"""
Collect all subclasses of user-defined base classes from project.
:return: Dictionary from module name to list of tuples.
First element of tuple is model name and second is alias.
Currently we set alias equal to model name,
but in future functionality of aliasing subclasses can be added.
"""
result = {} # type: Dict[str, List[Tuple[str, str]]]
for loader, module_name, is_pkg in walk_packages(path=[settings.BASE_DIR]):
subclasses_from_module = self._collect_classes_from_module(module_name)
if subclasses_from_module:
result[module_name] = subclasses_from_module
return result
def _collect_classes_from_module(self, module_name): # type: (str) -> List[Tuple[str, str]]
for excluded_module in getattr(settings, 'SHELL_PLUS_SUBCLASSES_IMPORT_MODULES_BLACKLIST', []):
if module_name.startswith(excluded_module):
return []
imported_module = import_module(module_name)
classes_to_import = getmembers(
imported_module, lambda element: isclass(element) and element.__module__ == imported_module.__name__
)
classes_to_import = list(filter(self._should_be_imported, classes_to_import))
return [(name, name) for name, _ in classes_to_import]

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
"""
Daily cleanup job.
Can be run as a cronjob to clean out old data from the database (only expired
sessions at the moment).
"""
from django.conf import settings
from django.core.cache import caches
from django_extensions.management.jobs import DailyJob
class Job(DailyJob):
help = "Cache (db) cleanup Job"
def execute(self):
if hasattr(settings, 'CACHES'):
for cache_name, cache_options in settings.CACHES.items():
if cache_options['BACKEND'].endswith("DatabaseCache"):
cache = caches[cache_name]
cache.clear()
return

View File

@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
"""
Daily cleanup job.
Can be run as a cronjob to clean out old data from the database (only expired
sessions at the moment).
"""
from django_extensions.management.jobs import DailyJob
class Job(DailyJob):
help = "Django Daily Cleanup Job"
def execute(self):
from django.core import management
management.call_command("clearsessions")

View File

@ -0,0 +1,79 @@
# django_extentions in Danish.
# django_extensions på Dansk.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Michael Lind Mortensen <illio@cs.au.dk>, 2009.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "og"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Brug feltet til venstre til at lave %(model_name)s lookups i felterne %"
"(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "skabt"
#: db/models.py:16
msgid "modified"
msgstr "ændret"
#: db/models.py:26
msgid "title"
msgstr "titel"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "beskrivelse"
#: db/models.py:50
msgid "Inactive"
msgstr ""
#: db/models.py:51
msgid "Active"
msgstr ""
#: db/models.py:53
msgid "status"
msgstr ""
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr ""
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr ""
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Lookup"

View File

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "und"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Das linke Feld benutzen, um %(model_name)s Abfragen in den Feldern %"
"(field_list)s durchführen."
#: db/models.py:15
msgid "created"
msgstr "erstellt"
#: db/models.py:16
msgid "modified"
msgstr "geändert"
#: db/models.py:26
msgid "title"
msgstr "Titel"
#: db/models.py:27
msgid "slug"
msgstr "Slug"
#: db/models.py:28
msgid "description"
msgstr "Beschreibung"
#: db/models.py:50
msgid "Inactive"
msgstr "Inaktiv"
#: db/models.py:51
msgid "Active"
msgstr "Aktiv"
#: db/models.py:53
msgid "status"
msgstr "Status"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "Leer lassen für sofortige Aktivierung"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "Leer lassen für unbefristete Aktivierung"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s ist kein urlpattern Objekt"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Abfrage"

View File

@ -0,0 +1,79 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: 2011-02-02 10:38+0000\n"
"Last-Translator: Jannis <jannis@leidel.info>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: el\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: admin/__init__.py:121
msgid "and"
msgstr "και"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Χρησιμοποίησε το αριστερό πεδίο για να κάνεις αναζήτηση του %(model_name)s "
"με βάσει τα πεδία %(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "δημιουργήθηκε"
#: db/models.py:16
msgid "modified"
msgstr "τροποποιήθηκε"
#: db/models.py:26
msgid "title"
msgstr "τίτλος"
#: db/models.py:27
msgid "slug"
msgstr "μίνι-όνομα"
#: db/models.py:28
msgid "description"
msgstr "περιγραφή"
#: db/models.py:50
msgid "Inactive"
msgstr "ανενεργό"
#: db/models.py:51
msgid "Active"
msgstr "Ενεργό"
#: db/models.py:53
msgid "status"
msgstr "κατάσταση"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "αφήστε άδειο για άμεση ενεργοποίηση"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "αφήστε άδειο για αόριστη ενεργοποίηση"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s δεν φαίνεται να είναι ένα αντικείμενο urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Αναζήτηση"

View File

@ -0,0 +1,112 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-02-10 20:37+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:142
msgid "and"
msgstr ""
#: admin/__init__.py:144
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
#: admin/filter.py:24 admin/filter.py:53
msgid "Yes"
msgstr ""
#: admin/filter.py:25 admin/filter.py:54
msgid "No"
msgstr ""
#: admin/filter.py:32
msgid "All"
msgstr ""
#: db/models.py:18
msgid "created"
msgstr ""
#: db/models.py:19
msgid "modified"
msgstr ""
#: db/models.py:38
msgid "title"
msgstr ""
#: db/models.py:39
msgid "description"
msgstr ""
#: db/models.py:60
msgid "slug"
msgstr ""
#: db/models.py:121 mongodb/models.py:76
msgid "Inactive"
msgstr ""
#: db/models.py:122 mongodb/models.py:77
msgid "Active"
msgstr ""
#: db/models.py:124
msgid "status"
msgstr ""
#: db/models.py:125 mongodb/models.py:80
msgid "keep empty for an immediate activation"
msgstr ""
#: db/models.py:126 mongodb/models.py:81
msgid "keep empty for indefinite activation"
msgstr ""
#: mongodb/fields/__init__.py:22
#, python-format
msgid "String (up to %(max_length)s)"
msgstr ""
#: validators.py:14
msgid "Control Characters like new lines or tabs are not allowed."
msgstr ""
#: validators.py:48
msgid "Leading and Trailing whitespaces are not allowed."
msgstr ""
#: validators.py:74
msgid "Only a hex string is allowed."
msgstr ""
#: validators.py:75
#, python-format
msgid "Invalid length. Must be %(length)d characters."
msgstr ""
#: validators.py:76
#, python-format
msgid "Ensure that there are more than %(min)s characters."
msgstr ""
#: validators.py:77
#, python-format
msgid "Ensure that there are no more than %(max)s characters."
msgstr ""

View File

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "y"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Utilice el campo de la izquierda para hacer búsquedas en los campos %"
"(field_list)s de %(model_name)s."
#: db/models.py:15
msgid "created"
msgstr "creado"
#: db/models.py:16
msgid "modified"
msgstr "modificado"
#: db/models.py:26
msgid "title"
msgstr "titulo"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "descripción"
#: db/models.py:50
msgid "Inactive"
msgstr "Inactivo"
#: db/models.py:51
msgid "Active"
msgstr "Activo"
#: db/models.py:53
msgid "status"
msgstr "estado"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "mantener vacío para una activación inmediata"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "deje vacío para mantener la activación indefinida"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "% s no parece ser un objeto urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Buscar"

View File

@ -0,0 +1,81 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# mathiasuk, 2014
# mathiasuk, 2014
# stevandoh <stevandoh@gmail.com>, 2013
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:42+0100\n"
"PO-Revision-Date: 2014-01-11 11:14+0000\n"
"Last-Translator: mathiasuk\n"
"Language-Team: French (http://www.transifex.com/projects/p/django-extensions/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: admin/__init__.py:121
msgid "and"
msgstr "et"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields "
"%(field_list)s."
msgstr "Utilisez le champ de gauche pour faire des recheres de %(model_name)s dans les champs %(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "créé"
#: db/models.py:16
msgid "modified"
msgstr "mis à jour"
#: db/models.py:26
msgid "title"
msgstr "titre"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "description"
#: db/models.py:50
msgid "Inactive"
msgstr "Inactif"
#: db/models.py:51
msgid "Active"
msgstr "Actif"
#: db/models.py:53
msgid "status"
msgstr "état"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "laisser vide pour activation immédiate"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "laisser vide pour activation indéterminée"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s ne semble pas etre un object urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Recherche"

View File

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "és"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Használd a baloldali mezőt hogy keress a %(model_name)s %(field_list)s. "
"mezőiben"
#: db/models.py:15
msgid "created"
msgstr "létrehozva"
#: db/models.py:16
msgid "modified"
msgstr "módosítva"
#: db/models.py:26
msgid "title"
msgstr "Cím"
#: db/models.py:27
msgid "slug"
msgstr "Slug"
#: db/models.py:28
msgid "description"
msgstr "Leírás"
#: db/models.py:50
msgid "Inactive"
msgstr "Inaktív"
#: db/models.py:51
msgid "Active"
msgstr "Aktív"
#: db/models.py:53
msgid "status"
msgstr "Állapot"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "Üresen hagyni azonnali aktiváláshoz"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "Üresen hagyni korlátlan aktiváláshoz"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "Úgy néz ki hogy %s nem egy urlpattern objektum"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Lekérdezés"

View File

@ -0,0 +1,98 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: django-extensions\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-27 22:25+0700\n"
"PO-Revision-Date: 2020-07-28 10:48+0700\n"
"Last-Translator: Sutrisno Efendi <kangfend@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: admin/__init__.py:139
msgid "and"
msgstr "dan"
#: admin/__init__.py:141
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Gunakan bidang sebelah kiri untuk pencarian %(model_name)s pada bidang %(field_list)s."
#: admin/filter.py:24 admin/filter.py:53
msgid "Yes"
msgstr "Ya"
#: admin/filter.py:25 admin/filter.py:54
msgid "No"
msgstr "Tidak"
#: admin/filter.py:32
msgid "All"
msgstr "Semua"
#: db/models.py:18
msgid "created"
msgstr "dibuat"
#: db/models.py:19
msgid "modified"
msgstr "diubah"
#: db/models.py:37
msgid "title"
msgstr "judul"
#: db/models.py:38
msgid "description"
msgstr "deskripsi"
#: db/models.py:59
msgid "slug"
msgstr "slug"
#: db/models.py:120 mongodb/models.py:76
msgid "Inactive"
msgstr "Nonaktif"
#: db/models.py:121 mongodb/models.py:77
msgid "Active"
msgstr "Aktif"
#: db/models.py:123
msgid "status"
msgstr "status"
#: mongodb/fields/__init__.py:22
#, python-format
msgid "String (up to %(max_length)s)"
msgstr "String (hingga %(max_length)s)"
#: validators.py:74
msgid "Only a hex string is allowed."
msgstr "Hanya string hex yang diizinkan."
#: validators.py:75
#, python-format
msgid "Invalid length. Must be %(length)d characters."
msgstr "Panjang tidak valid. Harus %(length)d karakter."
#: validators.py:76
#, python-format
msgid "Ensure that there are more than %(min)s characters."
msgstr "Pastikan lebih dari %(min)s karakter."
#: validators.py:77
#, python-format
msgid "Ensure that there are no more than %(max)s characters."
msgstr "Pastikan tidak lebih dari %(max)s karakter."

View File

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "e"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Utilizzare il campo a sinistra per fare ricerche nei campi %(field_list)s "
"del modello %(model_name)s."
#: db/models.py:15
msgid "created"
msgstr "creato"
#: db/models.py:16
msgid "modified"
msgstr "modificato"
#: db/models.py:26
msgid "title"
msgstr "titolo"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "descrizione"
#: db/models.py:50
msgid "Inactive"
msgstr "Inattivo"
#: db/models.py:51
msgid "Active"
msgstr "Attivo"
#: db/models.py:53
msgid "status"
msgstr "stato"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "lasciare vuoto per attivazione immediata"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "lasciare vuoti per attivazione indefinita"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "% s non sembra essere un oggetto urlPattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Ricerca"

View File

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "と"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"%(field_list)s フィールドの内容から %(model_name)s を検索するには左のフィール"
"ドを使用して下さい。"
#: db/models.py:15
msgid "created"
msgstr "作成日時"
#: db/models.py:16
msgid "modified"
msgstr "変更日時"
#: db/models.py:26
msgid "title"
msgstr "タイトル"
#: db/models.py:27
msgid "slug"
msgstr "スラグ"
#: db/models.py:28
msgid "description"
msgstr "説明"
#: db/models.py:50
msgid "Inactive"
msgstr "非アクティブ"
#: db/models.py:51
msgid "Active"
msgstr "アクティブ"
#: db/models.py:53
msgid "status"
msgstr "ステータス"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "すぐに有効化する場合は空白のままにして下さい"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "無期限に有効化しておく場合は空白のままにして下さい"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s は urlpattern オブジェクトではないようです"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "検索"

View File

@ -0,0 +1,109 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Zbigniew Siciarz <antyqjon@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "i"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Użyj pola po lewej, by wyszukać pola %(field_list)s w modelu %(model_name)s."
#: db/models.py:15
msgid "created"
msgstr "utworzony"
#: db/models.py:16
msgid "modified"
msgstr "zmodyfikowany"
#: db/models.py:26
msgid "title"
msgstr "tytuł"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "opis"
#: db/models.py:50
msgid "Inactive"
msgstr "Nieaktywny"
#: db/models.py:51
msgid "Active"
msgstr "Aktywny"
#: db/models.py:53
msgid "status"
msgstr "stan"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "pozostaw puste, by aktywować od razu"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "pozostaw puste, by nie definiować daty deaktywacji"
#: mongodb/fields/__init__.py:22
#, python-format
msgid "String (up to %(max_length)s)"
msgstr "String (do %(max_length)s znaków)"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s nie jest obiektem typu urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Szukaj"
#: validators.py:14
msgid "Control Characters like new lines or tabs are not allowed."
msgstr "Znaki nowej linii i tabulatory nie są dozwolone."
#: validators.py:48
msgid "Leading and Trailing whitespaces are not allowed."
msgstr "Białe znaki na początku i końcu wiersza nie są dozwolone."
#: validators.py:74
msgid "Only a hex string is allowed."
msgstr "Tylko wartość hex jest dozwolona."
#: validators.py:75
#, python-format
msgid "Invalid length. Must be %(length)d characters."
msgstr "Niewłaściwa długość. Musi być %(length)d znaków."
#: validators.py:76
#, python-format
msgid "Ensure that there are more than %(min)s characters."
msgstr "Upewnij się, że jest więcej niż %(min)s znaków."
#: validators.py:77
#, python-format
msgid "Ensure that there are no more than %(max)s characters."
msgstr "Upewnij się, że nie ma więcej niż %(max)s znaków."

View File

@ -0,0 +1,77 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-02-02 11:43+0100\n"
"PO-Revision-Date: 2010-11-15 22:06-0300\n"
"Last-Translator: Fernando Silva <fernand at liquuid dot net>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: admin/__init__.py:121
msgid "and"
msgstr "e"
#: admin/__init__.py:123
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr ""
"Use o campo esquerdo para fazer com que o modelo %(model_name)s procure nos "
"campos %(field_list)s."
#: db/models.py:15
msgid "created"
msgstr "criado"
#: db/models.py:16
msgid "modified"
msgstr "modificado"
#: db/models.py:26
msgid "title"
msgstr "título"
#: db/models.py:27
msgid "slug"
msgstr "slug"
#: db/models.py:28
msgid "description"
msgstr "descrição"
#: db/models.py:50
msgid "Inactive"
msgstr "Inativo"
#: db/models.py:51
msgid "Active"
msgstr "Ativo"
#: db/models.py:53
msgid "status"
msgstr "estado"
#: db/models.py:56
msgid "keep empty for an immediate activation"
msgstr "deixe vazio para ativação imediata"
#: db/models.py:58
msgid "keep empty for indefinite activation"
msgstr "deixe vazio para ativação por tempo indeterminado"
#: management/commands/show_urls.py:34
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s não parece ser um objeto urlpattern"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Busca"

View File

@ -0,0 +1,79 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Claudemiro Alves Feitosa Neto <dimiro1@gmail.com>, 2013.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-09-13 22:49-0300\n"
"PO-Revision-Date: 2013-09-13 22:49-0300\n"
"Last-Translator: Claudemiro Alves Feitosa <dimiro1@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: admin/__init__.py:128
msgid "and"
msgstr "e"
#: admin/__init__.py:130
#, python-format
msgid ""
"Use the left field to do %(model_name)s lookups in the fields %(field_list)s."
msgstr "Use o campo da esquerda para fazer com que o modelo %(model_name)s procure nos "
"campos %(field_list)s"
#: db/models.py:22 mongodb/models.py:17
msgid "created"
msgstr "criado"
#: db/models.py:23 mongodb/models.py:18
msgid "modified"
msgstr "modificado"
#: db/models.py:36 mongodb/models.py:29
msgid "title"
msgstr "título"
#: db/models.py:37 mongodb/models.py:30
msgid "slug"
msgstr "slug"
#: db/models.py:38 mongodb/models.py:31
msgid "description"
msgstr "descrição"
#: db/models.py:63 mongodb/models.py:55
msgid "Inactive"
msgstr "Inativo"
#: db/models.py:64 mongodb/models.py:56
msgid "Active"
msgstr "Ativo"
#: db/models.py:66 mongodb/models.py:58
msgid "status"
msgstr "status"
#: db/models.py:67 mongodb/models.py:59
msgid "keep empty for an immediate activation"
msgstr "deixe vazio para uma ativação imediata"
#: db/models.py:68 mongodb/models.py:60
msgid "keep empty for indefinite activation"
msgstr "deixe vazio para ativação por tempo indeterminado"
#: mongodb/fields/__init__.py:24
#, python-format
msgid "String (up to %(max_length)s)"
msgstr "Cadeia de Caracteres (até %(max_length)s)"
#: templates/django_extensions/widgets/foreignkey_searchinput.html:4
msgid "Lookup"
msgstr "Busca"

Some files were not shown because too many files have changed in this diff Show More