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.
Related
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:
# …
# …
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, ...)
I am trying to learn to make cart in e-commerce website by watching some tutorial. I get an error while running my code although it works fine in the tutorial but in my code, it gives error something like this. I have no idea why I tried to check my code several time but still I am unable to figure out.
type object 'Cart' has no attribute 'objects'
These are my codes
carts/models.py
from django.conf import settings
from django.db import models
from products.models import Product
User = settings.AUTH_USER_MODEL
# Create your models here.
class CartManager(models.Manager):
def new(self, user=None):
user_obj = None
if user is not None:
if user.is_authenticated():
user_obj = user_obj
return self.model.objects.create(user=user_obj)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
products = models.ManyToManyField(Product, blank=True)
total = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
object = CartManager()
def __str__(self):
return str(self.id)
carts/view
from django.shortcuts import render
from .models import Cart
# Create your views here.
def cart_home(request):
cart_id = request.session.get('cart_id', None)
qs = Cart.objects.filter(id = cart_id)
if qs.count() == 1:
cart_obj = qs.first()
print('Cart id exists')
else:
cart_obj = Cart.objects.new(user=request.user)
request.session['cart_id'] = cart_obj.id
return render(request, "carts/home.html", {})
Because of this:
class Cart(models.Model):
...
object = CartManager()
You have assigned the model manager as attribute object in Cart model. So rename it to objects.
I'm not sure where to start. Right now, the user can press like as many times they want and it'll just add up the total likes for that tweet.
models.py
class Howl(models.Model):
author = models.ForeignKey(User, null=True)
content = models.CharField(max_length=150)
published_date = models.DateTimeField(default=timezone.now)
like_count = models.IntegerField(default=0)
rehowl_count = models.IntegerField(default=0)
def get_absolute_url(self):
return reverse('howl:index')
def __str__(self):
return self.content
views.py
class HowlLike(UpdateView):
model = Howl
fields = []
def form_valid(self, form):
instance = form.save(commit=False)
instance.like_count += 1
instance.save()
return redirect('howl:index')
Django Twitter clone. How to restrict user from liking a tweet more than once?
As well as tracking how many Likes a post has, you'll probably also want to track who has "Liked" each post. You can solve both of these problems by creating a joining table Likes with a unique key on User and Howl.
The unique key will prevent any User from doing duplicate likes.
You can do this in Django with a ManyToManyField, note that since this means adding a second User relationship to Howl, we need to disambiguate the relationship by providing a related_name
Eg:
class Howl(models.Model):
author = models.ForeignKey(User, null=True, related_name='howls_authored')
liked_by = models.ManyToManyField(User, through='Like')
# ...rest of class as above
class Like(models.Model):
user = models.ForeignKey(User)
howl = models.ForeignKey(Howl)
class Meta:
unique_together = (('user', 'howl'))
like_count count then becomes redundant, since you can use Howl.liked_by.count() instead.
The other benefit of this is that it allows you to store information about the Like - eg when it was added.
An idea could be adding a column to your table named likers and before incrementing like_counts check if the models.likers contains the new liker or not. If not increment the likes, if yes don't.
Changed liked_count in my models.py to
liked_by = models.ManyToManyField(User, related_name="likes")
views.py
class HowlLike(UpdateView):
model = Howl
fields = []
def form_valid(self, form):
instance = form.save(commit=False)
instance.liked_by.add(self.request.user)
instance.like_count = instance.liked_by.count()
instance.save()
return redirect('howl:index')
index.html
{{howl.liked_by.count}}
I'm trying to save some form data inputted by the user. I would like to slugify the "name" which was entered by the user, but dont want the slug field to show on the template that the user sees. I tried to do it manually with the sell function that you see below, but cant quite get it to work. I want to eventually save the slugified name into the Item model I have listed below. I'm sure there's a much smarter/simpler way than the sell function I'm currently using :P. Thanks in advance!
class Item(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=75)
slug = models.SlugField(max_length=50, unique=True)
is_active = models.BooleanField(default=True)
image = models.CharField(max_length=50)
price = models.DecimalField(max_digits=9, decimal_places=2)
quantity = models.IntegerField(default=1)
description = models.TextField()
created = models.DateTimeField(auto_now_add=True)
shipping_price = models.DecimalField(decimal_places=2, max_digits=6)
categories = models.ManyToManyField(Category)
class AddItem(forms.ModelForm):
class Meta:
model = Item
exclude = ('user','slug','is_active',)
def sell(request):
if request.method == "POST":
form = AddItem(request.POST)
item = form.save(commit=False)
item.user = request.user
item.is_active = True
item.slug = slugify(form.name) **#not sure what this line should be?**
item.save()
if form.is_valid():
form.save()
return HttpResponseRedirect('thanks.html')
else:
url = urlresolvers.reverse('register')
return HttpResponseRedirect(url)
You can exclude slug from user form.
And slugify in pre_save signal.
from django.dispatch import receiver
from django.db.models.signals import pre_save
#receiver(pre_save, sender=Item)
def iter_pre_save_handler(sender, instance, **kwargs):
if not instance.pk:
instance.slug = slugify(instance.name)
According to the docs, you can exclude a field from being rendered in a model form like this:
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title')
or
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
exclude = ('birth_date',)
or by setting editable=False on the Field instance in your model.
Once you have done this, you can override the save method of the model, as the comments in the OP have suggested:
# shamelessly copied from http://stackoverflow.com/questions/837828/how-do-i-create-a-slug-in-django/837835#837835
from django.template.defaultfilters import slugify
class test(models.Model):
q = models.CharField(max_length=30)
s = models.SlugField()
def save(self, *args, **kwargs):
self.s = slugify(self.q)
super(test, self).save(*args, **kwargs)