mmich
mmich

Reputation: 101

How to update two models in one form in django?

Okay, so first of all the situation is not quite easy as in the title. So I want to create form which can create object based on Cycle model and update only one field in Post model (field in question is 'cycle_title'). What is more its isn't only one post where this post have to be updated but there are several of it (all post's titles are saved in Cycle.post).

views

class CycleCreateView(LoginRequiredMixin, BSModalCreateView):
    template_name = 'blog/cycle_form.html'
    form_class = CycleForm

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update(user=self.request.user)
        return kwargs

    def form_valid(self, form, **kwargs):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def get_success_url(self):
        reverse_user = self.request.user
        return reverse('profile', kwargs={'username': reverse_user})

forms

class CycleForm(BSModalForm):

    def __init__(self, *args, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        if user is not None:
            self.fields['posts'].queryset = Post.objects.filter(author=user)

    class Meta:
        model = Cycle
        fields = ['title', 'description', 'posts']
        widgets = {
            'posts': forms.CheckboxSelectMultiple(),
        }

models

class Post(models.Model):
    title = models.CharField(max_length=100, unique=True)
    content = MDTextField()
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    cycle_title = models.CharField(max_length=100, default='')
class Cycle(models.Model):
    title = models.CharField(max_length=100, unique=True)
    description = models.TextField(max_length=500, default="Brak opisu")
    date_created = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    posts = models.ManyToManyField(Post)

I was thinking about a solution like this:

for i in form.cleaned_data['posts']:
    post = Post.objects.get(title=form.cleaned_data['title'][i])
    post.cycle_title = form.cleaned_data['title']
    post.save()

But I doubt if it is good way to resolve this issue

Upvotes: 2

Views: 941

Answers (1)

FlipperPA
FlipperPA

Reputation: 14311

A package has been built just to handle this exact scenario, django-shapeshifter. You can find it here:

https://github.com/kennethlove/django-shapeshifter

The basic premise is to create two model forms, then include them in the same template. The example given shows how to update a User and a Profile model from the same view and form. It sounds like that is a match for your problem. Full disclosure, I'm a contributor to this package, but is was created exactly because of frustrations like your own!

Upvotes: 2

Related Questions