Source code for ox.core.views

from typing import Any

from django.apps import apps
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import ImproperlyConfigured
from django.views.generic.base import ContextMixin, TemplateView
from django.utils.translation import gettext as __, get_language

from rest_framework import permissions, viewsets

# FIXME: circular dependencies among apps
from ox.apps.core.serializers import UserSerializer, GroupSerializer
from ox.core.assets import Assets
from .panels import Panels, registry

__all__ = ("AppMixin", "UserAuthMixin", "AppView", "UserAppView")


[docs] class AppMixin(ContextMixin): """Base mixin for applications.""" title: str = "" """Application title (as displayed in ``<title>`` and top bar).""" app_config_name: str | None = None """AppConfig name of the related application. If none provided, retrieve it based of request's resolver match. """ default_panel: str = "" """Default panel to display.""" panels: Panels = None """Application's panels descriptors.""" assets: Assets = None """Use theses assets instead of app config's one. """ def get_context_data(self, **kwargs): kwargs["app_config"] = self.get_app_config() kwargs["app_data"] = self.get_app_data() kwargs["panels"] = self.panels kwargs["assets"] = self.get_assets() kwargs.setdefault("title", self.title) return super().get_context_data(**kwargs)
[docs] def get_app_config(self): """Return application config. Set to request resolved match application name by default. """ app_name = self.app_config_name or self.request.resolver_match.app_name self.app_config = apps.get_app_config(app_name) return self.app_config
[docs] def get_app_data(self, **kwargs): """Return application data to pass down to js application.""" if current := self.request.GET.get("panel", self.default_panel): kwargs.setdefault("panel", current) kwargs["nav"] = self.get_app_nav() kwargs["host"] = settings.SITE_URL kwargs["language"] = get_language() kwargs["languages"] = [(k, __(v)) for k, v in settings.LANGUAGES] return kwargs
[docs] def get_app_nav(self) -> dict[str, Any]: """Return application navigation menu.""" return registry.nav_data
[docs] def get_assets(self) -> Assets | None: """ Return assets to use with the view. It retuns assigned :py:attr:`assets` or app config one if any. """ if self.assets: return self.assets return self.app_config and getattr(self.app_config, "assets", None) or None
[docs] class UserAuthMixin: """Provide request's user in Application's initial data, as ``user``.""" user_ser_class = UserSerializer group_ser_class = GroupSerializer def get_app_data(self, **kwargs): if not kwargs.get("user"): kwargs["user"] = self.user_ser_class(self.request.user).data kwargs["groups"] = self.group_ser_class(self.request.user.groups, many=True).data kwargs.setdefault("urls", {}) # urls["user"] = reverse("auth:api:") return super().get_app_data(**kwargs)
[docs] class AppView(UserAuthMixin, AppMixin, TemplateView): """Base view used for ox based applications.""" template_name = "ox/core/app.html"
[docs] def get_template_names(self) -> list[str]: """ By default return a list with: - :py:attr:`template_name` value - ``{self.app_config.root_url}/app.html``, if app_config is found. """ try: names = super().get_template_names() except ImproperlyConfigured: names = [] if hasattr(self, "app_config"): names.append(f"{self.app_config.root_url}/app.html") return names
def get(self, *args, service=None, **kwargs): context = self.get_context_data(**kwargs) return self.render_to_response(context)
[docs] class UserAppView(LoginRequiredMixin, AppView): """Application view requiring user to be authentified.""" pass
class ModelViewSet(viewsets.ModelViewSet): """Base model viewset use by Oxylus application. Lookup objects by uuid. """ permission_classes = [permissions.DjangoModelPermissions] lookup_field = "uuid" filterset_fields = { "uuid": ["exact", "in"], }