IntegrityError at /cart/update-transaction/0cqydz1f/ - python

Hello am trying to make a transaction pressing submit this is the error am getting
IntegrityError at /cart/update-transaction/0cqydz1f/ NOT NULL
constraint failed: shopping_cart_transaction.product_id Request
Method: GET Request
URL: http://localhost:8000/cart/update-transaction/0cqydz1f/ Django
Version: 2.2 Exception Type: IntegrityError Exception Value: NOT NULL
constraint failed: shopping_cart_transaction.product_id
models.py
class Transaction(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
product = models.ForeignKey(Product,on_delete=models.CASCADE)
token = models.CharField(max_length=120)
order_id = models.CharField(max_length=120)
amount = models.DecimalField(max_digits=100, decimal_places=2)
success = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
def __str__(self):
return self.order_id
class Meta:
ordering = ['-timestamp']
views.py
#login_required()
def update_transaction_records(request, token):
# get the order being processed
order_to_purchase = get_user_pending_order(request)
# update the placed order
order_to_purchase.is_ordered=True
order_to_purchase.date_ordered=datetime.datetime.now()
order_to_purchase.save()
# get all items in the order - generates a queryset
order_items = order_to_purchase.items.all()
# update order items
order_items.update(is_ordered=True, date_ordered=datetime.datetime.now())
# Add products to user profile
user_profile = get_object_or_404(Profile, user=request.user)
# get the products from the items
order_products = [item.product for item in order_items]
user_profile.ebooks.add(*order_products)
user_profile.save()
# create a transaction
transaction = Transaction(profile=request.user.profile,
token=token,
order_id=order_to_purchase.id,
amount=order_to_purchase.get_cart_total(),
success=True)
# save the transcation (otherwise doesn't exist)
transaction.save()
messages.info(request, "Thank you! Your purchase was successful!")
return redirect(reverse('accounts:my_profile'))
Please help out am stuck here

Update your transaction in your view
I'm assuming your order_products is a list of all ordered products
for i in order_products:
transaction = Transaction(profile=request.user.profile,
product=i,
token=token,
order_id=order_to_purchase.id,
amount=order_to_purchase.get_cart_total(),
success=True)
# save the transcation (otherwise doesn't exist)
transaction.save()

You haven't passed an argument for product as mentioned in your model. And since you have not given it a default value or blank = True is given you the NOT NULL constrained failed error.
product = models.ForeignKey(Product,on_delete=models.CASCADE)
Pass the product object here.
transaction = Transaction(profile=request.user.profile,product = product, ...)

Related

TypeError at /listing: save() missing 1 required positional argument: 'self'

I'm trying to make an auction site and I'm having an issue changing the bid in the Bids model for a particular Auctionlisting object when POST data is submitted.
class Bids(models.Model):
minimum_bid = models.DecimalField(max_digits=8, decimal_places=2, null=False)
allbids = []
bid = models.DecimalField(max_digits=8, decimal_places=2, null=True, blank=True)
allbids.append(bid)
numBids = len(allbids)
def __str__(self):
if self.bid == None:
return f"Minimum Bid: ${self.minimum_bid}"
else:
return f"Highest Bid: ${self.bid}"
def save(self, userbid, object):
item = self.objects.get(pk=object)
item.bid = userbid
item.save()
Here is my AuctionListing model:
class AuctionListing(models.Model):
title = models.CharField(max_length=30)
description = models.CharField(max_length=137)
category = models.CharField(max_length=10, choices=Category.CHOICES, default="Men")
image = models.ImageField(upload_to="media")
bid = models.OneToOneField(Bids, on_delete=models.CASCADE, null=True)
def __str__(self):
return f"{self.category}: {self.title}"
Here is how I'm submitting the data in my views:
if request.method == "POST":
if "userbid" in request.POST:
try:
userbid = AuctionListing.objects.get(pk = request.GET.get("listing"))
userbid.bid = Bids.save(userbid=1000,object=object)
userbid.save()
except IntegrityError:
pass
The modeling is quite odd. An AuctionListing refers to a Bids model, but it makes not much sense to do that. In case each AcutionListing has a Bids object and vice-versa, it is more sensical to just add the data to the AuctionListing itself.
Furthermore you do not store the individual bids. If later the auction is closed, how will you know who made the highest bid? Your Bids model also creates a list, and appends the bid field to that, but that is the only item it will contain. The logic in the class is only evaluated once: when the class is constructed, so from the moment the class has been interpreted, the bid and numBids do not make much sense anymore.
The Bids also contain a field minimum_bid, but this is information related to the object people are bidding on, not a bid itself.
A more sensical modeling is that you have an AuctionListing to present objects on which one can bid. Per AuctionListing there can be multiple Bids, one can then determine the lowest bid by annotating, or making queries. In that case the two models are thus defined as:
class AuctionListing(models.Model):
title = models.CharField(max_length=30)
description = models.CharField(max_length=137)
category = models.CharField(max_length=10, choices=Category.CHOICES, default='Men')
image = models.ImageField(upload_to='media')
minimum_bid = models.DecimalField(max_digits=8, decimal_places=2)
def __str__(self):
return f'{self.category}: {self.title}'
def get_largest_bit(self):
return self.bids.order_by('-bid').first()
Then you can define a Bid model with a ForeignKey to the AuctionList: the item that people can bid on:
class Bid(models.Model):
item = models.ForeignKey(
AuctionListing,
on_delete=models.CASCADE,
related_name='bids'
)
bid = models.DecimalField(max_digits=8, decimal_places=2)
In your view, you can then make a bid on the AuctionList item with as primary key pk with:
from django.shortcuts import get_object_or_404
def make_bid(request, pk):
item = get_object_or_404(AuctionList, pk=pk)
if request.method == 'POST':
bid_value = request.POST['bid'] # retrieve the bid value from somewhere
if bid_value < item.minimum_bid:
# do something, report an error
# …
else:
Bid.objects.create(item_id=pk, bid=bid_value)
return redirect('name-of-some-view')
else:
# …
# …

django.db.utils.IntegrityError: UNIQUE constraint failed: auctions_bids.item_id

I building the auctions website and have this problem:
UNIQUE constraint failed: auctions_bids.item_id
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.db.models.deletion import CASCADE
from django.db.models.fields import EmailField, NOT_PROVIDED
class User(AbstractUser):
pass
class Listings(models.Model):
title = models.CharField(max_length=64)
description = models.TextField(max_length=250)
price = models.FloatField()
image_url = models.CharField(max_length=150)
category = models.ForeignKey(Categories, on_delete=models.CASCADE)
listed_by = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"{self.title}" #{self.description} {self.price} {self.image_url} {self.category}"
class Bids(models.Model):
item = models.OneToOneField(Listings, on_delete=models.CASCADE)
bid = models.FloatField(blank=True)
user_bid = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
def __str__(self):
return f"{self.item} {self.bid} {self.user_bid}"
views.py
def placebid(request, id_product):
if request.method == "POST":
item_list = Listings.objects.get(pk=id_product)
bid = request.POST['bid']
user = request.user
Bids.objects.update_or_create(item=item_list, bid=bid, user_bid=user)
return redirect(reverse("listings", args=(id,)))
When I try to update the new bid, this appears the above error, the only way to delete the old object and create a new object, I want to update the new bid if the object exists and create if the object doesn't exist by using update_or_create
I think I had wrong in setting parameter item values of the Bids model, but I don't know how to fix them! Any advice for me, Thanks so much !!!
You are filtering on the bid and user_bid as well. This thus means that it will only update if the item, bid and userbid are the same. But likely you want to update from the moment item is the same, so you should use the defaults=… parameter of the .update_or_create(…) method [Django-doc]:
from django.shortcuts import redirect
def placebid(request, id_product):
if request.method == 'POST':
bid = request.POST['bid']
user = request.user
Bids.objects.update_or_create(
item_id=id_product
defaults={'bid': bid, 'user_bid': user}
)
return redirect('listings', id)
Django will thus check if it can find a Bids object for which item_id is id_product. If it can, it will update bid and user_bid as specified in the defaults, otherwise it will create a Bids object with these defaults.
Note: normally a Django model is given a singular name, so Bid instead of Bids.

UserCheckout matching query does not exist

I'm trying to display all orders matching each logged in user, I dont understand why it gives me issues when trying to filter for users as it gives me that UserCheckout does not have any matching queries:
orders/views.py
class OrderList(LoginRequiredMixin, ListView):
queryset = Order.objects.all()
def get_queryset(self):
user_check_id = self.request.user.id
user_checkout = UserCheckout.objects.get(id=user_check_id)
return super(OrderList, self).get_queryset().filter(user=user_checkout)
orders/mixins.py
class LoginRequiredMixin(object):
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request,*args, **kwargs)
orders/models.py
class UserCheckout(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete = models.CASCADE) # not required as to allow guests to checkout too
email = models.EmailField(unique=True) # required, unique as if there the guest already has an authentication just one email needed
def __str__(self):
return self.email
class Order(models.Model):
status = models.CharField(max_length=120, choices=ORDER_STATUS_CHOICES, default='created')
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
user = models.ForeignKey(UserCheckout, null=True, on_delete=models.CASCADE)
billing_address = models.ForeignKey(UserAddress, related_name='billing_address', null=True,on_delete=models.CASCADE)
shipping_address = models.ForeignKey(UserAddress, related_name='shipping_address', null=True, on_delete=models.CASCADE)
shipping_total_price = models.DecimalField(max_digits=50, decimal_places=2, default=5.99)
order_total = models.DecimalField(max_digits=50, decimal_places=2)
def __str__(self):
return str(self.cart.id)
Error it gives me:
DoesNotExist at /orders/
UserCheckout matching query does not exist.
You are getting an error because you are trying to use the User's primary key (id) as the UserCheckout's primary key i.e. the lines:
user_check_id = self.request.user.id
user_checkout = UserCheckout.objects.get(id=user_check_id)
Change these lines to:
user = self.request.user
user_checkout = UserCheckout.objects.get(user=user)
Also this can throw an Exception if a UserCheckout instance doesn't exist you can catch that using try-except or use django's shortcut function get_object_or_404:
from django.shortcuts import get_object_or_404
user_checkout = get_object_or_404(UserCheckout, user=user)

