mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-05-10 22:03:09 +00:00
92 lines
3.6 KiB
Python
92 lines
3.6 KiB
Python
from six import with_metaclass
|
|
|
|
from django.forms.forms import BaseForm # , get_declared_fields
|
|
from django.forms.widgets import media_property
|
|
|
|
from nine.versions import DJANGO_GTE_1_7
|
|
|
|
__title__ = 'fobi.dynamic'
|
|
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
|
__copyright__ = '2014-2016 Artur Barseghyan'
|
|
__license__ = 'GPL 2.0/LGPL 2.1'
|
|
__all__ = ('assemble_form_class',)
|
|
|
|
|
|
if DJANGO_GTE_1_7:
|
|
from collections import OrderedDict
|
|
else:
|
|
from django.utils.datastructures import SortedDict as OrderedDict
|
|
|
|
# ****************************************************************************
|
|
# ****************************************************************************
|
|
# **************************** Form generator ********************************
|
|
# ****************************************************************************
|
|
# ****************************************************************************
|
|
|
|
|
|
def assemble_form_class(form_entry, base_class=BaseForm, request=None,
|
|
origin=None, origin_kwargs_update_func=None,
|
|
origin_return_func=None, form_element_entries=None):
|
|
"""Assemble a form class by given entry.
|
|
|
|
:param form_entry:
|
|
:param base_class:
|
|
:param django.http.HttpRequest request:
|
|
:param string origin:
|
|
:param callable origin_kwargs_update_func:
|
|
:param callable origin_return_func:
|
|
:param iterable form_element_entries: If given, used instead of
|
|
``form_entry.formelemententry_set.all`` (no additional database hit).
|
|
"""
|
|
if form_element_entries is None:
|
|
form_element_entries = form_entry.formelemententry_set.all()
|
|
|
|
class DeclarativeFieldsMetaclass(type):
|
|
"""Declarative fields meta class.
|
|
|
|
Copied from ``django.forms.forms.DeclarativeFieldsMetaclass``.
|
|
|
|
Metaclass that converts Field attributes to a dictionary called
|
|
`base_fields`, taking into account parent class 'base_fields' as well.
|
|
"""
|
|
def __new__(cls, name, bases, attrs):
|
|
"""New."""
|
|
base_fields = []
|
|
|
|
for creation_counter, form_element_entry \
|
|
in enumerate(form_element_entries):
|
|
plugin = form_element_entry.get_plugin(request=request)
|
|
|
|
# We simply make sure the plugin exists. We don't handle
|
|
# exceptions relate to the non-existent plugins here. They
|
|
# are instead handled in registry.
|
|
if plugin:
|
|
plugin_form_field_instances = \
|
|
plugin._get_form_field_instances(
|
|
form_element_entry=form_element_entry,
|
|
origin=origin,
|
|
kwargs_update_func=origin_kwargs_update_func,
|
|
return_func=origin_return_func,
|
|
extra={'counter': creation_counter},
|
|
request=request
|
|
)
|
|
for form_field_name, form_field_instance \
|
|
in plugin_form_field_instances:
|
|
base_fields.append(
|
|
(form_field_name, form_field_instance)
|
|
)
|
|
|
|
attrs['base_fields'] = OrderedDict(base_fields)
|
|
new_class = super(DeclarativeFieldsMetaclass, cls).__new__(
|
|
cls, name, bases, attrs
|
|
)
|
|
|
|
if 'media' not in attrs:
|
|
new_class.media = media_property(new_class)
|
|
|
|
return new_class
|
|
|
|
class DynamicForm(with_metaclass(DeclarativeFieldsMetaclass, base_class)):
|
|
"""Dynamically created form element plugin class."""
|
|
|
|
return DynamicForm
|