My shopping cart is designed in such a way that the user must be logged in.
How can I design the shopping cart with these two conditions that it must be stored in the database and not in the session and that the user does not need to login to add the product to the shopping cart?
my model :
class Cart(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
def __str__(self):
return self.user.username
my view :
def cart_detail(request):
cart = Cart.objects.filter(user_id=request.user.id)
return render(request, 'cart/cart.html', {'cart': cart, })
Related
How can I get the obj of the the cartItem and place an order?
here's how my models.py look like.
class Cart(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.user)
class CartItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
cart = models.ForeignKey('Cart', on_delete=models.CASCADE)
selected = models.BooleanField(default=False)
At frontend -
first get the list of Cart
Select a cart
Form an object with desired values.
Send this object to django.
i am trying to create a shop where users can add products on sale and other users can add them to their cart
i can't figure out how can i make a cart contain multiple products and their quantities.
class Product(models.Model):
name = models.TextField()
description = models.TextField()
price = models.FloatField()
quantity = models.FloatField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Cart(models.Model):
#list of products
#list of quantities
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
You can make a model in between and use this as a through=… [Django-doc] model. In that model one uses a ForeignKey to the Product, a ForeignKey to the Cart, and an IntegerField for its quantity:
class Product(models.Model):
name = models.TextField()
description = models.TextField()
price = models.FloatField()
quantity = models.FloatField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Cart(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
products = models.ManyToManyField(
Product,
related_name='carts',
through='CartProduct'
)
class CartProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
class Meta:
constraints = [
models.UniqueField(fields=['product', 'cart'], name='unique_product_cart')
]
You thus add items to a cart by creating (or updating) the CartOrder with the given product and cart. In case the combination of the cart and the product already exists, you can increase its quantity.
You can furthermore iterate over the mycart.cardproduct_set.all() queryset to obtain the quantities, we can for example print the names of the products with its quantities with:
mycart = … # some cart
for cartproduct in mycart.cartproduct_set.select_related('product'):
print(f'{cartproduct.product.name}: {cartproduct.quantity}')
class Product(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(blank=True)
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=20, default=39.99)
image = models.ImageField(upload_to=upload_image_path,null=True, blank=True)
featured = models.BooleanField(default=False)
# quantity = models.IntegerField(default=1, null=True, blank=True)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True)
class OrderItem(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
item = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
class Cart(models.Model):
user = models.ForeignKey(User,null=True, blank=True,on_delete=models.CASCADE)
products = models.ManyToManyField(OrderItem, blank=True)
subtotal = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
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)
"""i am trying to create a ecom website and trying to add products in cart without login
the below code works with login user as request.user how to change it with guest user
"""
def add_cart(request, slug):
item = get_object_or_404(Product,slug=slug)
order_item ,created = OrderItem.objects.get_or_create(
user=request.user,
item =item,
)
print(order_item)
order_qs = Cart.objects.filter(user=request.user)
if order_qs.exists():
order= order_qs[0]
# check if the order item is in the order
if order.products.filter(item__slug=item.slug).exists():
order_item.quantity+= 1
order_item.save()
print("1")
else:
order.products.add(order_item)
else:
order = Cart.objects.create(
user=request.user
)
order.products.add(order_item)
print("done")
return redirect("cart:home")
I am trying to create a ecom website and trying to add products in cart without the below code works with login user with request.user how to change it with guest user and perform add cart and and quandity
to products as guest user
You need to use Django Sessions Framework to achieve this.
Django Sessions Framework
I am not sure that this is the best solution but the below code worked for me like a charm. And use this method if do not want to use JavaScript and only want to stick to the Django Sessions Framework.
In your Cart model:
class Cart(models.Model):
user = models.ForeignKey(User,null=True, blank=True,on_delete=models.CASCADE)
products = models.ManyToManyField(OrderItem, blank=True)
subtotal = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
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)
ordered = models.BooleanField(default=False)
session_key = models.CharField(max_length=40, null=True)
In your view.py
def add_cart(request, slug):
if request.user.is_authenticated:
item = get_object_or_404(Product,slug=slug)
order_item ,created = OrderItem.objects.get_or_create(
user=request.user,
item =item,
)
print(order_item)
order_qs = Cart.objects.filter(user=request.user, ordered=False)
if order_qs.exists():
order= order_qs[0]
# check if the order item is in the order
if order.products.filter(item__slug=item.slug).exists():
order_item.quantity+= 1
order_item.save()
print("1")
else:
order.products.add(order_item)
else:
order = Cart.objects.create(
user=request.user
)
order.products.add(order_item)
print("done")
return redirect("cart:home")
else:
item = get_object_or_404(Product,slug=slug)
order_item ,created = OrderItem.objects.get_or_create(
user=None,
item =item,
)
print(order_item)
order_qs = Cart.objects.filter(user=None, ordered=False, session_key=request.session.session_key)
if order_qs.exists():
order= order_qs[0]
# check if the order item is in the order
if order.products.filter(item__slug=item.slug).exists():
order_item.quantity+= 1
order_item.save()
print("1")
else:
order.products.add(order_item)
else:
order = Cart.objects.create(
user=None, session_key=request.session.session_key
)
order.products.add(order_item)
print("done")
return redirect("cart:home")
Furter Reference:
Thanks to Todor
Django: Anonymous session & "temporary" one-to-one related model?
You could create a specific user in your database that represents a guest user and assign the cart to that user. However, I do not recommend this.
I assume you want a visitor to be able to save their shopping cart. You can also achieve this by setting a cookie containing the cart data. You'll not need any backend for this as this can be build with javascript.
I have four models of the shop, customer, product, an order.
I am showing the relation of models
shop
user = models.OneToOneField(User, null=True, related_name='shop', blank=True, on_delete=models.CASCADE)
customer
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE
product
shop = models.ForeignKey(Shop, models.CASCADE, null=True, blank=True)
order
shop = models.ForeignKey(Shop, models.CASCADE, null=True)
customer = models.ForeignKey(Customer, models.CASCADE, null=True)
product = models.ForeignKey(Product, models.CASCADE, null=True)
when customers login then the shop will print on the screen and a button on shop to show the products by the shop in the form card
how I can create an order form so that the customer in order is the instance and the shop in order is that shop which is selected to show the products and every card of the product have a field to fill the remaining detail and submit
If I was you, I would add it to the form, with one of the following two options
Option 1
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Get the shop_id from the URL
shop = get_object_or_404(Shop, pk=shop_id)
# Create a form and add it the context
form = OrderForm(
# This is where the magic happens
initial={"shop": shop], "customer": self.request.user})
# Use this if you want to hide it as well
form.fields['item'].widget = forms.HiddenInput()
Option 2
# If the form is already created you can use this pattern
context['form'].fields['shop'].initial = shop
context['form'].fields['customer'].initial = self.request.user
I'm making a shopping cart with two class models, one user can order multiple products
I used the many-to-many relationships. but I'm facing some issues like if two users has order same product then the last user's selected qty will show in both user's order. and many times it shows all orders in the user's cart by default.
please tell the correct way to write these models. So each users cart can't affect others
class OrderItem(models.Model):
id = models.AutoField(primary_key=True)
product = models.OneToOneField(Product, on_delete=models.SET_NULL, null=True)
is_ordered = models.BooleanField(default=False)
date_added = models.DateTimeField(auto_now=True)
qty = models.IntegerField(default=1)
def __str__(self):
return self.product.Productname
class Cart(models.Model):
owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
is_ordered = models.BooleanField(default=False)
items = models.ManyToManyField(OrderItem, default=None, blank=True)
You should be able to have more than 1 order for a given product.
So the OrderItem should have a FK to the Product not onetoone.
I don't think you would have the same order in multiple carts, so you probably want a single FK from the OrderItem to the user's cart.