I want to dynamically generate ModelForm's Meta Class widgets according to exercise_type
field from Exercise
class.
How can I get the value?
class ExerciseAdminForm(ModelForm):
class Meta:
model = Exercise
fields = '__all__'
widgets = {
'starter_code': _make_language_mode(exercise_type=Exercise.exercise_type)
}
I don't know how to get the excercise_object.
Basically I need to override the default form in the administration interface, to use CodeMirror and Skulpt support for entry fields.
class ExerciseAdminForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ExerciseAdminForm, self).__init__(*args, **kwargs)
print("DEBUG: len(kwargs)=",len(kwargs))
initial_dict = kwargs['initial']
print("DEBUG: len(initial_dict)=",len(initial_dict))
self.fields['starter_code'].widget = _make_language_mode(exercise_type=excercise_object.exercise_type)
class Meta:
model = Exercise
fields = '__all__'
widgets = {
'preamble': _make_markdown_mode()
}
My debug message shows:
('DEBUG: len(kwargs)=', 1)
('DEBUG: len(initial_dict)=', 0)
My function get called from the Python 2.7 library site-packages:
/root/.virtualenvs/codebench/local/lib/python2.7/site-packages/django/contrib/admin/options.py
At line 1481:
form = ModelForm(initial=initial)
In the changeform_view function:
@csrf_protect_m
@transaction.atomic
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR))
if to_field and not self.to_field_allowed(request, to_field):
raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)
model = self.model
opts = model._meta
add = object_id is None
if add:
if not self.has_add_permission(request):
raise PermissionDenied
obj = None
else:
obj = self.get_object(request, unquote(object_id), to_field)
if not self.has_change_permission(request, obj):
raise PermissionDenied
if obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {
'name': force_text(opts.verbose_name), 'key': escape(object_id)})
if request.method == 'POST' and "_saveasnew" in request.POST:
return self.add_view(request, form_url=reverse('admin:%s_%s_add' % (
opts.app_label, opts.model_name),
current_app=self.admin_site.name))
ModelForm = self.get_form(request, obj)
if request.method == 'POST':
form = ModelForm(request.POST, request.FILES, instance=obj)
if form.is_valid():
form_validated = True
new_object = self.save_form(request, form, change=not add)
else:
form_validated = False
new_object = form.instance
formsets, inline_instances = self._create_formsets(request, new_object, change=not add)
if all_valid(formsets) and form_validated:
self.save_model(request, new_object, form, not add)
self.save_related(request, form, formsets, not add)
if add:
self.log_addition(request, new_object)
return self.response_add(request, new_object)
else:
change_message = self.construct_change_message(request, form, formsets)
self.log_change(request, new_object, change_message)
return self.response_change(request, new_object)
else:
if add:
initial = self.get_changeform_initial_data(request)
form = ModelForm(initial=initial)
formsets, inline_instances = self._create_formsets(request, self.model(), change=False)
else:
form = ModelForm(instance=obj)
formsets, inline_instances = self._create_formsets(request, obj, change=True)
adminForm = helpers.AdminForm(
form,
list(self.get_fieldsets(request, obj)),
self.get_prepopulated_fields(request, obj),
self.get_readonly_fields(request, obj),
model_admin=self)
media = self.media + adminForm.media
inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj)
for inline_formset in inline_formsets:
media = media + inline_formset.media
context = dict(self.admin_site.each_context(request),
title=(_('Add %s') if add else _('Change %s')) % force_text(opts.verbose_name),
adminform=adminForm,
object_id=object_id,
original=obj,
is_popup=(IS_POPUP_VAR in request.POST or
IS_POPUP_VAR in request.GET),
to_field=to_field,
media=media,
inline_admin_formsets=inline_formsets,
errors=helpers.AdminErrorList(form, formsets),
preserved_filters=self.get_preserved_filters(request),
)
context.update(extra_context or {})
return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
Maybe you could override the __init__
function to do this? Pass the exercise instance as a keyword arg to the form. Assuming you pass the exercise object with the form and _make_language_mod
e returns a widget.
def __init__(self, *args, **kwargs):
excercise_object = kwargs["excercise"]
self.fields['starter_code'].widget = _make_language_mode(exercise_type=excercise_object.exercise_type)