Ok, I apologize. Here is a fuller representation of what I'm doing. I had a 
hard time figuring out how much was enough versus too much. This is 
simplified, but I think it represents what I'm trying to do. For instance, 
don't pay too much attention to the save logic in the view, I haven't 
actually really worked on it much yet.

To restate my scenario, I want to carry information in hidden fields of a 
form that determine how the form is displayed and functions. I realize I do 
have access to the self.Initial values in the form itself but I don't think 
that there's easy access to those values in the template. The value that I 
want seems to be the value() method of the BoundField, but run through the 
to_python() method of the field. I actually solved this by adding a 
to_python() method to the BoundField that does just this, but I would like 
to solve this without modifying the Django code. The samples below do not 
reflect my added to_python() method.

# Form class (I use the self["multiLineInfo"] pattern instead of 
self.fields["multiLineInfo"] 
# because the former gives a BoundField which merges the Field and the 
post/initial data)
class OrganizationItemForm(ModelForm):
    selected      = forms.BooleanField(required=False)  
    extraRequired = forms.BooleanField(required=False, 
        widget=forms.HiddenInput)
    multiLineInfo = forms.BooleanField(required=False, 
        widget=forms.HiddenInput)
    
    def __init__(self, *args, **kwargs):
        super(AuditModelForm, self).__init__(*args, **kwargs)
        if self["multiLineInfo"].value():
            self.fields["descr"].widget = 
forms.Textarea(attrs={"class":"descriptionEdit"})
        else:
            self.fields["descr"].widget = 
forms.TextInput(attrs={"class":"itemDescrEdit"})     
        self.fields["descr"].required = self["extraRequired"].value() and 
self["selected"].value()
        
    class Meta:
        model = OrganizationItem

# Model classes

class OrganizationItem(models.Model):
    organization = models.ForeignKey(Organization)
    item       = models.ForeignKey(ListItem)
    descr      = models.TextField("Description", blank=True)

