(Django CBV) Need object be attached to a user with CBV


I implemented this functionality with using FBV, but when I’m trying to use CBV, Objects were created with empty user field.


class BlockCreate(CreateView):
    model = TrainingBlock
    template_name = 'training_room/create_block.html'
    form_class = BlockForm
    success_url = reverse_lazy('gym')
    def set_user(self, form):
        form.instance.user = self.request.user
        return super(BlockCreate, self).set_user(form)



class TrainingBlock(models.Model):
     user = models.ForeignKey(User, on_delete=models.CASCADE)
     name = models.CharField(max_length=30)
     duration = models.IntegerField(default=10)
     if_ended = models.BooleanField(default=False)
     def __str__(self):
          return self.name


class BlockForm(forms.ModelForm):
    class Meta:
        model = TrainingBlock
        fields = '__all__'
        exclude = ['user']


There is no .set_user method in a CreateView, hence the logic will never get invoked. You use .form_valid(…) [Django-doc] instead:

from django.contrib.auth.mixins import LoginRequiredMixin

class BlockCreate(LoginRequiredMixin, CreateView):
    model = TrainingBlock
    template_name = 'training_room/create_block.html'
    form_class = BlockForm
    success_url = reverse_lazy('gym')

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

Note: You can limit views to a view to authenticated users with the
@login_required decorator [Django-doc].

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Note: Since PEP-3135 [pep], you don’t need to call super(…) with parameters if the first parameter is the class in which you define the method, and the second is the first parameter (usually self) of the function.

Answered By: Willem Van Onsem