DEV Community

Discussion on: Django inline formsets with Class-based views and crispy forms

Collapse
 
katbotkowska profile image
KatBot

It could be a problem with your views or forms. Paste that code. I've faced the similiar problem with formsets for m2m trought table and generic views maybe I can help you.

Collapse
 
mzakonek profile image
Mateusz

Or if you could share snippet with your implementation for m2m, then it will also be very helpful.

Collapse
 
mzakonek profile image
Mateusz • Edited

Hi,
I am sending link to code: github.com/mzakonek/laboratory_app...
It will open the Cart app in my project and inline formset is implemented at the 'views.py' and 'forms.py' files.
Actually I don't even need those 'remove' or 'add' buttons in the form. I need only to update the fields in the form.
Thanks a lot for your time!

Thread Thread
 
katbotkowska profile image
KatBot

I have a project concerning budget managing with model task, articles (expenditure category) and model m2m task_articles. Here, you have my code for create, update view for m2m model:

add articles to task

class AddArticlesToTaskView(PermissionRequiredMixin, FormView):
permission_required = 'budget.add_taskarticles'
raise_exception = False
login_url = reverse_lazy('budget:login')
permission_denied_message = 'You dont\'t have permission to add articles to task'
template_name = 'budget/add_articles_to_task.html'
pk_url_kwarg = 'task_slug'
success_url = ''

def get_task(self):
    task_slug = self.kwargs.get('task_slug')
    return Task.objects.get(slug=task_slug)

def get_form_class(self):
    return formset_factory(AddArticlesToTaskForm, extra=6)

def get_success_url(self):
    return reverse('budget:task_details', kwargs={'task_slug': self.kwargs.get('task_slug')})

def form_valid(self, form):
    for single_form in form:
        instance = single_form.save(commit=False)
        instance.task = self.get_task()
        instance.save()
    return super().form_valid(form)

def get_context_data(self, **kwargs):
    ctx = super().get_context_data(**kwargs)
    ctx['task'] = self.get_task()
    return ctx

class EditArticlesInTaskView(PermissionRequiredMixin, UpdateView):
permission_required = 'budget.change_taskarticles'
raise_exception = False
login_url = reverse_lazy('budget:login')
permission_denied_message = 'You dont\'t have permission to edit articles to task'
model = TaskArticles
form_class = EditArticlesInTaskForm
template_name = 'budget/task_edit_articles.html'
slug_url_kwarg = 'task_slug'
success_url = ''

def get_object(self, queryset=None):
    return self.get_task()

def get_queryset(self):
    return TaskArticles.objects.filter(task=self.get_task())

def get_task(self):
    task_slug = self.kwargs.get('task_slug')
    return Task.objects.get(slug=task_slug)

def get_success_url(self):
    return reverse('budget:task_details', kwargs={'task_slug': self.kwargs.get('task_slug')})

def post(self, request, *args, **kwargs):
    self.object = self.get_object()
    formset = EditArticlesInTaskFormSet(request.POST)
    if formset.is_valid():
        return self.form_valid(formset)
    return self.form_invalid(request, formset)

def form_invalid(self, request, formset):
    return render(request, self.template_name, {"formset": formset})

def form_valid(self, form):
    for single_form in form:
        instance = single_form.save(commit=False)
        instance.task = self.get_task()
        instance.save()
    return super().form_valid(form)

def get_context_data(self, **kwargs):
    ctx = super().get_context_data(**kwargs)
    ctx['task'] = self.get_task()
    ctx['formset'] = EditArticlesInTaskFormSet(queryset=TaskArticles.objects.filter(task=self.get_task()))
    return ctx

I hope it would help you. If you need more code, write :)

Thread Thread
 
katbotkowska profile image
KatBot

I can't use generic create view for add articles to task, because it doesn't work, so I used form view, update view works but only for that model m2m.
My other models m2m -add articles to contracts needs diffrent piece of code, I don't understand why, but solution for task doesn't work.

Thread Thread
 
mzakonek profile image
Mateusz

Thanks a lot! I will try to implement this in my project during this weekend and let you know how it goes.

And your EditArticlesInTaskFormSet is inlineformset or just modelformset_factory of TaskArticle ? Could you share it??
Once again, thanks a lot!

Thread Thread
 
katbotkowska profile image
KatBot

I didn't use inline formsets but model formset factory. I set I'd do it but with my data validations and fields querysets it was too complicated.

class EditArticlesInTaskForm(ModelForm):

def clean(self):
    super().clean()
    #many lines of code to validate accounting
        return self.cleaned_data

class Meta:
    model = TaskArticles
    fields = ('article', 'value')

EditArticlesInTaskFormSet = modelformset_factory(TaskArticles, fields=('article', 'value'),
extra=0, form=EditArticlesInTaskForm)

Thread Thread
 
mzakonek profile image
Mateusz

Now everything works, thanks so much!!!

Collapse
 
nad2000 profile image
Radomirs Cirskis

adding the manytomany fields to the excluded field list solved this issue:

class CollectionTitleForm(forms.ModelForm):

    class Meta:
        model = CollectionTitle
        exclude = ["titles_with_language"]
Enter fullscreen mode Exit fullscreen mode