"""
Mix-ins for building your own views.
"""
import os
from django.contrib import messages
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
from django.db import models
from django.shortcuts import redirect
from django.views.generic import base as generic
from pytoolbox import module
from pytoolbox.django.core import exceptions
from pytoolbox.django.forms import mixins as forms_mixins
from pytoolbox.django.models import utils
_all = module.All(globals())
[docs]class BaseModelMultipleMixin(object):
[docs] def get_context_object_name(self, instance_list):
"""Get the name of the item to be used in the context."""
if self.context_object_name:
return self.context_object_name
elif hasattr(instance_list, 'model'):
return f'{utils.get_base_model(instance_list.model)._meta.model_name}_list'
[docs]class BaseModelSingleMixin(object):
[docs] def get_context_object_name(self, instance):
"""Get the name to use for the instance."""
if self.context_object_name:
return self.context_object_name
elif isinstance(instance, models.Model):
return utils.get_base_model(instance)._meta.model_name
[docs]class InitialMixin(object):
"""Add helpers to safely use the URL query string to fill a form with initial values."""
initials = {}
[docs] def get_initial(self):
initial = super().get_initial()
for name, default in self.initials.items():
self.set_inital(initial, name, default)
return initial
[docs] def set_inital(self, initial, name, default):
initial[name] = value = self.request.GET.get(name, default)
return value
[docs] def set_initial_from_func(self, initial, name, default, func, msg_value, mgs_missing):
value = self.request.GET.get(name, default)
if value is not default:
try:
value = func(value)
except ValueError:
messages.error(self.request, f'{name} - {msg_value}.')
return None
except KeyError:
messages.error(self.request, f'{name} - {mgs_missing}.')
return None
initial[name] = value
return value
[docs] def set_initial_from_model(self, initial, name, default, model, msg_value, mgs_missing):
value = self.request.GET.get(name, default)
if value is not default:
try:
value = model.objects.for_user(self.request.user).get(pk=value)
except ValueError:
messages.error(self.request, f'{name} - {msg_value}.')
return None
except model.DoesNotExist:
messages.error(self.request, f'{name} - {mgs_missing}.')
return None
initial[name] = value
return value
[docs]class LoggedCookieMixin(object):
"""Add a "logged" cookie set to "True" if user is authenticated else to "False"."""
[docs] def post(self, *args, **kwargs):
response = super().post(*args, **kwargs)
logged = self.request.user.is_authenticated
response.set_cookie('logged', logged if isinstance(logged, bool) else logged())
return response
[docs]class RedirectMixin(object):
"""Redirect to a page."""
redirect_view = None
[docs] def dispatch(self, request, *args, **kwargs):
if self.redirect_view:
return redirect(self.redirect_view)
return super().dispatch(request, *args, **kwargs)
[docs]class TemplateResponseMixin(generic.TemplateResponseMixin):
default_template_directory = 'default'
[docs] def get_template_names(self):
return [self.template_name] if self.template_name else [
os.path.join(self.template_directory, self.action + '.html'),
os.path.join(self.default_template_directory, self.action + '.html')
]
[docs]class ValidationErrorsMixin(object):
def _handle_unknown_error(self, form, error):
form.add_error(NON_FIELD_ERRORS, error)
__all__ = _all.diff(globals())