DEV Community

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

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!!!