2

不确定这是否可行,但在Django Admin 的购物车(模型类)详细视图中,我想合计我的所有 TabularInline条目模型类小计,并将该值保存到我的购物车的 total_price属性。有没有办法做到这一点,或者以某种方式使用过滤器或表单小部件将所有小计添加在一起以达到相同的目的?提前感谢您的帮助!

下面是我想做的一个例子。您可以在总价字段中看到我手动输入了 130(小计:90 + 20 + 20 = 130)。我希望每次从库存中添加条目并编辑其数量时自动计算此值。

在此处输入图像描述

到目前为止,在我的 admin.py 中,我有一个 TabularInline 管理类,它通过将每个条目的数量乘以其各自的价格来返回每个条目的小计。然后我的 CartAdmin 类在购物车模型详细信息视图中显示该内联关系。

管理员.py

class EntryInline(admin.TabularInline):
    model = Entry
    extra = 0
    readonly_fields = ['subtotal']
    exclude = ['price']
    def subtotal(self, obj):
        return "$" + str(obj.quantity * obj.inventory.price)


class CartAdmin(admin.ModelAdmin):
    inlines = [EntryInline]
    fieldsets = (
        (None, {
            'fields':('user', 'total_price')
            }),
    )

模型.py

class Inventory(models.Model):
    quantity        = models.IntegerField()
    price           = models.DecimalField(max_digits=5, decimal_places=2)


class Cart(models.Model):
    user            = models.OneToOneField(User)
    total_price     = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True)


class Entry(models.Model):
    cart            = models.ForeignKey(Cart, related_name="entries")
    inventory       = models.ForeignKey(Inventory, related_name="entries")
    quantity        = models.PositiveSmallIntegerField(default=1)
    price           = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True)
4

3 回答 3

1

您可以尝试在购物车管理员中获取 total_price 并将该字段填充为:

class CartAdmin(admin.ModelAdmin):
    inlines = [EntryInline]
    fieldsets = (
    (None, {
        'fields':('user', 'total_price')
        }),
    )

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        # check if the cart object exists
        if obj:
            try:
                _price = Entry.objects.filter(cart=obj).aggregate(sum=Sum(F('quantity')*F('inventory__price'), output_field=FloatField()))
                total = _price['sum']
                obj.total_price = total
            except:
                pass
    return form

关于您的 Import error ,将 F 和 Sum 导入为:

from django.db.models import Sum, F

或者,如果您想要更多动态控制,以便每当用户编辑内联条目中的数量时,total_price 应该会自动更新,您可以为其编写自定义 javascript。

希望能帮助到你。

于 2018-10-03T09:06:44.457 回答
0

以下是我在管理员中保存以更新总数后用来刷新页面的内容:

购物车.js

if (!$) {
    $ = django.jQuery;
 }
function addSecs(d, s) {
    return new Date(d.valueOf() + s * 1000);
}
function doRun() {
    document.getElementById("msg").innerHTML = "Processing JS...";
    setTimeout(function() {
        start = new Date();
        end = addSecs(start, 5);
        do {
            start = new Date();
        } while (end - start > 0);
        document.getElementById("msg").innerHTML = "Finished Processing";
    }, 10);
 }
$(function() {
    $(".change_form_save").click(doRun);

    if (window.localStorage) {
        if (!localStorage.getItem("firstLoad")) {
            localStorage["firstLoad"] = true;
            window.location.reload();
        } else localStorage.removeItem("firstLoad");
    }
});

然后在我的 CartAdmin(admin.ModelAdmin) 类下的 admin.py 中:

class Media:
    js = ('js/cart.js',)
于 2018-10-30T05:09:33.267 回答
0

Welp,当我在管理详细信息视图中编辑数量以查看购物车总价服务器端的更新更改时,我仍在研究一种刷新浏览器发出 AJAX 请求的方法。不知道这需要多长时间,但我会在弄清楚后立即更新这个答案。

同时,这是我获得小计和总计的方法:


models.py中,我在 Entry 模型中添加了一个“小计”字段:

subtotal = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)

admin.py 中:

class EntryInline(admin.TabularInline):
    model = Entry
    extra = 0
    # calls my helper method
    readonly_fields = ['get_subtotal']
    # exclude redundant field being replaced by helper method
    exclude = ['subtotal']


    # gets subtotal of each entry
    def get_subtotal(self, obj):
        # for a given entry, find that id
        entry = Entry.objects.get(id=obj.id)
        # subtotal the entry quantity * its related price
        entry_subtotal = obj.quantity * obj.inventory.price
        # check if entry obj has a subtotal and try to save to db
        if entry.subtotal != entry_subtotal:
            try:
                entry.subtotal = entry_subtotal
                entry.save()
            except DecimalException as e:
                print(e)
        # return a str representation of entry subtotal
        return "$" + str(entry_subtotal)
    # set helper method's description display
    get_subtotal.short_description = 'subtotal'


# initialization of variable
total_price = 0

class CartAdmin(admin.ModelAdmin):
    model = Cart
    inlines = [EntryInline]
    # calls get_total helper method below
    readonly_fields = ['get_total']
    exclude = ['total_price']


    def get_total(self, obj):
        # extend scope of variable
        global total_price
        # get all entries for the given cart
        entries = Entry.objects.filter(cart=Cart.objects.get(id=obj.id))
        # iterate through entries
        for entry in entries:
            # if entry obj has a subtotal add it to total_price var
            if entry.subtotal:
                total_price += entry.subtotal
        print(obj.total_price)
        # assign cart obj's total_price field to total_price var
        obj.total_price = total_price
        # save to db
        obj.save()
        # reset total_price var
        total_price = 0
        # return cart's total price to be displayed
        return obj.total_price
    # give the helper method a description to be displayed
    get_total.short_description = 'total'

**需要注意的一点是,当我编辑数量并保存时,小计会动态加载,因为它使用了辅助方法。我仍然需要再次刷新浏览器才能保存到数据库,但是显示仍然存在。我不确定为什么 get_total() 的工作方式不同;没有显示,我必须刷新浏览器才能保存到数据库。逻辑似乎不一致...

于 2018-10-04T21:42:24.943 回答