viewflow / django-material

Material Design for Django
http://viewflow.io/
BSD 3-Clause "New" or "Revised" License
2.48k stars 425 forks source link

inline_formset including instance #129

Closed alvarosaavedra closed 8 years ago

alvarosaavedra commented 8 years ago

Hi I'm working with a form including a inline_formset for a update, I have make it work in a Create generic view but I having problems for the update one. I can not set the instance in the inline_formset have you ay idea how i can make this???

kmmbvnr commented 8 years ago

Sorry, i don't understand what you mean. Could you provide a code sample?

alvarosaavedra commented 8 years ago

It works correct creating new extrajobs but it no selects the correct extrajobs for the bonus

ExtraJobFormSet = inlineformset_factory(Bonus, ExtraJob, form=ExtraJobForm, extra=2)

class BonusForm(forms.ModelForm):

  extrajob_set = FormSetField(ExtraJobFormSet)

  class Meta:
    model = Bonus
    fields = ['bonus']

class ExtraJobForm(forms.ModelForm):
  class Meta:
    model = ExtraJob
    fields = ['name','hh']

class BonusUpdate(LoginRequiredMixin,UpdateView, LayoutMixin):
    model = Bonus
    form_class = BonusForm
    layout = Layout('bonus','extrajob_set')

    def get_object(self, **kwargs):
        date= '%s-%s-%s' % (self.kwargs['year'], self.kwargs['month'], 1)
        job = Job.objects.get(pk = self.kwargs['job_pk'])
        bonus, created = Bonus.objects.get_or_create(
            date= date,
            job= job,
            defaults={'bonus': 0.0}
        )
        return bonus

    def get_context_data(self, **kwargs):
        data = super(BonusUpdate, self).get_context_data(**kwargs)
        if self.request.POST:
            data['extrajob_set'] = ExtraJobFormSet(self.request.POST)
        else:
            object = self.object
            data['form'].fields['extrajob_set'].formset_cls =  ExtraJobFormSet(instance=self.object)
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        extrajob_set = context['extrajob_set']
        self.object = form.save()

        if extrajob_set.is_valid():
            extrajob_set.instance = self.object
            extrajob_set.save()

        return super(BonusUpdate, self).form_valid(form)
kmmbvnr commented 8 years ago

Ok, so as I see, we have two problems:

  1. passing initials to the FormsetField
  2. No support for InlineFormsetField
kmmbvnr commented 8 years ago

I'm thinking about to drop django-extra-views support, but instead add https://github.com/gregmuellegger/django-superform fields templates.

This would gives much nicer integration with standard django GCBV and material.frontend

alvarosaavedra commented 8 years ago

@kmmbvnr looks realy nice talk to me if you need some help

kmmbvnr commented 8 years ago

Since the genaral policy of this repo is not to have any 3d party deps, the formsets support implemented in a viewflow-pro suite code.

You can have django_superforms support in your project by adding following files:

material/templates/material/fields/django_superform_formsetwidget.html

{% load material_form_internal %}
{% render bound_field template='layout/tabular_inline.html' %}{% endrender %}

material/templates/material/layout/tabular_inline.html

{% with formset=bound_field.value %}
<div class="section row">
    <div class="formset-field col s12" data-formset-prefix="{{ formset.prefix }}">
        {% part field label %}<h5>{{ bound_field.name|capfirst }}</h5>{% endpart %}
        <script type="form-template" data-formset-empty-form>
            {% include 'material/layout/_tabular_inline_form.html' with form=formset.empty_form layout=formset.empty_form.layout %}
        </script>
        <table class="table responsive-table">
            <tbody data-formset-body>
                {% for form in formset %}
                {% include 'material/layout/_tabular_inline_form.html' with layout=form.layout %}
                {% endfor %}
            </tbody>
        </table>
        <button type="button" class="btn btn-flat grey lighten-4" style="padding:0px 40px;width:100%" data-formset-add><i class="material-icons">add</i></button>
        {{ formset.management_form }}
    </div>
</div>
{% endwith %}

material/templates/material/layout/_tabular_inline_form.html

{% load material_form_internal %}
<tr data-formset-form>
    {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %}
    {% for bound_field in form.visible_fields %}
    {% if bound_field.name != 'DELETE' %}
    <td>
        {% render bound_field %}{% endrender %}
    </td>
    {% endif %}
    {% endfor %}
    {% if formset.can_delete %}
    <td>
        <div style="display:none">{{ form.DELETE }}</div>
        <button type="button" class="btn btn-flat white lighten-4"
                style="padding:0px 5px;font-size:0.7rem;height:calc(100% - 15px);width:100%"
                data-formset-delete-button>
            <i class="material-icons">clear</i>
        </button>
    </td>
    {% endif %}
</tr>