from django.newforms import * from django.newforms.widgets import flatatt def form_decorator(fields = {}, attrs = {}, widgets = {}, labels = {}, choices = {}): """ This function helps to add overrides when creating forms from models/instances. Pass in dictionary of fields to override certain fields altogether, otherwise add widgets or labels as desired. For example: class Project(models.Model): name = models.CharField(maxlength = 100) description = models.TextField() owner = models.ForeignKey(User) project_fields = dict( owner = None ) project_widgets = dict( name = forms.TextInput({"size":40}), description = forms.Textarea({"rows":5, "cols":40})) project_labels = dict( name = "Enter your project name here" ) callback = form_decorator(project_fields, project_widgets, project_labels) project_form = forms.form_for_model(Project, formfield_callback = callback) This saves having to redefine whole fields for example just to change a widget setting or label. """ def formfields_callback(f, **kw): if f.name in fields: # replace field altogether field = fields[f.name] f.initial = kw.pop("initial", None) return field if f.name in widgets: kw["widget"] = widgets[f.name] if f.name in attrs: widget = kw.pop("widget", f.formfield().widget) if widget : widget.attrs.update(attrs[f.name]) kw["widget"] = widget if f.name in labels: kw["label"] = labels[f.name] if f.name in choices: choice_set = choices[f.name] if callable(choice_set) : choice_set = choice_set() kw["choices"] = choice_set return f.formfield(**kw) return formfields_callback class ChainSelectWidget(Widget): #This widget uses javascript to build Chain Selects to #narrow down ForeignKey object types in an intuitive manner. #It is especially useful when the __str__ of the object direct foreign #key isn't necessarily unique, and the parent model of it needs #to be looked at. #This code uses the Chained Select javascript written by #Xin Yang (http://www.yxscripts.com/) #This widget must be used on custom views. I had a VERY hard time #trying to get it registered into the form_for_model and #form_for_instance helper functions. #example: ###models.py### #class A(models.Model): # name=models.CharField() #class B(models.Model): # name=models.CharField() # to_A = models.ForeignKey(A) #class C(models.Model): # name=models.CharField() # to_B = models.ForeignKey(B) ###views.py### #def test(request): # import A,B,C # from CustomWidgets import * # from django.newforms import form_for_model # from django.shortcuts import render_to_response # widget_overwrite=dict(to_B=ChainSelectWidget(order=[(A, 'name'), (B, 'name'), (C, 'name')])) # callback=form_decorator(widgets=widget_overwrite) # modified_form=form_for_model(C, formfield_callback=callback)() # return render_to_response('path/to/template.html', {'form': modified_form}) ###template.html### #... #
# # #... #