mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-05-11 06:13:10 +00:00
95 lines
3.7 KiB
Python
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
|