ox.core

Core application libraries.

ox.core.apps

Oxylus application inherits from AppConfig. It allows to:

  • handle assets;

  • provide application metadata;

  • application level permission;

We plan to use those metadata and dependencies in order to automate loading and ease application installation by end-users.

class ox.core.apps.AppConfig(*args, **kwargs)[source]

Base AppConfig application to use for Oxylus applications.

It provides extra features as:

  • assets managements (Assets);

  • custom root url for the whole application (see ox.urls)

  • default icon (as MDI specifier)

It is planned later to handle app dependencies.

assets: Assets = <ox.assets.base.Assets object>

The assets use by the application. It will be used at two places:

  • building and managing assets, through ./manage.py assets;

  • rendering scripts and stylesheets includes into templates

Note: there is no need to provide an extra Asset specifying the application to be compiled, since it is what the Assets class does.

dependencies: list[Type[AppConfig]] | None = None

List of required dependencies for this application.

icon: str = 'mdi-home'

Material design icon class.

npm_package: str | None = None

Name of the corresponding NPM package to look up for.

Defaults to app label.

root_url: str = ''

Provide an alternative to app label when we target application in paths.

For example Oxylus will nest template directories as ox/core/ instead of ox_core. The same happens for urls.

class ox.core.apps.AppMeta[source]
dependencies: tuple[str] = ()

