Django购物车和物品模型 - 获取更新数量

时间:2018-02-10 01:28:45

标签: python django django-models django-views

我正在开发一个Django购物车应用程序。我有两个型号Cart和Item。我正在尝试将项目添加到购物篮时获取更新数量,但无法使视图正常工作。我在将item_obj赋值工作时遇到问题 - 我是否需要在此处对模型管理器执行任何操作?任何帮助都非常感谢。

Models.py

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

Views.py extract

    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

Views.py update(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})

此外,我还有一个单独的购物车模型管理器,用于创建新购物车或为用户分配一个购物车,如下所示:

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)

调试日志中的错误可在此处获得:

http://dpaste.com/1NX02JW

提前致谢

更新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 %} 

1 个答案:

答案 0 :(得分:5)

我们可以在模型中使用post-save signal更新购物车模型。以下保存后接收器将在创建条目时更新购物车模型。

models.py

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

示例函数

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

如果您想稍后从购物车中删除行条目,Django中也会有删除后信号。

祝你好运

编辑#1

要在管理面板中使用此功能,请尝试following

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

我还要注意,因为有多种方法可以给猫皮肤涂抹#34;我们可以override the save method in the model而不是使用信号。我认为这取决于申请和个人偏好。

编辑#2

这是一个示例视图:

  1. 获取用户购物车
  2. 从该购物车中抓取条目列表
  3. 获取这些条目中产品的所有唯一名称的列表
  4. example_view.py

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

    编辑#3

    在我谈论代码之前,我将进行快速比较,以便我们在模型类的相同页面上。

      

    想象一下你在亚马逊上购物。您作为亚马逊客户拥有   的即可。当您在网站上购物时,购物车会向您显示您添加的任何条目

         

    当你去浏览亚马逊的奇妙商品时,你偶然发现了一个   你想买的那双鞋。这些鞋是产品并且有   名称,价格和对它们的描述。

         

    您决定购买这些鞋子,然后点击&#34;添加到购物车&#34;。在   这次亚马逊网络服务生成一个条目链接到   购物车,其中包含有关产品的信息。

    实施

    因此,您单击按钮将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})