Error with CreateView

Hi, I’m learning Django and now I’m stuck with a problem…
The thing is I have a CBV which is not working… When I submit the form it doesn’t persist it in the database nor I see any error messages, it simply redirects to the same page:

views.py

class ProductCreateView(CreateView):
    model = Product
    success_url = reverse_lazy("store")
    form_class = ProductForm    


    def form_valid(self, form):
        instance = form.save(commit=False)
        instance.seller = User.objects.get(pk=self.kwargs['pk'])
        form.save()
        return super(ProductCreateView, self).form_valid(form)

forms.py

class ProductForm(forms.ModelForm):

    class Meta:
        model = Product
        fields = ['title', 'description', 'price', 'state', 'image']
        widgets = {
            'title': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Title'}
            ),
            'description': forms.Textarea(attrs={
                'class':'form-control',
                'placeholder':'Description',
                'id':'exampleFormControlTextarea1',
                'rows':3}
            ),
            'image': forms.ClearableFileInput(attrs={
                'class':'form-control-file',
                'placeholder': 'Image'}
            ),
            'price': forms.NumberInput(attrs={
                'class':'form-control',
                'placeholder':'Price'}
            ),
            'state': forms.Select(attrs={
                'class':'form-control'
            }),
        }

models.py

STATUS_CHOICES = (
       ('New', 'New'),
       ('Used as new', 'Used as new'),
       ('Used', 'Used'),
       ('Refurbished', 'Refurbished'),
)


class Product(models.Model):
    title = models.CharField(max_length=200, verbose_name="Title")
    description = models.TextField(verbose_name="Description")
    price = models.CharField(max_length=6, verbose_name="Price")
    image = models.ImageField(verbose_name="Image", upload_to="store")
    seller = models.ForeignKey(Seller, verbose_name="Seller", on_delete=models.CASCADE, related_name='%(class)s_seller', null=True, blank=True)
    state = models.CharField(max_length=20, choices=STATUS_CHOICES, default='Used')
    published = models.DateTimeField(auto_now_add=True, verbose_name="Publish date", null=True, blank=True)

    class Meta:
        verbose_name = "Product"
        verbose_name_plural = "Products"
        ordering = ['-published']

    def __str__(self):
        return self.title

product_form.html

    <form  class="form-control" method="post">
        {% csrf_token %}
        <div class="container">
            <div class="row">
                <div class="col-12 col-md-12 col-lg-12">
                    {{form.title}}
                    {{form.description}}                              
                </div>
            </div>
            <div class="row">
                <div class="col-12 col-md-6 col-lg-4">
                    {{form.price}}
                </div>
                <div class="col-12 col-md-6 col-lg-4">
                    {{form.state}}
                </div>
                <div class="col-12 col-md-6 col-lg-4">
                    {{form.image}}
                </div>
            </div>
        </div>
        <input type="submit" class="form-control btn btn-primary" value="Publish">
    </form>

Thanks for your time :slight_smile:

Oh, I happen to have something similar written down.
It’s in Korean, but you can use it as a reference just by looking at the code.

After form.save(commit=False), you must save the instance, not save the form.
form.save() After form.save(commit=False) just creates same object.

from django.shortcut import redirect
def form_valid(self, form):
  self.object = form.save(commit=False)
  self.object.seller = User.objects.get(pk=self.kwargs['pk'])
  self.object.save()
  return redirect(self.get_success_url())

You said simply redirects to the same page, I think that means you have been moved to the form creation page.
The reason is that you did not make space in the form template to display an error message.
The easiest way to solve this is to automatically render the form with the {{ form }} command.

#product_form.html
<form class="form-control" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" class="form-control btn btn-primary" value="Publish">
</form>

But if you want to use individual fields

#product_form.html

{{form.non_field_errors}}
<form class="form-control" method="post">
        {% csrf_token %}
        <div class="container">
            <div class="row">
                <div class="col-12 col-md-12 col-lg-12">
                    {{form.title.error}}
                    {{form.title}}
                    {{form.description.errors}}   
                    {{form.description}}                              
                </div>
            </div>
            <div class="row">
                <div class="col-12 col-md-6 col-lg-4">
                    {{form.price.errors}}
                    {{form.price}}
                </div>
                <div class="col-12 col-md-6 col-lg-4">
                    {{form.state.errors}}
                    {{form.state}}
                </div>
                <div class="col-12 col-md-6 col-lg-4">
                    {{form.image.errors}}
                    {{form.image}}
                </div>
            </div>
        </div>
        <input type="submit" class="form-control btn btn-primary" value="Publish">
</form>