# Imports
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
import os
from superdjango.utils import camelcase_to_underscore
from .library import FieldGroup
# Exports
__all__ = (
"get_field_template",
"get_field_type",
"get_html_framework",
"get_html_path",
"get_input_type",
"is_required_field",
"HTMLFramework",
)
# Functions
[docs]def get_field_template(instance):
"""Get the template to use for a given field instance.
:param instance: The field instance to be checked.
:type instance: BaseType[Field]
:rtype: str
"""
from .shortcuts import template_exists
field_type = camelcase_to_underscore(get_field_type(instance)).replace("_field", "")
input_type = camelcase_to_underscore(get_input_type(instance)).replace("_widget", "")
# textarea simply becomes text.
if input_type == "textarea":
input_type = "text"
# In some cases, the input type (based on the widget) indicates the field template that should be used. This allows
# the wrapper templates in html/forms/fields to do their job, but should also make it possible to specify a custom
# template.
template = "html/forms/fields/%s.html" % input_type
if template_exists(template):
# print("%s(field_type=%s, input_type=%s, template=%s)" % (instance.name, field_type, input_type, template))
return template
# Deal with special Django fields.
if field_type == "username":
return "html/forms/fields/char.html"
# In remaining cases, we attempt to use the field type.
template = "html/forms/fields/%s.html" % field_type
if template_exists(template):
# print("%s(field_type=%s, input_type=%s, template=%s)" % (instance.name, field_type, input_type, template))
return template
# print("%s(field_type=%s, input_type=%s)" % (instance.name, field_type, input_type))
return "html/forms/fields/char.html"
# if field_type == "username":
# return "html/forms/"
# field_type = get_field_type(instance).replace("Field", "").lower()
# input_type = get_input_type(instance).lower()
#
# if field_type == "char":
# if input_type == "codeeditorwidget":
# file = "code_editor.html"
# elif input_type == "markdownwidget":
# file = "markdown.html"
# elif input_type == "textarea":
# file = "text.html"
# else:
# file = "char.html"
# elif field_type == "username":
# # This is the UsernameField in Django's standard AuthenticationForm.
# file = "char.html"
# else:
# if input_type == "chooserwidget":
# file = "chooser.html"
# else:
# file = "%s.html" % field_type
#
# # print("%s:" % instance.name, get_field_type(instance), field_type, input_type, file)
#
# return "html/forms/fields/%s" % file
# widget = instance.field.widget.__class__.__name__
# file = camelcase_to_underscore(widget).replace("_", "-") + ".html"
#
# return "html/forms/fields/%s" % file
[docs]def get_field_type(instance):
"""Get the type of field for a given instance.
:param instance: The field instance to be checked.
:type instance: Type[Field]
:rtype: str
"""
return instance.field.__class__.__name__
# return instance.field.__class__.__name__.replace("Field", "").lower()
[docs]def get_html_framework():
"""Get the framework to use for rendering standard HTM Gel templates.
:rtype: str
:raise: ImproperlyConfigured
"""
if HTMLFramework.is_bootstrap():
return "bootstrap4"
elif HTMLFramework.is_foundation():
return "foundation6"
elif HTMLFramework.is_uikit():
return "uikit3"
elif hasattr(settings, "HTML_FRAMEWORK"):
return settings.HTML_FRAMEWORK
else:
raise ImproperlyConfigured("The SuperDjango HTML framework has not been defined.")
[docs]def get_html_path(prefix="html"):
"""Get the path to standard HTM Gel templates.
:param prefix: The prefix or starting point of the path. This may be given as ``["superdjango", "ui"]`` or
``["superdjango", "views"]`` or a custom prefix to use templates that you've created.
:type prefix: list | str | tuple
:rtype: str
:raise: ImproperlyConfigured
"""
if type(prefix) is str:
prefix = [prefix]
return os.path.join(*prefix, "_frameworks", get_html_framework())
[docs]def is_required_field(instance):
"""Determine if the given field is required.
:param instance: The field instance to be checked.
:type instance: Type[Field]
:rtype: bool
"""
try:
return instance.field.required
except AttributeError:
pass
try:
return instance.required
except AttributeError:
pass
return False
# Classes
[docs]class HTMLFramework(object):
"""A utility class which encapsulates functionality for identifying the current HTML framework."""
[docs] @classmethod
def is_bootstrap(cls):
"""Indicates the use of Twitter Bootstrap.
:rtype: bool
"""
return "superdjango.html.frameworks.bootstrap4" in settings.INSTALLED_APPS
[docs] @classmethod
def is_foundation(cls):
"""Indicates the use of Twitter Bootstrap.
:rtype: bool
"""
return "superdjango.html.frameworks.foundation6" in settings.INSTALLED_APPS
[docs] @classmethod
def is_uikit(cls):
"""Indicates the use of Twitter Bootstrap.
:rtype: bool
"""
return "superdjango.html.frameworks.uikit3" in settings.INSTALLED_APPS
[docs] @classmethod
def get_path(cls, *parts, prefix="html"):
"""As with ``path()``, but joins the given parts relative to the path of the HTML framework."""
base = cls.path(prefix=prefix)
return os.path.join(base, *parts)
[docs] @classmethod
def path(cls, prefix="html"):
"""Get the path to the framework. See :py:func:`get_html_path`."""
return get_html_path(prefix=prefix)