from collections import OrderedDict
from oioioi.base.models import UserPreferences
# Huge thanks to: http://jacobian.org/writing/dynamic-form-generation/
[docs]class PreferencesFactory(object):
"""Since each app might want to add new options for the user to edit in his
preferences, this class was created - it allows for adding new fields to
the form and requesting callback when the form will have been completed
Usage:
PreferencesFactory.add_field(
"Dog",
CharField,
lambda name, user: 'Spot',
max_length=20
)
form = PreferencesFactory().create_form(UserForm, user, allow_login_change=False)
"""
[docs] _additional_fields = []
@staticmethod
[docs] def add_field(
field_name, field_type, initial_value_callback, order=0, *args, **kwargs
):
"""When the user will want to edit preferences there will be additional
field listed, as if it was specified in the form:
class OurForm(Forms.form):
field_name = field_type(*args, **kwargs)
Order is an int that will be used to sort additional fields in
ordered dict, set to 0 if you don't care
When instating the form, initial_value_callback will be called
with the field_name and user parameters
initial_value_callback(field_name, user), it should return a value
that can be put in field_type, this is what the user will see when
opens his preferences, preferably some saved info from before.
To actually get the results you should use the PreferencesSaved
signal from models (and to validate use the field validators, fool)
Keep in mind that adding fields that already exist is an
undefined behavior.
"""
PreferencesFactory._additional_fields.append(
{
'name': field_name,
'type': field_type,
'order': order,
'callback': initial_value_callback,
'args': args,
'kwargs': kwargs,
}
)
@staticmethod
[docs] def remove_field(field_name):
"""Removes field with given name."""
for field in PreferencesFactory._additional_fields[:]:
if field['name'] == field_name:
PreferencesFactory._additional_fields.remove(field)
[docs]def ensure_preferences_exist_for_user(user):
if not hasattr(user, "userpreferences"):
UserPreferences.objects.get_or_create(user=user)