【问题标题】:Implementing Anonymous User Checkout Django实现匿名用户结帐 Django
【发布时间】:2026-01-30 00:40:01
【问题描述】:

我正在尝试建立一个电子商务网站。我创建了不同的应用程序。

  1. 帐户
  2. 手推车
  3. 订单
  4. 产品

我想实现匿名用户结帐,如果用户未登录,他将被重定向到访客用户结帐表单。我已经尝试删除 login_required 装饰器,但我没有成功修改它。目前,我的订单应用程序模型看起来像这样。我

from django.db import models
from django.conf import settings
from accounts.models import UserAddress
# Create your models here.

from carts.models import Cart

STATUS_CHOICES =(
        ("Started", "Started"),
        ("Abandoned", "Abandoned"),
        ("Finished", "Finished"),

    )

class Order(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True)
    order_id = models.CharField(max_length=120, default='ABC', unique=True)
    cart = models.ForeignKey(Cart)
    status = models.CharField(max_length=120, choices=STATUS_CHOICES, default="Started")
    shipping_address = models.ForeignKey(UserAddress, related_name='shipping_address', default=1)
    billing_address = models.ForeignKey(UserAddress, related_name='billing_address',default=1)
    sub_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
    tax_total = models.DecimalField(default=0.00, max_digits=1000, decimal_places=2)
    final_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)


    # address **

    status = models.CharField(max_length=120, choices=STATUS_CHOICES, default="Started")
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)

    def __unicode__(self):
        return self.order_id

视图看起来像这样

import time

from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.shortcuts import render, HttpResponseRedirect

# Create your views here.

from accounts.forms import UserAddressForm
from accounts.models import UserAddress
from carts.models import Cart

from .models import Order
from .utils import id_generator

def orders(request):
    context = {}
    template = "orders/user.html"
    return render(request, template, context)


#require user login ** 
@login_required
def checkout(request):
    try:
        the_id = request.session['cart_id']
        cart = Cart.objects.get(id=the_id)
    except:
        the_id = None
        #return HttpResponseRedirect("/cart/")
        return HttpResponseRedirect(reverse("cart"))

    try:
        new_order = Order.objects.get(cart=cart)
    except Order.DoesNotExist:
        new_order = Order()
        new_order.cart = cart
        print new_order.cart
        new_order.user = request.user
        new_order.order_id = id_generator()
        new_order.save()
    except:
        new_order = None
        # work on some error message
        return HttpResponseRedirect(reverse("cart"))
    if new_order is not None:
        new_order.sub_total = cart.total
        new_order.save()

    try:
        address_added = request.GET.get("address_added")
    except:
        address_added = None

    if address_added is None:
        address_form = UserAddressForm()
    else:
        address_form = None

    current_addresses = UserAddress.objects.filter(user=request.user)
    billing_addresses = UserAddress.objects.get_billing_addresses(user=request.user)
    print billing_addresses
    ##1 add shipping address
    ##2 add billing address
    #3 add and run credit card 
    if new_order.status == "Finished":
        #cart.delete()
        del request.session['cart_id']
        del request.session['items_total']
        return HttpResponseRedirect(reverse("cart"))

    context = {
    "order":new_order,
    "address_form": address_form,
    "current_addresses": current_addresses,
    "billing_addresses": billing_addresses,
    }
    template = "orders/checkout.html"
    return render(request, template, context)

我的购物车应用模型:

from django.db import models

# Create your models here.
from products.models import Product, Variation

class CartItem(models.Model):
    cart = models.ForeignKey('Cart', null=True, blank=True)
    product = models.ForeignKey(Product)
    variations = models.ManyToManyField(Variation, null=True, blank=True)
    quantity = models.IntegerField(default=1)
    line_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
    notes = models.TextField(null=True, blank=True)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False, null=True)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True, null =True)

    def __unicode__(self):
        try:
            return str(self.cart.id)
        except:
            return self.product.title


class Cart(models.Model):
    total = models.DecimalField(max_digits=100, decimal_places=2, default=0.00)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)
    active = models.BooleanField(default=True)

    def __unicode__(self):
        return "Cart id: %s" %(self.id)

和购物车视图:

from django.shortcuts import render, HttpResponseRedirect
from django.core.urlresolvers import reverse

# Create your views here.

from products.models import Product, Variation

from .models import Cart, CartItem

def view(request):
    try:
        the_id = request.session['cart_id']
        cart = Cart.objects.get(id=the_id)
    except:
        the_id = None
    if the_id:

        new_total = 0.00
        for item in cart.cartitem_set.all():
            line_total = float(item.product.price) * item.quantity
            new_total += line_total

        request.session['items_total'] = cart.cartitem_set.count()
        cart.total = new_total
        cart.save()
        context = {"cart": cart}
    else:
        empty_message = "Your Cart is Empty, please keep shopping."
        context = {"empty": True, "empty_message": empty_message}

    template = "cart/view.html"
    return render(request, template, context)

def remove_from_cart(request, id):
    try:
        the_id = request.session['cart_id']
        cart = Cart.objects.get(id=the_id)
    except:
        return HttpResponseRedirect(reverse("cart"))

    cartitem = CartItem.objects.get(id=id)
    # cartitem.delete()
    cartitem.cart = None
    cartitem.save()
    return HttpResponseRedirect(reverse("cart"))



def add_to_cart(request, slug):
    request.session.set_expiry(120000)

    try:
        the_id = request.session['cart_id']
    except:
        new_cart = Cart()
        new_cart.save()
        request.session['cart_id'] = new_cart.id
        the_id = new_cart.id

    cart = Cart.objects.get(id=the_id)

    try:
        product = Product.objects.get(slug=slug)
    except Product.DoesNotExist:
        pass
    except:
        pass

    product_var = [] #product variation
    if request.method == "POST":
        qty = request.POST['qty']

        for item in request.POST:
            key = item
            val = request.POST[key]
            try:
                v = Variation.objects.get(product=product, category__iexact=key, title__iexact=val)
                product_var.append(v)
            except:
                pass
        cart_item= CartItem.objects.create(cart=cart, product=product)      
        if len(product_var) > 0:
            cart_item.variations.add(*product_var)
        cart_item.quantity = qty
        cart_item.save()


        return HttpResponseRedirect(reverse("cart"))

    return HttpResponseRedirect(reverse("cart"))     

PS:我是初学者尝试学习 django。

【问题讨论】:

  • 你到底想问什么?
  • 处理匿名用户的结帐请求而不使用 login_required 装饰器
  • 但是你不需要使用@login_required在您必须将某些视图的访问权限限制为已注册和经过身份验证的用户时才使用它,这不是您的情况。

标签: python django


【解决方案1】:

您是否考虑过像django-oscar 这样的电子商务框架?

至于@login_required,您可以添加login_url 参数以重定向到您的匿名结帐网址。即:

@login_required(login_url='/checkout/new-user')

并将 /checkout/new-user URL 连接到 urls.py 模块中的匿名结帐视图。

【讨论】:

  • 不,我没有。除了这个之外,我还有所有其他功能都在工作,所以我只是想用 django-oscar 来修改它
  • 之所以需要提到框架,是因为 DIY 方法会增加很多功能和安全测试。
  • 谢谢你。我一定会去看看的。