Rut*_*net 0 python django django-models django-views
我正在开发Django购物车应用程序。我有两种型号的购物车和物品。我正在尝试将数量添加到购物篮中时更新数量,但无法使视图正常工作。我在使item_obj分配工作时遇到问题-在这里我需要对模型管理器做任何事情吗?任何帮助都非常感谢。
型号
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True)
products = models.ManyToManyField(Product, blank=True)
total = models.DecimalField(default=0.00, max_digits=10, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = CartManager()
def __str__(self):
return str(self.id)
class Item(models.Model):
item = models.ForeignKey(Product, null=True)
cart = models.ForeignKey(Cart, null=True)
quantity = models.PositiveIntegerField()
Run Code Online (Sandbox Code Playgroud)
Views.py提取
def cart_update(request):
product_id = request.POST.get('product_id')
product_obj = Item.objects.get(id=product_id)
print(item_id)
item_obj = Item.objects.get(id=product_id)
cart_obj, new_obj = Cart.objects.new_or_get(request)
if item_obj in cart_obj.products.all():
cart_obj.products.add(product_obj)
item_obj.quantity += 1
item_obj.save()
else:
cart_obj.products.add(product_obj)
return redirect("cart:home")
EDIT
Run Code Online (Sandbox Code Playgroud)
Views.py更新(12/02/2018)
def cart_update(request):
# Based on the user who is making the request, grab the cart object
cart_obj, new_obj = Cart.objects.new_or_get(request)
# Get entries in the cart
my_carts_current_entries = Entry.objects.filter(cart=cart_obj)
# Get a list of your products
products = Product.objects.all()
if request.POST:
# Get the product's ID from the POST request.
product_id = request.POST.get('product_id')
# Get the quantity of the product desired.
product_quantity = request.POST.get('product_quantity')
# Create the new Entry...this will update the cart on creation
Entry.objects.create(cart=cart_obj, product=product_id, quantity=product_quantity)
return HttpResponse('carts/carts.html')
return render(request, 'carts/carts.html', {'cart_obj': cart_obj, 'my_carts_current_entries': my_carts_current_entries,
'products': products})
Run Code Online (Sandbox Code Playgroud)
另外,我还有一个单独的购物车模型管理器,用于创建新购物车或为用户分配一个购物车,如下所示:
class CartManager(models.Manager):
def new_or_get(self, request):
cart_id = request.session.get("cart_id", None)
qs = self.get_queryset().filter(id=cart_id)
if qs.count() == 1:
new_obj = False
cart_obj = qs.first()
if request.user.is_authenticated() and cart_obj.user is None:
cart_obj.user = request.user
cart_obj.save()
else:
cart_obj = Cart.objects.new(user=request.user)
new_obj = True
request.session['cart_id'] = cart_obj.id
return cart_obj, new_obj
def new(self, user=None):
user_obj = None
if user is not None:
if user.is_authenticated():
user_obj = user
return self.model.objects.create(user=user_obj)
Run Code Online (Sandbox Code Playgroud)
调试日志中的错误在这里可用:
提前致谢
更新2:
这就是我的模板文件目前的读取方式。
{% for product in cat_appetizers %}
<table>
<tr>
<td><h5>{{ product.name }}</h5>
<td><p><strong>£ {{ product.price }}</strong></p></td>
<td>
<form class='form-product-ajax' method="POST" action='{% url "cart:update" %}' data-endpoint='{% url "cart:update" %}' class="form"> {% csrf_token %}
<input type="hidden" name='product_id' value='{{ product.id }}'>
<span class='submit-span'>
{% if product in cart.products.all %}
<button>Remove</button>
{% else %}
<button>Add to Basket</button>
</span>
{% endif %}
</form>
</td>
</tr>
</table>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
我们可以通过在模型中使用保存后的信号来更新Cart模型。每当创建条目时,以下保存后的接收器都会更新购物车模型。
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.datetime_safe import datetime
class Product(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=64, unique=True)
description = models.TextField(default='')
cost = models.DecimalField(default=0.00, max_digits=10, decimal_places=2)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete='CASCADE')
count = models.PositiveIntegerField(default=0)
total = models.DecimalField(default=0.00, max_digits=10, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "User: {} has {} items in their cart. Their total is ${}".format(self.user, self.count, self.total)
class Entry(models.Model):
product = models.ForeignKey(Product, null=True, on_delete='CASCADE')
cart = models.ForeignKey(Cart, null=True, on_delete='CASCADE')
quantity = models.PositiveIntegerField()
def __str__(self):
return "This entry contains {} {}(s).".format(self.quantity, self.product.name)
@receiver(post_save, sender=Entry)
def update_cart(sender, instance, **kwargs):
line_cost = instance.quantity * instance.product.cost
instance.cart.total += line_cost
instance.cart.count += instance.quantity
instance.cart.updated = datetime.now()
Run Code Online (Sandbox Code Playgroud)
def test_my_cart():
apple, created = Product.objects.get_or_create(name='apple', cost=0.25)
my_cart, created = Cart.objects.get_or_create(user=None)
print(my_cart)
# STDOUT --> User: None has 0 items in their cart. Their total is $0.00
entry1 = Entry.objects.create(product=apple, cart=my_cart, quantity=3)
print(entry1)
# STDOUT --> This entry contains 3 apple(s)
print(my_cart)
# STDOUT --> User: None has 3 items in their cart. Their total is $0.75
Run Code Online (Sandbox Code Playgroud)
如果您想稍后再从购物车中删除该行条目,则Django中还会有一个后删除信号。
祝你好运
要在管理面板中使用此功能,请尝试以下操作:
# admin.py
from django.contrib import admin
from django.utils.datetime_safe import datetime
from app.models import Product, Cart, Entry
class EntryAdmin(admin.ModelAdmin):
# Overide of the save model
def save_model(self, request, obj, form, change):
obj.cart.total += obj.quantity * obj.product.cost
obj.cart.count += obj.quantity
obj.cart.updated = datetime.now()
obj.cart.save()
super().save_model(request, obj, form, change)
# Register your models here.
admin.site.register(Product)
admin.site.register(Cart)
admin.site.register(Entry, EntryAdmin)
Run Code Online (Sandbox Code Playgroud)
我还想指出的是,由于存在“多种方法来给猫换皮”,我们可以在模型中覆盖save方法,而不使用信号。我认为这取决于应用程序和个人喜好。
这是一个示例视图,它将:
from django.shortcuts import render
from scratchwork.models import Cart, Entry
from django.contrib.auth.models import User
def test_view(request):
""" This view displays what is in a user's cart. """
# Based on the user who is making the request, grab the cart object
my_cart = Cart.objects.get_or_create(user=User)
# Get a queryset of entries that correspond to "my_cart"
list_of_entries = Entry.objects.filter(cart=my_cart)
# Make a list of the product's names
list_of_products = list(list_of_entries.values_list('product__name', flat=True))
# Remove redundant product names
list_of_products = list(set(list_of_products))
return render(request, 'something.html', {'list_of_products': list_of_products})
Run Code Online (Sandbox Code Playgroud)
在讨论代码之前,我将进行快速比较,因此我们在同一页上讨论了模型类。
假设您在亚马逊购物。您作为亚马逊客户拥有 购物车。购物车将显示您在网站上购物时添加到其中的所有条目。
当您浏览亚马逊奇妙的商品时,偶然发现了一双想要购买的鞋子。这些鞋子是产品,并有名称,价格和描述。
您决定购买这些鞋子,因此单击“添加到购物车”。此时,Amazon Web服务会生成一个链接到购物车的条目,其中 包含有关产品的信息。
因此,您单击一个按钮将POST数据发送回视图。假设您正在使用表单或AJAX数据来获取信息,这就是设计视图的方式。
from django.http import HttpResponse
from django.shortcuts import render
from scratchwork.models import Cart, Entry, Product
from django.contrib.auth.models import User
def test_view(request):
# Based on the user who is making the request, grab the cart object
my_cart = Cart.objects.get_or_create(user=User)
# Get entries in the cart
my_carts_current_entries = Entry.objects.filter(cart=my_cart)
# Get a list of your products
products = Product.objects.all()
if request.POST:
# Get the product's ID from the POST request.
product_id = request.POST.get('product_id')
# Get the object using our unique primary key
product_obj = Product.objects.get(id=product_id)
# Get the quantity of the product desired.
product_quantity = request.POST.get('product_quantity')
# Create the new Entry...this will update the cart on creation
Entry.objects.create(cart=my_cart, product=product_obj, quantity=product_quantity)
return HttpResponse('somewhereelse.html')
return render(request, 'something.html', {'my_cart': my_cart, 'my_carts_current_entries': my_carts_current_entries,
'products': products})
Run Code Online (Sandbox Code Playgroud)