U.Ali
U.Ali

Reputation: 65

Django - Get Related Key and Insert into Database

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

Answers (1)

Peter DeGlopper
Peter DeGlopper

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

Related Questions