django-fobi/src/fobi/dynamic.py
Artur Barseghyan 012c5b3835 merge
2015-12-16 03:24:45 +01:00

95 lines
3.7 KiB
Python

__title__ = 'fobi.dynamic'
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
__copyright__ = '2014-2015 Artur Barseghyan'
__license__ = 'GPL 2.0/LGPL 2.1'
__all__ = ('assemble_form_class',)
#import logging
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
if DJANGO_GTE_1_7:
from collections import OrderedDict
else:
from django.utils.datastructures import SortedDict as OrderedDict
#logger = logging.getLogger(__file__)
# ****************************************************************************
# ****************************************************************************
# **************************** 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):
"""
Assembles 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):
"""
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):
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