Example #1
0
def occurrence_composition_queryset(formset, request, obj):
    release_id = utils_id.get_release_id(request, obj)

    if release_id == 0:
        force_formset_size(formset, 0)
    else:
        release_compositions = retrieve_release_composition(release_id)
        force_formset_size(formset, len(release_compositions))
            ## Does not help with saving the emtpy forms (only with their initial values)...
        #formset.validate_min = True
        #formset.validate_max = True

        # Would not be a safe approach, see comment in populate_occurrence_attributes()
        #formset.initial = [{"release_composition": compo} for compo in release_compositions]

        release_compositions = list(release_compositions)

        for form in formset:
            release_compo, in_db = get_or_initial_release_corresponding_entry(form, release_compositions, "release_composition")

            release = release_compo.to_release
            #form.empty_permitted=False ## Does not help with empty forms either
            form.fields["to_occurrence"].queryset = (
                Occurrence.objects.filter(release=release)  # only propose occurrences of the right release
                                  .filter(Q(occurrence_composition__isnull=True) # not already nested in another occurrence
                                          | Q(occurrence_composition__from_occurrence=formset.instance)) # except if nested in this occurrence (for edit)
            )
            form.fields["to_occurrence"].label = "Nested {} occurrence".format(release.name)
Example #2
0
def populate_occurrence_attributes(formset, request, obj):
    release_id = utils_id.get_release_id(request, obj)
    
    attributes = retrieve_noncustom_custom_release_attributes(release_id)
    force_formset_size(formset, len(attributes))

    # We had to move away from always assigning the initial value for release_corresponding_entry:
    # When "changing" and existing occurrence, if the Occurrence***Attribute are not saved in the same order as the Release***Attribute of the matching Release
    # (side note: this situation is treated as an error by formset clean)
    # the value assigned to initial would override the release_corresponding_entry saved in the DB,
    # but the associated attribute value would still be the one from the DB, causing a mismatch.
    #formset.initial = [{"release_corresponding_entry": attrib} for attrib in attributes]

    # Instead, we create a list of all Release***Attribute assigned to the correponding release, and remove from this list
    # the Release***Attribute which already have a matchin Occurrence***Attribute saved to the DB.
    attribute_list = list(attributes)

    for form in formset:
        rel_attrib, in_db = get_or_initial_release_corresponding_entry(form, attribute_list, "release_corresponding_entry")

        # This is very important: by default, forms in formsets have empty_permitted set to True
        # Then, a form with no other value than the initial(s) would skip fields validation, not populating cleaned_data     
        # see: https://github.com/django/django/blob/1.8.3/django/forms/forms.py#L389
        form.empty_permitted=False 
        form.fields["value"] = enum.Attribute.Type.to_form_field[rel_attrib.attribute.value_type]
        if not in_db:
            form.initial.update({
                "attribute_type": ContentType.objects.get_for_model(rel_attrib.__class__),
                "attribute_id": rel_attrib.pk,
            })
Example #3
0
def populate_occurrence_attributes(formset, request, obj):
    release_id = utils_id.get_release_id(request, obj)

    attributes = retrieve_noncustom_custom_release_attributes(release_id)
    force_formset_size(formset, len(attributes))

    # We had to move away from always assigning the initial value for release_corresponding_entry:
    # When "changing" and existing occurrence, if the Occurrence***Attribute are not saved in the same order as the Release***Attribute of the matching Release
    # (side note: this situation is treated as an error by formset clean)
    # the value assigned to initial would override the release_corresponding_entry saved in the DB,
    # but the associated attribute value would still be the one from the DB, causing a mismatch.
    #formset.initial = [{"release_corresponding_entry": attrib} for attrib in attributes]

    # Instead, we create a list of all Release***Attribute assigned to the correponding release, and remove from this list
    # the Release***Attribute which already have a matchin Occurrence***Attribute saved to the DB.
    attribute_list = list(attributes)

    for form in formset:
        rel_attrib, in_db = get_or_initial_release_corresponding_entry(
            form, attribute_list, "release_corresponding_entry")

        # This is very important: by default, forms in formsets have empty_permitted set to True
        # Then, a form with no other value than the initial(s) would skip fields validation, not populating cleaned_data
        # see: https://github.com/django/django/blob/1.8.3/django/forms/forms.py#L389
        form.empty_permitted = False
        form.fields["value"] = enum.Attribute.Type.to_form_field[
            rel_attrib.attribute.value_type]
        if not in_db:
            form.initial.update({
                "attribute_type":
                ContentType.objects.get_for_model(rel_attrib.__class__),
                "attribute_id":
                rel_attrib.pk,
            })
Example #4
0
def populate_occurrence_picture_attributes_choices(formset, request, obj):
    """
    Populates the any_attribute ChoiceField of OccurrencePictureForm with all attributes (incl. CustomReleaseAttributes) 
    available on the Release of the related occurrence. Also populates its initial data for edition form. 
    """
    release_id = utils_id.get_release_id(request, obj)
    
    choices = [("", "----")]

    attributes = utils.retrieve_noncustom_custom_release_attributes(release_id)
    choices.extend([ ("{}_{}".format(ContentType.objects.get_for_model(attribute.__class__).pk, attribute.pk),
                      "{}".format(attribute),)
                     for attribute in attributes])

    for form in formset:
        form.fields["any_attribute"].choices = choices
        if form.instance.attribute_id:
            form.fields["any_attribute"].initial = "{}_{}".format(form.instance.attribute_type.pk, form.instance.attribute_id)

    def empty_form(self):
        form = super(OccurrencePictureFormSet, self).empty_form
        form.fields["any_attribute"].choices = choices
        return form

    # The empty_formset property is used when clicking the "Add another Occurrence picture" in the web interface
    # "patches" the property by subclassing, as described on SO: http://stackoverflow.com/a/31591589/1027706
    class PatchedFormset(formset.__class__):
        @property
        def empty_form(self):
            form = super(PatchedFormset, self).empty_form
            form.fields["any_attribute"].choices = choices
            return form
    formset.__class__ = PatchedFormset
Example #5
0
def occurrence_composition_queryset(formset, request, obj):
    release_id = utils_id.get_release_id(request, obj)

    if release_id == 0:
        force_formset_size(formset, 0)
    else:
        release_compositions = retrieve_release_composition(release_id)
        force_formset_size(formset, len(release_compositions))
        ## Does not help with saving the emtpy forms (only with their initial values)...
        #formset.validate_min = True
        #formset.validate_max = True

        # Would not be a safe approach, see comment in populate_occurrence_attributes()
        #formset.initial = [{"release_composition": compo} for compo in release_compositions]

        release_compositions = list(release_compositions)

        for form in formset:
            release_compo, in_db = get_or_initial_release_corresponding_entry(
                form, release_compositions, "release_composition")

            release = release_compo.to_release
            #form.empty_permitted=False ## Does not help with empty forms either
            form.fields["to_occurrence"].queryset = (
                Occurrence.objects.filter(
                    release=release
                )  # only propose occurrences of the right release
                .filter(
                    Q(occurrence_composition__isnull=True
                      )  # not already nested in another occurrence
                    |
                    Q(occurrence_composition__from_occurrence=formset.instance)
                )  # except if nested in this occurrence (for edit)
            )
            form.fields["to_occurrence"].label = "Nested {} occurrence".format(
                release.name)