How to Return Error Message for Every Instance in Bulk (Array of JSON Objects) POST Request?

I am working on Restaurant Ordering Application. Order of items will be created as an Array of JSON object will be POSTed to orderdetail models, but when the stock of any of the item is not sufficient it will raise Exception. But I only can give an error for one item not all the items.
For example:
Current Stock
Apple 5pcs
Mango 10pcs
When I make an order of Apple 10pcs and Mango 20pcs. I want to get an Error Message saying that "Apple and Mango stock is not sufficient". But currently, I only get "Apple stock is not sufficient" because I put apple as the first object in the array. If I put mango as the first object, I will get "Mango stock is not sufficient".
For full of the code, you can check the repo link: here.
My Models:
class Menu(models.Model):
image = models.ImageField(upload_to=path_and_rename)
name = models.CharField(max_length=100)
price = models.IntegerField()
category = models.IntegerField()
availability = models.BooleanField(default=False)
qty = models.IntegerField(default=100)
sellerID = models.ForeignKey(Seller, on_delete=models.PROTECT)
class OrderDetail(models.Model):
orderID = models.ForeignKey(Order, on_delete=models.PROTECT)
menuID = models.ForeignKey(Menu, on_delete=models.PROTECT)
price = models.IntegerField()
qty = models.IntegerField()
tableNumber = models.IntegerField()
done = models.BooleanField(default=False)
# orderTime = models.DateTimeField(auto_now_add=True)
# finishTime = models.DateTimeField(auto_now=True)
finishTime = models.DateTimeField(null=True, blank=True)
sellerID = models.ForeignKey(Seller, on_delete=models.PROTECT)
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
if self.done:
self.finishTime = datetime.datetime.now()
else:
menuID = self.menuID.id
menuObject = Menu.objects.get(id=menuID)
tempQty = menuObject.qty - self.qty
if tempQty>=0:
menuObject.qty = tempQty
menuObject.save()
else:
# return serializers.ValidationError()
raise serializers.ValidationError(menuObject.name + ": STOCK IS NOT SUFFICIENT")
super().save(force_insert, force_update, using, update_fields)
My View:
class OrderDetailViewset(viewsets.ModelViewSet):
serializer_class = serializers.OrderDetailSerializer
def get_queryset(self):
queryset = models.OrderDetail.objects.all()
sellerID = self.request.query_params.get('sellerID', None)
done = self.request.query_params.get('done', None)
if sellerID is not None:
queryset = queryset.filter(sellerID=sellerID)
if done is not None:
queryset = queryset.filter(sellerID=sellerID, done=done)
return queryset
# Enable Post of List
# https://stackoverflow.com/questions/37329771/django-rest-bulk-post-post-array-of-json-objects
# Accessed on March 9, 2019
def create(self, request, pk=None, company_pk=None, project_pk=None):
is_many = True if isinstance(request.data, list) else False
serializer = self.get_serializer(data=request.data, many=is_many)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
I think the problem is located where I raised the Exception, but I have no Idea how to fix it. Thank you before!
as you correctly said the problem is located where you raised the Exception: ModelViewSet.create > serializer.is_valid(raise_exception=True).
Based on the DRF docs:
When deserializing data, you always need to call is_valid() before attempting to access the validated data, or save an object instance.
...
The .is_valid() method takes an optional raise_exception flag that will cause it to raise a serializers.ValidationError exception if there are validation errors.
These exceptions are automatically dealt with by the default exception handler that REST framework provides, and will return HTTP 400 Bad Request responses by default.
So, the first object who reaches this validation returns the HTTP 400 Bad Request you mention.
You'll need to customize the validation to not return an HTTP 400 Bad Request, implement your own validation in the serializer and/or catch and process these exception in the view, that way you'll have the flexibility you need to handle these bulk load.
Take a look at DRF code and DRF docs.
Good Luck!

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 :)
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)

Categories

Resources