class ListItem(models.Model):
    category = models.ForeignKey(ListCategory)
    name     = models.CharField("Name", max_length=200)
    order    = models.IntegerField("Order")
    extraInfo     = models.BooleanField("Requires extra information")
    multiLineInfo = models.BooleanField("The display should use a multi-line 
edit box instead of a single line edit")
    descrLabel    = models.CharField("Extra information label", 
max_length=50,
        blank=True)

class ListCategory(modelUtils.MyModelAudit):
    catId = models.CharField("Category identifier", max_length=15,
        primary_key=True)
    name  = models.CharField("Name", max_length=100)
    order = models.IntegerField("Order")
    group = models.ForeignKey(ListGroup)
    organization = models.BooleanField("Should this be associated with an 
organization?")
    twoColumn    = models.BooleanField("Should the current list span 2 
columns?")

class ListGroup(modelUtils.MyModelAudit):
    name = models.CharField("Name", max_length=15)
    descr = models.CharField("Description", max_length=100, blank=True)
    order = models.IntegerField("Order")

# View example
def organizationAdd(request):

    OrganizationItemFormSet = formset_factory(OrganizationItemForm)
    
    if request.method == 'POST':
        orgItemFormSet = OrganizationItemFormSet(request.POST)    
        orgItemFormSetIsValid = orgItemFormSet.is_valid()
        if orgItemFormSetIsValid:
            orgItemFormSet.save(commit=False)
    else:
        orgItemFormSet = OrganizationItemFormSet() 
        listItems = CreateItemsSection(orgItemFormSet, "organization", 
category__organization=True)

    context = {
        'listItems': listItems, 
        'listItemsManagementForm': orgItemFormSet.management_form}
    
    return render_to_response('organizationEdit.html', context,
            context_instance=RequestContext(request))


def CreateItemsSection(formset, idField="", objId=None, relation=None, 
**kwargs):
    """Construct the list of selectable items"""

    qs = ListItem.objects.filter(**kwargs)
    
    # Get the appliable list of groups
    groups = qs.values(
        "category__group", "category__group__descr"
        ).order_by(
        "category__group__order"
        ).distinct()
    
    # Convert the items relation into a dictionary of ListItem PK and 
XItems.descr
    selectedData = {}
    if relation is not None:
        selectedData = dict([(item.item__id, item.descr) for item in 
relation])
    
    retVal = []
    
    # Track the current form to display when the formset is populated from a 
postback
    formIndex = 0;
    postedData = len(formset) > 0
    
    # Assemble the information for each category group
    for grp in groups:
        # The current group's description
        curGrpDescr = grp["category__group__descr"]
        # Initialize the current group entry with a name and a list for the
        # category entries
        curGrp = {"group": curGrpDescr, "categories": []}
        # Get the applicable list of catagories
        categories = 
qs.filter(category__group=grp["category__group"]).values(
            "category", "category__name", 
"category__twoColumn").order_by("category__order").distinct()
        
        # These are used to determine when to start and end the table rows
        startRow = True
        endRow = False 
        
        # Assemble the category information
        for cat in categories:
            # The current category description (name field)
            curCatDescr = cat["category__name"] 
            # Get the current category's items
            listItems = 
qs.filter(category=cat["category"]).order_by("order")
            # Should the category display span 2 columns
            twoColumn = cat["category__twoColumn"]
            
            # Build the checkboxes, each contains a formset form
            items = []
            for li in listItems:
                    
                if postedData:
                    form = formset.forms[formIndex]                
                    formIndex += 1
                else:   
                    # Check if the item is selected items
                    isSelected = selectedData.has_key(li.pk)
                    data = ""
                    if isSelected:
                        data = selectedData[li.pk]
                    initialData = {
                        'selected': isSelected,
                        idField: objId,
                        'item': li.pk, 
                        'descr': data,
                        'extraRequired': li.extraInfo,
                        'multiLineInfo': li.multiLineInfo}
                    form = formset.add_form(initial=initialData)
    
                items.append({
                    'label': li.name, 
                    'descrLabel': li.descrLabel,
                    'category': cat["category"],
                    'order': li.order,
                    'form': form})
            
            # If the category should span 2 columns, ensure the last 
category
            # ends it's row and the current category both starts and ends 
this row
            if twoColumn:
                lastCatIndex = len(curGrp["categories"]) - 1
                if lastCatIndex > -1:
                    curGrp["categories"][lastCatIndex]["endRow"] = True
                
                startRow = True
                endRow = True
            
            # Append to the current group's list of categories
            curCat = {
                "category": curCatDescr, 
                "items": items,
                "startRow": startRow,
                "endRow": endRow,
                "twoColumn": twoColumn}
            curGrp["categories"].append(curCat)
            
            # Set the default row managment for the next category
            if not twoColumn:
                startRow = not startRow
                endRow = not endRow
            else:
                startRow = True
                endRow = False
            
        # Append the group to the return list
        retVal.append(curGrp)

    return retVal

# My custom formset for adding arbitrary forms to the set (I included this 
# because I didn't think that the CreateItemsSection function the save 
method 
# in the view would make sense without it.)
class XManagementForm(forms.formsets.ManagementForm):
    """
    ``ManagementForm`` is used to keep track of how many form instances
    are displayed on the page. If adding new forms via javascript, you 
should
    increment the count field of this form as well.
    """
    def __init__(self, data=None, extra_fields=None, *args, **kwargs):
        if extra_fields:
            for f, tv in extra_fields.items():
                self.base_fields[f] = tv[0](widget=forms.HiddenInput)
                if kwargs.has_key('initial'):
                    kwargs['initial'][f] = tv[1]
        super(XManagementForm, self).__init__(data, *args, **kwargs)


class BaseXFormSet(forms.formsets.BaseFormSet):

    def __init__(self, *args, **kwargs):
        self.added_forms = 0
        super(BaseXFormSet, self).__init__(*args, **kwargs)

    def _management_form(self):
        """Returns the ManagementForm instance for this FormSet."""
        if self.data or self.files:
            form = XManagementForm(self.data, auto_id=self.auto_id, 
prefix=self.prefix,
                extra_fields=self.extra_fields)
            #import pdb; pdb.set_trace()
            if not form.is_valid():
                raise forms.ValidationError('ManagementForm data is missing 
or has been tampered with')
        else:
            form = XManagementForm(auto_id=self.auto_id, prefix=self.prefix, 
extra_fields=self.extra_fields,
                initial={
                    forms.formsets.TOTAL_FORM_COUNT: 
self.total_form_count(),
                    forms.formsets.INITIAL_FORM_COUNT: 
self.initial_form_count()
            })
        return form
    management_form = property(_management_form)

    def initial_form_count(self):
        """Returns the number of forms that are required/pre-populated in 
this FormSet."""
        if not (self.data or self.files):
            initial_forms = self.initial and len(self.initial) or 0
            initial_forms += self.added_forms
            if initial_forms > self.max_num > 0:
                initial_forms = self.max_num
            return initial_forms
        return super(BaseXFormSet, self).initial_form_count()

    def add_form(self, existing_form=None, **kwargs):
        self.added_forms = self.added_forms + 1
        l_curIdx = len(self.forms)
        if existing_form:
            l_new_form = existing_form
            l_new_form.prefix = self.add_prefix(l_curIdx)
        else:
            l_new_form = self._construct_form(l_curIdx, **kwargs)
        l_new_form.form_index = l_curIdx
        self.forms.append(l_new_form)
        return l_new_form
        
    def save(self, commit=True):
        if hasattr(self.form, "save") and callable(self.form.save):
            for frm in self.forms:
                frm.save(commit=commit)
        else:
            raise NotImplementedError('The form %s does not implement the 
save() method' % self.form.__class__.__name__)
            

def formset_factory(form, formset=BaseXFormSet, extra=0, can_order=False,
                    can_delete=False, max_num=0, extra_fields=None):
    """Return a FormSet for the given form class."""
    attrs = {'form': form, 'extra': extra,
             'can_order': can_order, 'can_delete': can_delete,
             'max_num': max_num, 'extra_fields': extra_fields}
    return type(form.__name__ + 'FormSet', (formset,), attrs)


# Template

{{ listItemsManagementForm }}
{% for group in listItems %}
    {% for cat in group.categories %}
        {% if cat.startRow %}<tr>{% endif %}
        <td{% if cat.twoColumn %} colspan="2" {% endif %}>
        {{ cat.category }}<br>
        <ul>
        {% for item in cat.items %}            
            <li{% if item.form.descr.errors %} class="errors" {% endif %}>
            {{ item.form.descr.errors }}{% if item.form.descr.errors 
%}<br>{% endif %}
            <label>{{ item.form.selected }} {{ item.label }}</label>
            {% if item.form.extraRequired.value or item.descrLabel %}
                {% if item.form.multiLineInfo.value %}
                    <br>
                {% else %}
                    &ndash;
                {% endif %}
                <span class="listItemLabel{% if 
item.form.extraRequired.value %} required{% endif %}">{{ item.descrLabel 
}}</span>
                {% if item.form.multiLineInfo.value %}
                    <br>
                {% else %}
                    &nbsp;
                {% endif %}
                {{ item.form.descr }}
            {% else %}
                {{ item.form.descr.as_hidden }}
            {% endif %}
            {{ item.form.extraRequired }}
            {{ item.form.multiLineInfo }}
            </li>
        {% endfor %}
        </ul>
        </td>
        {% if cat.endRow %}</tr>{% endif %}
    {% endfor %}
{% endfor %}

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-users/-/FDyaPWVmBicJ.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to