在电子商务应用中扩展Django用户模型

7

我有一个Django电子商务项目,一直运行良好,直到我决定改进它。我允许用户在某些服务上下订单,但每次下订单时,他们都必须输入他们的详细信息(姓名、电子邮件、地址等),因此我决定升级应用程序,以便用户可以添加他们的账单地址,并且可以在订单中引用或作为访客继续。

模型

class Order(models.Model):
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50)
    email = models.EmailField()
    address = models.CharField(max_length=250) 
    postal_code = models.CharField(max_length=20) 
    city = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True) 
    updated = models.DateTimeField(auto_now=True) 
    paid = models.BooleanField(default=False)

class OrderItem(models.Model):
    order = models.ForeignKey(Order, related_name='items')
    product = models.ForeignKey(Product,related_name='order_items')
    price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.PositiveIntegerField(default=1)

视图

def order_create(request):
    cart = Cart(request)
    if request.method == 'POST':
        form = OrderCreateForm(request.POST) 
        if form.is_valid():
            order = form.save() 
            for item in cart:
            OrderItem.objects.create(order=order, product=item['product'],price=item['price'], quantity=item['quantity'])
            cart.clear()
            return render(request,'order/created.html', {'order': order})
    else:
        form = OrderCreateForm()
    return render(request, 'order/create.html',{'cart': cart, 'form': form})

我为用户创建了一个账户应用程序并扩展了Django用户模型,以便用户可以注册地址和手机号码,这样用户就不必每次下订单时都输入这些信息。
我的新数据模型如下:
class Order(models.Model):
    account = models.ForeignKey(Account, related_name='user_account')
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    paid = models.BooleanField(default=False)
    coupon = models.ForeignKey(Coupon, related_name='orders',null=True,blank=True)
    discount = models.IntegerField(default=0,validators=[MinValueValidator(0), MaxValueValidator(100)])

我对如何编写视图感到困惑。任何帮助都将有所帮助,我还有其他问题。

def admin_order_detail(request, order_id):
    order = get_object_or_404(Order, id=order_id)
    #account = Account.objects.filter(request.user)
    context = {
        'order': order,
        }
    template = 'order/detail.html'
    return render(request,template,context)

我希望能够在管理区域查看订单详细信息,但我只能扩展全名、电子邮件和电话号码。如果有帮助,将不胜感激。提前致谢。

GitHub上的所有代码副本:https://github.com/Olar19/ecommerce


可能是 在 Django 中使用自定义字段扩展用户模型 的重复问题。 - itzMEonTV
这不是一个重复的内容。 - King
4个回答

1
您正在尝试做的是非常普遍和合理的事情。有两种主要方法可以向Django用户模型添加附加信息。1)您可以覆盖django用户模型并定义自己的自定义模型,或2)您可以创建另一个模型,例如UserData,并使UserData与Django的User模型具有OneToOneField连接。因此,对于每个用户,都有一个关联的UserData存储所需的附加字段信息。在现有项目中执行选项1很困难且不建议这样做,因此我建议转换为选项2。
Django文档非常详细地介绍了如何创建UserData模型并将其链接到User模型。您可以在此处阅读有关它的信息。这种方法的一个关键说明是:a)如果存在任何现有用户,则需要返回并为所有现有用户创建UserData对象;b)每次用户在您的网站上注册用户帐户时都需要确保创建UserData对象。
class UserData(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, default=0, related_name="userdata")
    # other fields ...

现在在您的视图中,您可以这样访问用户数据:
def admin_order_detail(request):
    ud = request.user.userdata

当您想要在视图中访问用户数据时,它就会起作用。
我刚刚查看了您的代码,发现您目前没有使用Django的用户系统进行用户注册和登录。我认为第一步是阅读django文档中关于用户认证系统的部分(here)。然后,尝试将用户认证集成到您的应用程序中。最后,您可以创建一个自定义userdata类来扩展用户模型。
祝好运!

我正在使用Django-allauth进行身份验证。扩展用户模型不是我面临的问题。问题在于如何创建一个结账系统,该系统将获取订购的物品和价值,并检查用户是否输入了送货地址或用户是否想要创建另一个送货地址以便在继续付款之前选择任何一个。 - King
你可以在我的 Github 上查看我当前的代码,链接已经包含在问题中了。 - King

1
这是一个很好的想法,利用内置的用户对象。Django非常“电池包含”,这意味着它的开箱即用功能比如Flask更多,对我来说,其中一个重要部分就是用户认证系统。
通常情况下,您将使用一对一字段扩展用户对象,在您的上下文中看起来像是账户对象。 有关一对一字段的更多详细信息(来自文档) 如果您是B2B而不是B2C,则可能希望让账户对象包含公司名称,然后将员工分配给该账户,其中员工对象将成为从用户扩展的对象。
因此,假设账户对象看起来像:
class Account(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    ...

你可以从订单对象中访问账户和用户对象。
order = get_object_or_404(Order, id=order_id)
username = order.user_account.username

或者用于权限类型的东西。
orders = Order.objects.filter(user_account__user = request.user)

我认为你无法访问 order.user_account,因为 related_name 用于反向关系。此外,在 Order.objects.filter(user_account__user = request.user) 中。 - itzMEonTV
我感觉很蠢,请有人帮帮我。订单对象与账户对象存在下游关系。而账户与用户之间存在一对一的下游关系。因此,如果您使用账户而不是用户账户,它不会起作用,对吗?换句话说,我认为如果您使用“账户”而不是“用户账户”引用账户,它将起作用。如果它不起作用,我会构建一个虚拟应用程序并查看为什么它不起作用。对于这个错误的解决方案,我很抱歉。 - sahutchi

0

你可以使用

order.account.user

如果您想从订单加入到用户,必须使用账户(字段名称与相关名称无关)。

如果您想从账户实例加入到订单,可以使用以下内容:

account.user_account.all()

相关名称是反转的访问名称。从相关对象访问

因此,最好将帐户字段的相关名称命名为订单


0

我认为你应该创建一个扩展AbstractUser的Account模型,其中包含Email和Address作为OneToMany字段,以允许一个用户拥有多个地址。 Address可以是一个模型,其字段如下:

名称,地址行1,地址行2,邮政编码,城市,州,用户(fk)

或者是一个包含所有信息和用户fk的单个文本字段。

每当用户选择他的一个地址时,您可以将地址条目添加到相应订单的Order-model中,这使得客户可以从已提供的一个或多个地址中进行选择。

class Order(models.Model):
    account = models.ForeignKey(Account, related_name='user_account')
    address = models.ForeignKey(Address, related_name='address')
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    paid = models.BooleanField(default=False)
    coupon = models.ForeignKey(Coupon, related_name='orders',null=True,blank=True)
    discount = models.IntegerField(default=0,validators=[MinValueValidator(0), MaxValueValidator(100)])

这还使我们能够通过order.account和order.address检索给定订单的账户详细信息和地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接