Reputation: 65
Ok, so what I'm trying to do is allow the user to add a "product" to their shop but without having to choose the shop to add it to as each user will only have ONE shop.
I'm getting the: "IntegrityError at /shop/product/add/ NOT NULL constraint failed: shop_product.business_id"
This is what's being shown in the local variables: Local Vars
Local Vars:
Variable Value
__class__ <class 'shop.views.ProductCreate'>
form <AddProductForm bound=True, valid=True, fields=(product_name;product_desc;product_image)>
s <Shop: 4>
self <shop.views.ProductCreate object at 0x048B0370>
user 10
Now I believe the issue might be the "s" variable's as the code is actually getting the correct shop.. but it's also adding that weird "
My Code as it is right now.
models.py
# Shop Model. A Shop Object will be created when the user registers
class Shop(models.Model):
name = models.CharField(max_length=150)
owner = models.OneToOneField(User, related_name="owner")
shop_logo = models.FileField()
def __str__(self):
return str(self.name) + ": " + str(self.owner)
def create_shop(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
up = Shop(owner=user)
up.save()
post_save.connect(create_shop, sender=User)
def shoplogo_or_default(self, default_path='/static/images/dft/no-img.png'):
if self.shop_logo:
return self.shop_logo
return default_path
# The class that will link a product to the shop
class Product(models.Model):
product_name = models.CharField(max_length=250)
# connect the product to the shop
business = models.ForeignKey(Shop, on_delete=models.CASCADE, related_name="products")
product_desc = models.TextField()
product_image = models.FileField()
def __str__(self):
return self.product_name
views.py
class ProductCreate(CreateView):
model = Product
form_class = AddProductForm
template_name = 'shop/add-product.html'
def form_valid(self, form):
form.save(commit=False)
# get current logged in user
user = self.request.user.id
# match the current logged in user to an owner in the Shop model
s = Shop.objects.get(owner=user)
# get the id of that owner's shop identification number
form.business = str(s.id)
form.save()
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
return super(ProductCreate, self).form_valid(form)
The above should in theory get the current logged in user, match that user to a shop within the shop model as an owner and then get that shop ID.
forms.py
class AddProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ['product_name', 'product_desc', 'product_image']
exclude = ['business']
I'm rather new to Django and a student so I'd like to apologise if you see anything weird.
Thank you :)
Upvotes: 1
Views: 742
Reputation: 37344
You're close, but don't try to edit the shop value into the form. Instead, capture the in-memory Product
instance from saving the form and assign its business
attribute:
def form_valid(self, form):
new_product = form.save(commit=False)
# get current logged in user
user = self.request.user.id
# match the current logged in user to an owner in the Shop model
s = Shop.objects.get(owner=user)
# assign the shop instance to the product
new_product.business = s
# record the product to the database
new_product.save()
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
return super(ProductCreate, self).form_valid(form)
Upvotes: 3