.. auto generated by export_components.py ************ Contrib Apps ************ |development| |area| Various, optional apps for commonly needed features of a web site or web application. **Version:** 0.4.0-d Contributing or *contrib* apps provide pre-defined functionality. Some of this functionality may be used as is, while other features require integration or customization to be effectively employed. .. _contrib-contrib-accounts: Accounts ======== |development| |suite| **Version:** 0.4.0-d Various apps for managing user accounts. Developer Reference: :ref:`contrib-contrib-accounts-developer` .. _contrib-contrib-accounts-admin: Account Admin ------------- |development| |app| **Version:** 0.3.0-d The user admin app provides a SuperDjango UI for working with users and groups. Developer Reference: :ref:`contrib-contrib-accounts-admin-developer` **Provides** - UI Abstract ........ The user admin app provides a SuperDjango UI for working with users and groups. Install ....... Add ``superdjango.contrib.accounts.admin.apps.DefaultConfig`,` to ``INSTALLED_APPS``. .. note:: The SuperDjango UI system is required and ``UsersMenu`` must be registered. .. _contrib-contrib-accounts-auth: Authentication -------------- |alpha| |app| **Version:** 0.7.0-a Basic/standard user authentication via user name and/or email. Developer Reference: :ref:`contrib-contrib-accounts-auth-developer` **Provides** - Backends - `Forms `_ - Hooks - `Middleware `_ - `Templates `_ - `URLs `_ - `Views `_ **Dependencies** - `python-datetime-machine `_ (required) *Used to support things like max login attempts.* **Hooks** - ``get_login_redirect_url(request)``: Return a URL string to override the post-login redirect behavior. The first hook that responds is used. Abstract ........ The auth app focuses on user login/logout and provides support for intelligent redirection of the user after a successful login. Install ....... Add ``'superdjango.contrib.accounts.auth.apps.DefaultConfig',`` to ``INSTALLED_APPS``. Usage ..... Default usage may be invoked by loading the auth URLs: .. code-block:: python # main/urls.py from superdjango.contrib.accounts.views import AccountsViewSet auth = AccountsViewSet(auth=True) urlpatterns = [ ... path('accounts/', include(auth.urls), ] You'll also need to create an ``auth.html`` template for your theme: .. code-block:: text {% extends "base.html" %} {% block navbar %} {# no navbar #} {% endblock %} {% block breadcrumbs %} {# no breadcrumbs #} {% endblock %} .. _contrib-contrib-accounts-avatars: Avatars ------- |development| |app| **Version:** 0.4.0-d Support for user avatars. Developer Reference: :ref:`contrib-contrib-accounts-avatars-developer` **Provides** - `Template Tags `_ - Utilities Abstract ........ Simply implemented user avatars. Install ....... Add ``superdjango.contrib.accounts.avatars.apps.DefaultConfig,`` to ``INSTALLED_APPS``. Usage ..... TODO: Document avatars usage examples. .. _contrib-contrib-accounts-impersonation: User Impersonation ------------------ |development| |app| **Version:** 0.3.1-d Allow authenticated and authorized users to impersonate another user. Developer Reference: :ref:`contrib-contrib-accounts-impersonation-developer` **Provides** - `Admin `_ : base - Constants - `Context Processors `_ - `Forms `_ - `Middleware `_ - `Models `_ : abstract - `Templates `_ - `URLs `_ - Utilities - `Views `_ Abstract ........ The impersonation app allows authorized users to impersonate other users. Install ....... 1. Add ``'superdjango.contrib.accounts.impersonation.apps.DefaultConfig',`` to your ``INSTALLED_APPS``. 2. Add ``'superdjango.contrib.accounts.impersonation.middleware.UserImpersonationMiddleware',`` to your list of ``MIDDLEWARE``. 3. Add ``'superdjango.contrib.accounts.impersonation.context_processors.user_is_allowed_to_impersonate',`` to your context processors. 4. Add ``url(r'^accounts/impersonation/', include("superdjango.contrib.accounts.impersonation.urls")),`` to your ``urls.py`` file. (Or use `AccountsViewSet`.) 5. Include ``accounts/includes/user_impersonation_link.html`` somewhere in your base template, or recreate the link in the area of your choice. If you do not wish for staff users to be able to impersonate users, then set ``SUPERDJANGO_USER_IMPERSONATION_ENABLED_FOR_STAFF`` to ``False`` in ``settings.py``. You may also specify specific groups that are allowed to impersonate in ``settings.py``: .. code-block:: python SUPERDJANGO_USER_IMPERSONATION_ENABLED_FOR_GROUPS = ["Advisers", "Managers", "Trainers"] To enable database logging, you must provide a model. See ``ImpersonationHistoryModel`` as a starting point. Then set ``SUPERDJANGO_USER_IMPERSONATION_MODEL = "my_app_label.MyImpersonation"`` in ``settings.py``. .. _contrib-contrib-accounts-passwords: Password Management ------------------- |development| |app| **Version:** 0.5.0-d Allow users to self-manage passwords. Developer Reference: :ref:`contrib-contrib-accounts-passwords-developer` **Provides** - `Templates `_ - `Forms `_ - `Models `_ : abstract - `Views `_ Abstract ........ The passwords app focuses on user password management. Install ....... Add ``'superdjango.contrib.accounts.passwords.apps.DefaultConfig',`` to your ``INSTALLED_APPS``. Usage ..... Default usage may be invoked by loading the password URLs: .. code-block:: python # main/urls.py from superdjango.contrib.accounts.viewsets import AccountsViewSet passwords = AccountsViewSet(passwords=True) urlpatterns = [ ... path('accounts/passwords/', include(passwords.urls), ] .. _contrib-contrib-accounts-profiles: User Profiles ------------- |alpha| |app| **Version:** 0.7.0-a Allow users to manage their account profiles. Developer Reference: :ref:`contrib-contrib-accounts-profiles-developer` **Provides** - `Forms `_ - `Models `_ : abstract - `Signals `_ - `Templates `_ - `Views `_ Abstract ........ The profiles app provides support for user-managed profiles. Install ....... 1. Add ``'superdjango.contrib.accounts.profiles.apps.DefaultConfig',`` to your ``INSTALLED_APPS``. 2. Create your profile model by extending ``ProfileModel`` (or ``ProfileMixin``). 3. Set the ``SUPERDJANGO_USER_PROFILE_MODEL`` in ``settings.py``. Also, include profiles in your URLs. .. code-block:: python # main/urls.py from superdjango.contrib.accounts.viewsets import AccountsViewSet profiles = AccountsViewSet(profiles=True) urlpatterns = [ ... path('accounts/profile/', include(profiles.urls), ] Usage ..... You may implement a user profile using the provided :py:class:`superdjango.contrib.accounts.profiles.models.ProfileModel` as a starting point. Or use the :py:class:`superdjango.contrib.accounts.profiles.models.ProfileMixin` to implement a profile from scratch. Once your model is implemented (and migrations applied), set ``SUPERDJANGO_USER_PROFILE_MODEL`` to the dotted path of the model in the form of ``app_label.ModelName``. .. _contrib-contrib-accounts-utils: Account Utils ------------- |development| |app| **Version:** 0.5.0-d Utilities for managing user accounts. Developer Reference: :ref:`contrib-contrib-accounts-utils-developer` **Provides** - Utilities .. _contrib-contrib-accounts-views: Password Management ------------------- |development| |app| **Version:** 0.5.0-d Additional views for user account management. Developer Reference: :ref:`contrib-contrib-accounts-views-developer` **Provides** - `Views `_ : viewsets .. _contrib-contrib-embeds: Embeds ====== |experimental| |app| **Version:** 0.4.0-x An app for embedding media in a page. Developer Reference: :ref:`contrib-contrib-embeds-developer` **Provides** - `Checks `_ - Compat - Exceptions - Library - `Template Tags `_ **Dependencies** - `python-oembed `_ (required) *Required to use embed functionality.* Install ------- Install OEmbed: .. code-block:: pip install python-oembed; Add ``'superdjango.contrib.embeds.apps.DefaultConfig',`` to ``INSTALLED_APPS``. Usage ----- TODO .. _contrib-contrib-errors: Error Capture ============= |experimental| |app| **Version:** 0.3.1-x Error (exception) capture and disposition. Developer Reference: :ref:`contrib-contrib-errors-developer` **Provides** - Backends - Compat - `Middleware `_ - `Models `_ : abstract - `Templates `_ - Utilities - `Views `_ : views, viewsets **Dependencies** - `bitbucket-python `_ (optional) *Used by the bitbucket backend to create issues when an exception occurs.* - `PyGithub `_ (optional) *Used by the github backend to create issues when an exception occurs.* Abstract -------- Capturing errors (exceptions) outside of the development environment is an important aspect of product management and user experience. See the `Django documentation on error reporting`_. .. _Django documentation on error reporting: https://docs.djangoproject.com/en/stable/howto/error-reporting/ .. tip:: There are many more robust exception handling systems than SuperDjango's Error Capture app. `Sentry`_ for example, is highly recommended (and is itself a Django project). These include a great number of features, but may also require a fee. If you desire a simple, yet effective capture implementation or can't yet justify the cost of a third-party tool, then the Error Capture app may be an alternative. .. _Sentry: https://sentry.io/ Install ------- General ....... 1) Add ``superdjango.contrib.errors.apps.DefaultConfig`` to ``INSTALLED_APPS``. 2) Add ``superdjango.contrib.errors.middleware.ErrorCaptureMiddleware`` at the end of your middleware list in ``settings.py``. 3) To enable error capture in development, set ``SUPERDJANGO_ERROR_CAPTURE_DEBUG = True``. This is useful for testing customer error handlers as well as see a preview of your error templates, but it can be a hindrance to troubleshooting. 4) To control how often an error may repeat, set ``SUPERDJANGO_ERROR_CAPTURE_REPEAT_SECONDS``. The default is ``3600``, or one (1) hour. 5) Specify one or more error capture handlers using ``SUPERDJANGO_ERROR_CAPTURE_HANDLERS`` and provide the required settings for each one. See below. .. tip:: The last error handler specified is returned as the result if it is an ``HttpResponse`` instance. Bitbucket Handler ................. Create a Bitbucket issue based on an exception. Returns: a dictionary with the ``issue_url``. 1) Install bitbucket-python: ``pip install bitbucket-python`` 2) ``superdjango.contrib.errors.apps.DefaultConfig`` must be included in ``INSTALLED_APPS``. 3) Identify the repo using the ``SUPERDJANGO_ERROR_CAPTURE_BITBUCKET_REPO`` setting. 4) Identify the owner using the ``SUPERDJANGO_ERROR_CAPTURE_BITBUCKET_OWNER`` setting. 5) Provide a email using the ``SUPERDJANGO_ERROR_CAPTURE_BITBUCKET_EMAIL`` setting. 6) Provide a password using the ``SUPERDJANGO_ERROR_CAPTURE_BITBUCKET_PASSWORD`` setting. 7) Add ``superdjango.contrib.errors.backends.Bitbucket`` to ``SUPERDJANGO_ERROR_CAPTURE_HANDLERS``. CSV Handler ........... Basic data is written to ``current.csv`` in th output path, and tracebacks are written as text files in the ``tracebacks/`` directory of the output path. Returns: A dictionary with the ``issue_url`` if the error views are enabled (below). Otherwise, the dictionary includes the ``identifier`` of the error. .. note:: Each error is assigned a unique ID which exists in the CSV and is used for the file name of the traceback file. 1) To log errors to a CSV file, add ``superdjango.contrib.errors.backends.CSV`` to ``SUPERDJANGO_ERROR_CAPTURE_HANDLERS``. 2) You must also set ``SUPERDJANGO_ERROR_CAPTURE_OUTPUT_PATH`` to the path were the data is stored. For example: ``SUPERDJANGO_ERROR_CAPTURE_OUTPUT_PATH = os.path.join(BASE_DIR, "../data", "errors)``. 3) Optionally set up views. To access errors from within the project's UI, load the views. .. code-block:: python # main/urls.py from superdjango.contrib.errors.views import CSVErrorViewSet urlpatterns = [ # ... path("errors/", include(CSVErrorViewSet().get_urls())), ] Email Handler ............. Send an exception via email. Returns: ``None`` .. important:: In addition to the settings below, you must also configure `Django to send email`_. .. _Django to send email: https://docs.djangoproject.com/en/stable/ref/settings/#email-backend 1) ``superdjango.contrib.errors.apps.DefaultConfig`` must be included in ``INSTALLED_APPS``. 2) Set the "from address" using ``SUPERDJANGO_ERROR_CAPTURE_FROM_EMAIL``. 3) Set a list of email addresses to which the info is sent using ``SUPERDJANGO_ERROR_CAPTURE_EMAILS``. 4) Add ``superdjango.contrib.errors.backends.Email`` to ``SUPERDJANGO_ERROR_CAPTURE_HANDLERS``. GitHub Handler .............. Create a GitHub issue based on an exception. Returns: A dictionary with the ``issue_url``. 1) Install PyGithub: ``pip install PyGithub`` 2) ``superdjango.contrib.errors.apps.DefaultConfig`` must be included in ``INSTALLED_APPS``. 3) Identify the repo using the ``SUPERDJANGO_ERROR_CAPTURE_GITHUB_REPO`` setting. 4) Provide a token using the ``SUPERDJANGO_ERROR_CAPTURE_GITHUB_TOKEN`` setting. 5) Add ``superdjango.contrib.errors.backends.GitHub`` to ``SUPERDJANGO_ERROR_CAPTURE_HANDLERS``. Model Handler ............. Save an error report to the local database. Returns: A dictionary with the ``issue_url`` if the error views are enabled (below). Otherwise, ``None``. 1) Create an app and extend :py:class:`superdjango.contrib.errors.models.ErrorModel`. .. tip:: You can override the ``log()`` method to handle any custom fields you define on your extended model. 2) Add the dotted path to this model to settings using ``SUPERDJANGO_ERROR_CAPTURE_MODEL_NAME``. 3) Add ``superdjango.contrib.errors.backends.GitHub`` to ``SUPERDJANGO_ERROR_CAPTURE_HANDLERS``. 4) Optionally set up views. To access errors from within the project's UI, load the views. .. code-block:: python # main/urls.py from superdjango.contrib.errors.views import ModelErrorViewSet urlpatterns = [ # ... path("errors/", include(ModelErrorViewSet().get_urls())), ] .. important:: You *cannot* use ``ModelErrorViewSet`` *and* ``CSVErrorViewSet`` at the same time because these views utilize the same names. You *can* use both error handlers at once, but only one may be used for error views. You may also create a custom UI instead, using SuperDjango UI. .. code-block:: python # myapp/ui.py from .models import Error from superdjango import ui class ErrorUI(ui.ModelUI): detail_options = ui.DetailOptions( "name", "added_dt", "path", "line", "traceback", ) list_options = ui.ListOptions( "name", "added_dt", "path", "line", ) class ErrorMenu(ui.Menu): items = [ ErrorUI, ] label = "Errors" prefix = "errors" ui.site.register(ErrorMenu) Usage ----- Filtering Errors ................ Internally, the error capture system makes use of Django's ``django.views.debug.ExceptionReporter`` class. This provides support for Django's `built-in error filtering`_ functionality. .. _built-in error filtering: https://docs.djangoproject.com/en/table/howto/error-reporting/#filtering-error-reports Creating Your Own Error Handler ............................... An error handler should extend :py:class:`superdjango.contrib.errors.backends.base.ErrorHandler`. To perform additional work, the ``handle()`` method is overridden. See the existing handlers for examples. Once this is done, the custom handler may be added to the ``SUPERDJANGO_ERROR_CAPTURE_HANDLERS`` list in the ``settings.py`` file. Overriding Error Templates .......................... The templates used for creTimeZoneSelectionFormating and displaying errors may be overridden by providing your own templates in an app that is loaded above ``superdjango.contrib.errors.apps.DefaultConfig``. See ``superdjango/contrib/errors/templates/errors/`` for the templates that are defined for the various handlers. Known Issues ............ If you have an app that catches all remaining URLs (as with some CMS apps, including Wagtail), then ``DoesNotExist`` errors will be captured for things like the favicon. You can of course simply provide the missing file(s). You may also add ``django.middleware.common.BrokenLinkEmailsMiddleware`` to your middleware and define the links that should be ignored. For example: .. code-block:: python # settings.py import re IGNORABLE_404_URLS = [ re.compile(r'\.(php|cgi)$'), re.compile(r'^/phpmyadmin/'), re.compile(r'^/apple-touch-icon.*\.png$'), re.compile(r'^/favicon\.ico$'), re.compile(r'^/favicon\.ico/$'), re.compile(r'^/robots\.txt$'), ] .. _contrib-contrib-history: History ======= |experimental| |app| **Version:** 0.3.0-x An app for tracking the audit history of records in the database. Developer Reference: :ref:`contrib-contrib-history-developer` **Provides** - `Admin `_ - `Models `_ - `Templates `_ : tags - `Template Tags `_ - UI Abstract -------- The history app is an implementation of ``superdjango.db.history``, providing a concrete history with the option to also record field changes. Install ------- Add ``superdjango.contrib.history.apps.DefaultConfig`` to ``INSTALLED_APPS``. Usage ----- Integrating History With SuperDjango UI ....................................... Specify the history call back for your model UI. .. code-block:: python from superdjango import ui from superdjango.contrib.history.models import History from .models import Project class ProjectUI(ui.ModelUI): model = Project history_callback = History.log # ... You'll also need to add the :py:class:`superdjango.contrib.history.ui.HistoryUI` to a menu that is registered in order to access history records. Alternatively, you may specify the history class as part of the model UI. .. code-block:: python class ProjectUI(ui.ModelUI): model = Project history_callback = History.log history_options = ui.HistoryOptions(History) ... Integrating History with a Custom View ....................................... In this example, we had audit history to an update view: .. code-block:: python # myapp/views.py from superdjango.contrib.history.models import History from superdjango.db.history.utils import get_field_changes class UpdateTodo(UpdateView): ... def form_valid(self, form): self.object = form.save() field_changes = get_field_changes(form, self.model, record=self.object) History.log(self.object, self.request.user, History.UPDATE, fields=field_changes) ... Displaying History in a Template ................................ You may use the ``record_history`` template tag to display a record's history, for example in a detail view. .. code-block:: html {% load history_tags %} ...
...
See :ref:`db-db-history` for more examples. .. _contrib-contrib-i18n: Internationalization ==================== |planning| |suite| **Version:** 0.7.0-p Tools for assisting with internationalizing a site or application. Developer Reference: :ref:`contrib-contrib-i18n-developer` Abstract -------- Tools and resources for assisting with internationalizing a site or application. .. note:: The i18n suite does *not* provide concrete models. Form fields are provided as an alternative to model fields. In general, we feel these should be preferred because: 1. Form fields (and especially choices) may be customized at run time. 2. Choices may change with some regularity, which may generate unpredictable migrations. See also https://docs.djangoproject.com/en/stable/topics/i18n/ And https://www.w3.org/International/questions/qa-i18n .. _contrib-contrib-i18n-countries: Countries --------- |planning| |library| **Version:** 0.6.2-p Choices, form fields, and other resources for managing country data. Developer Reference: :ref:`contrib-contrib-i18n-countries-developer` **Provides** - Choices - Data - Descriptors - Factories - `Forms `_ : fields Abstract ........ Country-related data may be used in a variety of ways, including for addresses and shipping. This package wraps country data in an object-oriented interface, providing resources for working with countries. The data was originally sourced from various public resources and compiled into a re-usable (and translatable) form. .. note:: Is it accurate? To the best of our knowledge, yes, but data may change from time to time, and changes may occur outside of our refresh cycle. You should always double check the data for accuracy and report any issues you may find. .. _contrib-contrib-i18n-currencies: Currencies ---------- |planning| |library| **Version:** 0.2.3-p Choices, form fields, and other resources for managing currency data. Developer Reference: :ref:`contrib-contrib-i18n-currencies-developer` **Provides** - Choices - Descriptors - `Forms `_ : fields .. _contrib-contrib-i18n-languages: Languages --------- |experimental| |library| **Version:** 0.6.1-x Choices, constants, form fields, and other resources for managing language data. Developer Reference: :ref:`contrib-contrib-i18n-languages-developer` **Provides** - Choices - Constants - Data - Descriptors - `Forms `_ : fields Abstract ........ Web sites and Web applications may need to deal with language in a variety of ways: - Content negotiation for the `Accept Language header`_. - Manual selection of an available language. - Translation of site or application content. `Navigating this can be difficult`_. The generally accepted `approach to authoritative language codes`_ is using the `IANA Language Subtag Registry page`_. As this data is provided in record-jar format, SuperDjango sources this as JSON from `mattcg's repo`_ (specifically the ``registry.json`` and ``variant.json`` files) to generate choices and constants. .. _Accept Language header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language .. _approach to authoritative language codes: http://www.w3.org/International/techniques/server-setup#multiviews .. _IANA Language Subtag Registry page: http://www.iana.org/assignments/language-subtag-registry .. _mattcg's repo: https://github.com/mattcg/language-subtag-registry .. _Navigating this can be difficult: https://stackoverflow.com/a/13899628/241720 Install ....... No special installation steps are required, but you are referred to the Django docs for setting up language detection: https://docs.djangoproject.com/en/stable/topics/i18n/translation/#how-django-discovers-language-preference .. _contrib-contrib-i18n-timezones: Time Zones ---------- |development| |library| **Version:** 0.8.2-d Choices, constants, form fields, and other resources for managing timezones. Developer Reference: :ref:`contrib-contrib-i18n-timezones-developer` **Provides** - Choices - Constants - Descriptors - `Forms `_ : fields, forms - `Middleware `_ - `Models `_ : abstract - Utilities - `Views `_ **Dependencies** - `django-solo `_ (required) *Used for the abstract TimeZoneSettingsModel.* - `pytz `_ (required) *Required, but installed by default with Django.* Abstract ........ The timezones app provides resources for specifying and managing timezones. See https://docs.djangoproject.com/en/3.0/topics/i18n/timezones/ .. _contrib-contrib-notifications: Notifications ============= |experimental| |app| **Version:** 0.4.0-x Facilitates user notifications within a project, optionally sending email and SMS. Developer Reference: :ref:`contrib-contrib-notifications-developer` **Provides** - `Admin `_ - AJAX - Constants - `Management Commands `_ - `Models `_ - Shortcuts - `Templates `_ - `Template Tags `_ - UI - `URLs `_ - `Views `_ Abstract -------- The notifications app is primarily meant to provide in-app (e.g. in-project) notifications, but may also be used to send email and SMS when supported. Install ------- Add ``superdjango.contrib.notifications.apps.DefaultConfig`` to ``INSTALLED_APPS``. Run ``./manage.py migrate``. Sending Email ............. If you will be sending notifications via email: 1. Define the email address from which the message is sent using ``SUPERDJANGO_NOTIFICATIONS_FROM_EMAIL``. 2. Define the from name of the email address using ``SUPERDJANGO_NOTIFICATIONS_FROM_NAME``. Sending SMS/Text ................ If you will be sending notifications via SMS, you'll need to create a callback which integrates with a text messaging service such as Twilio. The callback must accept a body, mobile number, and optionally a from number. For example: .. code-block:: python def send_sms(body, number, from_number=None): # ... Set ``SUPERDJANGO_NOTIFICATIONS_SMS_CALLBACK`` to the dotted path of the callback. Optionally set the ``SUPERDJANGO_NOTIFICATIONS_FROM_NUMBER``. Usage ----- The notifications system allows developers to queue up notifications for users. It is also possible for administrators or authorized users to create notifications using the provided UI (see below). Creating a Notification Programmatically ........................................ To create a notification for a user: .. code-block:: python from django.contrib.auth import get_user_model from superdjango.contrib.notifications.models import Notification UserModel = get_user_model() body = "This is a test notification." subject = "Testing 123" users = [ UserModel.objects.get(pk=1), UserModel.objects.get(pk=2), UserModel.objects.get(pk=3), ] notification = Notification.create_for(body, subject, users) You can of course pass in a list of users with only one user instance. Sending Notifications ..................... The notifications app makes use of a queue pattern where the actual links to a user (and optional email/SMS) must be executed on a regular schedule. This is the purpose of the ``send_notifications`` management command. Create a shell script which loads the Python environment and executes the command: .. code-block:: bash #! /usr/bin/env bash cd /path/to/project; source python/bin/activate; cd source; ./manage.py send_notifications; Then add the script to a cron job: .. code-block:: text # send notifications every 15 minutes */15 * * * * root /path/to/project/cron/send_notifications.sh Displaying Notifications ........................ Various template tags are provided for displaying a user's notifications in your templates. All require the current user as a parameter. ``has_notifications``: Indicates whether a user has unread notifications. .. code-block:: html {% if has_notifications request.user %}
You have some notifications.
{% endif %} ``notification_bar``: Utilizes the ``notifications/tags/notification_bar.html`` template to display a promoted notification at the top of a page. .. code-block:: html ... {% notification_bar request.user %} ... If the AJAX views are set up using the automatic method (below), you may replace ``notification-bar.js`` with ``notification-bar-ajax.js``. Otherwise, additional work is required to override ``notification-bar-ajax.js`` so that it refers to the correct URL. ``unread_notification_count``: Returns the number of unread notifications. .. code-block:: html
Notifications {% unread_notification_count request.user %}
``unread_notifications``: Utilizes the ``notifications/tags/notification_items.html`` template to display a list of notifications. .. code-block:: html
{% unread_notifications request.user %}
Finally, the included ``notify_web_api.html`` template may be used to display in-browser messages for promoted notifications. .. code-block:: html ... {% include "notifications/includes/notify_web_api.html" %} Utilizing the Standard Views ............................ Detail and list views are provided for displaying notifications to users. .. code-block:: python # main/urls.py from superdjango.contrib.notifications.views import NotificationsViewSet urlpatterns = [ path("notifications/", include(NotificationsViewSet().get_urls())), ] Utilizing the AJAX Views ........................ The notification apps provides two (2) AJAX views; one for obtaining unread notifications, and the other for marking a notification as read. To automatically include these views, simply add ``superdjango.interfaces.ajax.apps.AutoConfig`` to your ``INSTALLED_APPS`` and include the AJAX URLs in your main ``urls.py`` file. See :ref:`interfaces-interfaces-ajax`. You may also manually include the views: .. code-block:: python # main/urls.py from superdjango.contrib.notifications.views import AjaxNotificationsViewSet urlpatterns = [ # ... path("ajax/notify/", include(AjaxNotificationsViewSet().get_urls())), # ... ] Setting up the UI ................. The notification apps comes with pre-defined configuration for SuperDjango UI. You may use it as is by registering the ``NotificationsMenu`` with the UI, or customize as desired. .. code-block:: python # glue/ui.py from superdjango import ui from superdjango.contrib.notifications.ui import NotificationsMenu ui.site.register(NotificationsMenu) .. _contrib-contrib-releases: Releases ======== |experimental| |app| **Version:** 0.2.0-x Provides support for managing project releases. Developer Reference: :ref:`contrib-contrib-releases-developer` **Provides** - Constants - Library - `Management Commands `_ - `Templates `_ - `URLs `_ - `Views `_ **Dependencies** - `markdown `_ (required) *Used to generate release pages from Markdown files.* - `semver `_ (required) *Used for version bumping.* Abstract -------- Managing releases in a consistent manner is a strategic strength for any project. Additionally, the ability to maintain release information for both users, developers, and administrators provides essential communication regarding each release of the project and paints a historical picture of the project's progress. Installation ------------ Install requirements: .. code-block:: bash pip install Markdown semver; Add ``superdjango.contrib.release.apps.DefaultConfig`` to ``INSTALLED_APPS``. Optionally configure the following settings: .. code-block:: python # Markdown extensions for rendering article content. SUPERDJANGO_RELEASE_PATH = "/path/to/releases/" The default is ``os.path.join(settings.BASE_DIR, "../deploy", "releases")``. Add URLs: .. code-block:: python urlpatterns = [ # ... path('releases/', include(superdjango.contrib.support.urls), # ... ] .. note:: If ``superdjango.contrib.support`` is installed, the release app's views will automatically integrate with the built-in help site. See the documentation for the support app for install. Usage ----- To create a new release: .. code-block:: bash ./manage.py create_release -m 2 Customize the INI files and content files as desired. .. _contrib-contrib-scheduler: Scheduler ========= |experimental| |app| **Version:** 0.5.0-x Provides support for scheduling jobs from the command line. Developer Reference: :ref:`contrib-contrib-scheduler-developer` **Provides** - Constants - Decorators - Library - `Management Commands `_ - `Models `_ - UI **Dependencies** - `schedule `_ (required) *Used to execute scheduled jobs.* Abstract -------- Backend (that is, server-side) jobs are a common necessity for many web-based applications. On POSIX systems, the cron job system is sometimes adequate, sometimes not so much. The scheduler app provides a solution for job scheduling that does not depend on cron while allowing app developers to define callbacks in Python that maybe configured to execute on a pre-determined schedule. Administrators or authorized users may optionally configure these jobs. Install ------- Make sure a ``config/`` directory exists in project root. If automatic discovery of jobs is desired, add ``superdjango.contrib.scheduler.apps.AutoConfig`` to ``INSTALLED_APPS``. Otherwise, create a ``scheduler.ini`` file in the ``config/`` directory (see below). For automated discovery, the Python module name defaults to ``scheduler``, but may changed using the ``SUPERDJANGO_SCHEDULER_MODULE_NAME`` setting. Usage ----- There are two (2) means of using the scheduler: 1. Manually configuring jobs by creating an maintaining the ``scheduler.ini`` file. 2. Auto discovery of jobs. .. important:: Note that the included (concrete) models are only used when auto-discovery is enabled. Manually Configuring Jobs ......................... Scheduled jobs are stored in a ``scheduler.ini`` file. This is assumed to be located in the ``config/`` directory of project root, but the location may be specified using the ``SUPERDJANGO_SCHEDULER_PATH`` setting. Each section of the INI represents a recurring job. The section name becomes the label of the job. Section parameters establish the attributes of the job to be performed. These are: - ``active``: Optional. ``yes`` (the default) or ``no``. - ``at``: Optional. The time of day to run the job in ``HH:MM`` (24 hour) format. - ``call``: Required. The callback to use for the job in dotted path format. - ``description``: Optional. A description may be provided to further explain or comment on the job. - ``every``: Required. Establishes the timing and interval in ``frequency interval`` format. For example: ``every = 10 minutes``. The valid frequencies are: - second - seconds - minute - minutes - hour - hours - day - days - week - weeks - monday - tuesday - wednesday - thursday - friday - saturday - sunday .. tip:: ``at`` is only applied when specifying a weekday frequency. Additional parameters within the section become keyword arguments passed to the callback. Here are some examples: .. code-block:: ini [run a test job] call = example.scheduler.test_job every = 5 seconds testing = True [this job should never make it to the scheduler] call = example.scheduler.nonexistent_job description = A nonexistent callback will not make it into the schedule. every = 5 seconds [this job is inactive] active = no call = example.automation.inactive_job every = 10 minutes [this job runs on sunday] callback = example.scheduler.sunday_cleanup frequency = sunday at = 23:30 Automatic Discovery of Jobs ........................... The provided registry interface allows for any app in the project to report that it has one or more jobs that may be included in the scheduler. 1. To build a list of jobs in the database, run: ``./manage.py scheduler_discover_jobs`` 2. Activate/deactivate jobs in the UI. 3. Export the ``scheduler.ini`` file: ``./manage.py scheduler_export_ini`` See `Creating Job Callbacks`_ below. You may provide a user interface for automated discovery by registering the UI menu provided with the scheduler. .. code-block:: python # glue/ui.py from superdjango import ui from superdjango.contrib.scheduler.ui import ScheduledJobsMenu ui.site.register(ScheduledJobsMenu) Listing the Available Jobs .......................... Regardless of manual or automatic discovery, the ``scheduler_list_jobs`` command will list the jobs found in the ``scheduler.ini`` file. Setting Up Supervisor D ....................... Some means of executing jobs is required. One way to do this is to set up `supervisord`_. .. _supervisord: http://supervisord.org .. tip:: You can use the management command: ``./manage.py scheduler_export_supervisord`` to create the configuration on the server. This requires a supervisord configuration file which points to a shell script. .. code-block:: text [program:superdjango_scheduler] command=/path/to/project/cron/scheduler.sh autostart=true autorestart=true stderr_logfile=/path/to/project/logs/scheduler.err.log stdout_logfile=/path/to/project/logs/scheduler.out.log The shell script is needed to a) load the Python virtual environment, and b) execute the management commands which queues up the jobs. For example: .. code-block:: bash #! /usr/bin/env bash source /path/to/project/python/bin/active; (cd /path/to/project/source && ./manage.py scheduler_run_jobs); Creating Job Callbacks ...................... A callback function is needed to execute a job. The function must accept ``**kwargs`` and return an instance of :py:class:`superdjango.contrib.scheduler.library.Result`. .. code-block:: python # myapp/scheduler.py from superdjango.contrib.scheduler import STATUS, Result def do_something_on_a_recurring_basis(**kwargs): # do some work ... return Result( STATUS.SUCCESS, message="This may be displayed to a user.", output="This may be displayed to administrators or developers." ) The label and start/end datetimes are automatically set at runtime. With manual configuration this callback would be added to the ``scheduler.ini`` file like so: .. code-block:: ini [do something on a recurring basis] callback = myapp.scheduler.do_something_on_a_recurring_basis description = It's good practice to include a description, but it will default to the callback's docstring. every = 5 minutes When auto-discovery is configured, you must also register the callback: .. code-block:: python # myapp/scheduler.py from superdjango.contrib.scheduler import STATUS, Result, schedule def do_something_on_a_recurring_basis(**kwargs): # do some work ... return Result( STATUS.SUCCESS, message="This may be displayed to a user.", output="This may be displayed to administrators or developers." ) schedule.register("myapp", do_something_on_a_recurring_basis) Creating Activity Records ......................... When auto-discovery is enabled, it is up to the developer to create the activity records for a given job. .. code-block:: python from superdjango.contrib.scheduler import STATUS, Result, schedule from superdjango.contrib.scheduler.models import Activity def do_something_on_a_recurring_basis(**kwargs): job_id = kwargs.pop("pk", None) # do some work ... result = Result( STATUS.SUCCESS, message="This may be displayed to a user.", output="This may be displayed to administrators or developers." ) if job_id: Activity.log(job_id, result) return result schedule.register("myapp", do_something_on_a_recurring_basis) Setting Up the INI Export ......................... A simple cron job may be used to set up the regular export of auto-configured the INI file: .. code-block:: bash # /etc/cron.d/project_name SHELL=/bin/bash PATH=/path/to/project/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # Times are in UTC. Starts at 4am EST. 0 8 * * 0 root /path/to/project/cron/export_scheduler_ini.sh And the script itself: .. code-block:: bash #! /usr/bin/env bash source /path/to/project/python/bin/active; (cd /path/to/project/source && ./manage.py scheduler_run_jobs); Multi-Tenant Considerations for Scheduled Jobs .............................................. In a multi-tenant environment, scheduled jobs may need to be specific to each tenant. `When using WSGI for tenant separation`_, there are fewer concerns with data separation, but a scheduler for each tenant must be maintained. .. _When using WSGI for tenant separation: https://superdjango.com/blog/mutli-tenancy-with-wsgi/ To accomplish this, a separate ``scheduler.ini`` file is required for each tenant. We suggest creating this in the tenant's directory, such as ``/path/to/example_app/shared/tenants/acme_example_app/config/scheduler.ini``. With manual configuration, simply create or copy the file to the appropriate location. Or with auto configuration, this is easily accomplished using preview and bash output redirection: .. code-block:: bash # from project root with virtual env activated ./manage.py scheduler_export_ini \ --settings=tenants.acme_example_app.settings \ -p > tenants/acme_example_app/config/scheduler.ini; This assumed job discovery has already been performed with: .. code-block:: bash ./manage.py scheduler_discover_jobs --settings=tenants.acme_example_app.settings; Listing jobs requires specifying the path, as in: .. code-block:: bash ./manage.py scheduler_list_jobs -P tenants/acme_example_app/config/scheduler.ini; The supervisord configuration may be exported using a tenant-specific name: .. code-block:: bash ./manage.py scheduler_export_supervisord \ /path/to/example_app/shared/tenants/acme_example_app/cron/scheduler.sh \ -w -n acme_example_app; And the cron script would look something like: .. code-block:: bash #! /usr/bin/env bash source /path/to/example_app/current/python/bin/active; (cd /path/to/example_app/current/source && ./manage.py scheduler_run_jobs \ --settings=tenants.acme_example_app.settings \ -P tenants/acme_example_app/config/scheduler.ini); .. _contrib-contrib-support: Support ======= |experimental| |app| **Version:** 0.3.1-x Provides management support or help content from within a project. Developer Reference: :ref:`contrib-contrib-support-developer` **Provides** - Compat - Exceptions - Library - `Management Commands `_ - `Templates `_ - `Template Tags `_ - `URLs `_ - `Views `_ **Dependencies** - `markdown `_ (required) *Used to generate support/help docs from Markdown files.* - `python-frontmatter `_ (required) *Parses meta data from Markdown files.* - `pyyaml `_ (required) *Currently only used for the ScannerError exception that may be emitted by frontmatter.* Install ------- Install requirements: .. code-block:: bash pip install Markdown python-frontmatter pyyaml; Add ``superdjango.contrib.support.apps.DefaultConfig`` to ``INSTALLED_APPS``. Add the ``static`` directory to the ``STATICFILES_DIRS`` list: .. code-block:: python STATICFILES_DIRS = [ # ... os.path.join(BASE_DIR, "../help", "static"), ] Optionally configure the following settings: .. code-block:: python # Markdown extensions for rendering article content. SUPERDJANGO_SUPPORT_MD_EXTENSIONS = ["extra"] # The path to help content. SUPERDJANGO_SUPPORT_PATH = os.path.join(BASE_DIR, "../help") # Indicates whether unauthenticated users can access help content. SUPERDJANGO_SUPPORT_REQUIRES_LOGIN = True # Indicates search results should be logged. Helps improve the search catalog. SUPERDJANGO_SUPPORT_SEARCH_LOG_RESULTS = True # A list of terms that may be used to build the search catalog. SUPERDJANGO_SUPPORT_SEARCH_TERMS = list() Add URLs: .. code-block:: python urlpatterns = [ # ... path('help/', include(superdjango.contrib.support.urls), # ... ] Usage ----- Initialize help files and directories: Create the help directory in project root: .. code-block:: bash ./manage.py init_support_dir; Customize the INI files and create content files as desired.