Application dependencies, as a tuple of:

  • AppConfig_name: related app config

  • TODO: (AppConfig_name, “version”): where `version is matched agains’t “^” operator.

description: str = ''

Describe application here.

Default will be fetched from metadatas.

extra_metadata: dict[str, str] | None = None

Application metadata.

If not provided, fetch those information based on root module of the package (using importlib.metadatay).

property package_metadata[source]

Return metadata read from package.

permission: str = ''

Permission to access application.

class ox.core.apps.CoreAppConfig(*args, **kwargs)[source]
icon: str = 'mdi-weather-sunny'

Material design icon class.

npm_package: str | None = '@oxylus/core'

Name of the corresponding NPM package to look up for.

Defaults to app label.

ready()[source]

Override this method in subclasses to run code when Django starts.

root_url: str = 'ox/core'

Provide an alternative to app label when we target application in paths.

For example Oxylus will nest template directories as ox/core/ instead of ox_core. The same happens for urls.

ox.core.exceptions

ox.core.exceptions.exception_handler(exc, context)[source]

Handle django exceptions…

ox.core.models

class ox.core.models.InheritanceQuerySet(*args, **kwargs)[source]

This is utility QuerySet subclass for Model, inheriting from model_utils.InheritanceQuerySet.

class ox.core.models.Model(*args, **kwargs)[source]

Model class used by Oxylus applications. It provides:

  • public uuid: reducing bruteforcing database row index;

  • url reverse;

Using uuid as a public identifier is preferred over directly exposing database primary key.

get_absolute_url()[source]

Return model detail url.

get_api_url(action='detail')[source]

Return model api url.

Return type:

str

get_list_url()[source]

Return model list url.

Return type:

str

classmethod reverse_url(action, namespace='', **kwargs)[source]

Reverse an url for the provided action.

Return type:

str

Parameters:
  • action (str) – name of the action (eg. detail, update);

  • namespace (str) – if provided insert namespace after application namespace;

  • **kwargs

    passed down to reverse

:return reversed url as string.

class ox.core.models.QuerySet(model=None, query=None, using=None, hints=None)[source]
uuid(value)[source]

Filter by uuid.

ox.core.panels

This module provide application’s panels description.

This is used to generate main navigation menu and application view’s panels.

Panels are logically organised using the following structure:

  • A Panel inside a group of Panels;

  • A Panels can be nested (once) in another one (eg. “Settings” regroup multiple settings applications);

Panels are defined in applications’ module panels.py in order to separate concerns with the views. However they are not discovered automatically, but by importing the module into the view (in order to assign panels).

Panel and panels are registered through the global object registry.

Application template

An AppView have panels assigned to a Panels instance. This is used to generate components inside the template using provided Panel.component (aka Vue component), and Panel.template, actions_template (used for extensibility).

Example

By convention the navigation items are registered inside panels.py module, such as:

from ox.core.panels import registry, Panel, Panels

panels = Panels("contacts", _("Contacts"), items=[
        Panel("persons", _("Persons"), "mdi-card-account-mail",
            url="ox_contacts:index",
            order=0,
            permission="ox_contacts.view_person",
        ),
        # ...
        Panels("settings", _("Settings"),
            order=100,
            items=[
                Panel("organisationtypes", _("Organisation Types"), "mdi-domain-switch",
                    url="ox_contacts:index",
                    permission="ox_contacts.view_organisationtype",
                )
            ],
        ),
    ])
)
registry.append(panels)

# use this to append to an already registered group:
# registry["settings"].append(panels)
class ox.core.panels.Panel(name, title, icon='', component='', **kwargs)[source]

Describe a panel component and its navigation.

component: str = ''

Vue component.

get_panels()[source]

For interface purpose, return iterator over self.

serialize(**kwargs)[source]

Return navigation data.

template = 'ox/core/components/model_panel.html'

Django template file used to render the panel

type: str = 'item'

Menu item type: group, subheader, item.

Use by frontend OxNavItem.

url: str = None

Url name to app view. It MUST always be namespaced under app’s name.

class ox.core.panels.Panels(name, title, items=None, **kwargs)[source]

Regroup multiple panels, usually of an application.

This also can be used in a more UX sense of the term, such as “Settings” would regroup different nested application Panels.

serialize(**kwargs)[source]

Return navigation data.

type: str = 'group'

Menu item type: group, subheader, item.

Use by frontend OxNavItem.

class ox.core.panels.Registry(items=None)[source]

Register all applications’ panels.

The following registry methods reset the cached property nav_data(): append(), __getitem__(), __setitem__(). Those are the public methods used to update the registry, whilst nav_data is used to provide navigation data to the user and is cached for performance.

append(item)[source]

Add new item to group.

Parameters:
  • item – item

  • path – dot separated path to parent group

Returns:

the appended item

property nav_data: list[dict[str, Any]][source]

Menu data as provided to frontend application.

ox.core.panels.registry = <ox.core.panels.Registry object>

Registry of all applications’ panels.

ox.core.renderers

class ox.core.renderers.AdminBrowsableAPIRenderer[source]

This class is used for browsable API views in order to deny access to non staff users.

get_context(*args, **kwargs)[source]

Returns the context used to render.

ox.core.signals

ox.core.signals.create_app_groups(sender, app_config, *args, **kwargs)[source]

This creates users groups for applications.

ox.core.serializers

class ox.core.serializers.ModelSerializer(*args, **kwargs)[source]

This ModelSerializer provides id field defaulted to model’s uuid.

class ox.core.serializers.NestedSerializer(*args, **kwargs)[source]

This serializer class allows to specify and save relations using nested serializer values.

Default behavior implies that existing values will be updated, new ones created and removed one deleted. You can customize by provided argument for the NestedInfo specific to a field.

The attribute Meta.nested is used to specify which fields are actually related models. Its value is a list of:

  • a string that is NestedInfo.field (serializer field name);

  • tuple with positional argument, dict with positional arguments;

  • a NestedInfo instance;

Limitations: - It only works with models having a uuid field used as reference. - It assumes a FK reverse relations.

Example: two models, A and B. B has ForeignKey to A, and on A’s serializer you want to update B objects related to A. You don’t want uuid as handled by RelatedField).

class BSerializer(ModelSerializer):
    # ...

class ASerializer(ModelSerializer):
    b_items = BSerializer(source="b_set", many=True, required=False)

    class Meta:
        # Declaring fields as nested allows them to be automatically
        # create/updated.
        nested = ("b_items",)
        # ...
        #
        # If you dont want deletion of missing items, you can use this:
        # nested = (("b_items", False),)

At the serializer class creation, Meta.nested is transformed into a dict of NestedInfo by serializer field name.

create(validated_data)[source]

We have a bit of extra checking around this in order to provide descriptive messages when something goes wrong, but this method is essentially just:

return ExampleModel.objects.create(**validated_data)

If there are many to many fields present on the instance then they cannot be set until the model is instantiated, in which case the implementation is like so:

example_relationship = validated_data.pop(‘example_relationship’) instance = ExampleModel.objects.create(**validated_data) instance.example_relationship = example_relationship return instance

The default implementation also does not handle nested relationships. If you want to support writable nested relationships you’ll need to write an explicit .create() method.

class ox.core.serializers.RelatedField(*args, **kwargs)[source]

Provide related field based on uuid.

ox.core.templatetags

ox.core.templatetags.ox

ox.core.templatetags.ox.do_json(value)[source]

Dumps value as json string.

Return type:

str

ox.core.templatetags.ox.do_startswith(text, search)[source]

Return True when provided text start with search.

Return type:

bool

ox.core.templatetags.ox.panel_url(urlname, panel, view=None, id=None)[source]

Return url to this panel.

Parameters:
  • urlname (str) – url name

  • panel (str) – panel name

  • view (str | None) – target view

  • id (str | int | None) – target object id

Return type:

str

ox.core.views

ox.core.views.accounts

class ox.core.views.accounts.AccountView(**kwargs)[source]
app_config_name: str | None = 'ox_core'

AppConfig name of the related application.

If none provided, retrieve it based of request’s resolver match.

title: str = 'My Account'

Application title (as displayed in <title> and top bar).

class ox.core.views.accounts.AccountViewSet(**kwargs)[source]
credentials_serializer_class

alias of PasswordLoginSerializer

serializer_class

alias of UserSerializer

class ox.core.views.accounts.LoginView(**kwargs)[source]
app_config_name: str | None = 'ox_core'

AppConfig name of the related application.

If none provided, retrieve it based of request’s resolver match.

ox.core.views.api

class ox.core.views.api.ListCommitMixin[source]

Viewset mixin providing commit action, which allows to update many items at once (create, update, delete).

commit(request)[source]

Request:

{
    "delete": [pk],
    "update": [{pk, **object}],
    "create": [object_data]
}

Response:

{
    "deleted": [pk],
    "updated": [object],
    "created": [object],
}
class ox.core.views.api.ModelViewSet(**kwargs)[source]

Base model viewset use by Oxylus application.

Lookup objects by uuid.

ox.core.views.auth

class ox.core.views.auth.ContentTypeViewSet(**kwargs)[source]
serializer_class

alias of ContentTypeSerializer

class ox.core.views.auth.GroupViewSet(**kwargs)[source]
serializer_class

alias of GroupSerializer

class ox.core.views.auth.PermissionViewSet(**kwargs)[source]
serializer_class

alias of PermissionSerializer

class ox.core.views.auth.UserViewSet(**kwargs)[source]
serializer_class

alias of UserSerializer

ox.core.views.core

class ox.core.views.core.ErrorView(**kwargs)[source]
title: str = 'An error occurred'

Application title (as displayed in <title> and top bar).