Django在视图中向formset添加表单

时间:2016-08-27 20:42:48

标签: django formset

我遇到了设计问题。

想象一下订单模型和材料模型,

class Material(models.Model):
    material_code = models.CharField(max_length=40)
    standard_price = models.DecimalField()

class Order(models.Model):
    customer = models.ForeignKey(Customer)


class OrderItems(models.Model):
    order = models.ForeignKey(Order)
    material = models.ForeignKey(Material)
    price = models.DecimalField()

在我的订单详情视图中,我使用inlineformset_factory(Order,OrderItems)填充订单项

我想要的行为如下:

如果用户想要添加更多订购项目,我想将用户重定向到材料列表页面,用户选择一种或多种材料并确认,然后我将其重定向到新添加项目的订单详细信息视图。

我正在考虑这些工作,例如django管理中心页面的操作。

在添加订购新订单之前,我还想从物料standard_price设置订购项价格,这意味着我想在将其添加到订单项之前修改formsets值。

我想问的问题是,是否有一种更简单的方法来实现这一点,似乎将formset数据存储到会话并使用新项目重新填充formset并不容易。我会考虑解决这个问题的另一种方法。

我不想要js解决方案,想象一下我的订单模型上的字段,grandtotal,我可以计算总项目数量,用js解决方案我可能需要用js做计算逻辑,用户添加项目并更改价格然后我用js进行大计算。这是我想要避免的。

3 个答案:

答案 0 :(得分:5)

根据您提供的说明,我找不到 formsets 的用例。

您只需要一个列出材料的材料目录页面。每种材料都可以添加到当前购物车中,这是通过Ajax调用传递到材料PK的URL来完成的,因此该Ajax调用的视图可以创建购物车并将该材料添加到购物车。

最后你需要一个OrderDetail,你需要一个关于所有材料的forloop,目前在用户购物车中。

您可以先在数据库中完全实现它,并为Cart定义关系模型,这实际上是您已经实施的Order类。

然后你可以添加一个缓存层来限制对DB的写入/删除/更新,使用django会话(考虑到你不在数据库中存储会话,这会带来性能提升!)

总而言之,您可能需要的是(我使用购物车的概念,暗示用户只能有一个有效订单,如果您的要求不同,则很容易可以更改为您的订单模型提供的内容):

数据模型:

class Cart:
     user = 1to1(User, related_name='cart') # Can be a FK if you want several active orders
     is_approved = Boolean # To tell if the order is considered Over or is still open
     created_at = DateTimeField
     ...

class Material:
     orders = M2M(Cart, through=CartItem)
     ...

class CartItem:
     cart = FK(Cart)
     material = FK(Material)
     ...

<强>查看:

def list_materials(request):
    returns_rendered_template_with(materials=Material.objects.all())

#Ajax method, called via Post, you probably need a way to also delete, or edit (number of materials to order ?)
def add_material_to_cart(request, material_id):
    cart = Cart.objects.get_or_create(user=request.user)
    material = Material.objects.get(pk=material_id)
    CartItem(material=material, cart=cart).save()

def order_detail_view(request):
    cart = user.cart
    cart_items = CartItems.objects.filter(cart=cart)
    returns_rendered_template_with(cart_items=cart_items)

<强>模板:

material_list.html

....
{% for item in materials %}
       {% show material info, such as price, availability, ... %}
       <button data-pk={{item.pk}}, ...> to call add_material_to_cart </button>
{% endfor %}

order_detail.html

....
{% for item in cart_items %}
       {% show each cart_item.material and its information + whatever you need %}
{% endfor %}

这是你能实现的最基本的形式,我明白,你想要的 您可以将多个这些视图合并在一起,您可以在会话中实现&#34; &#34;解决方案,不需要Cart和CartItem模型,只是最终确定的订单持续存在,我不知道,Bill模型?订单历史 ?无论你想要什么。

答案 1 :(得分:1)

如果我理解你的意图,你想创建某种购物车,而你不想为尚未放置的订单创建数据库条目。

我的建议是创建一个Cart模型和一个CartItem模型,用于存储有关购物车中当前商品的信息。 当客户下订单时,您可以使用购物车及其商品中相应的Order个实例创建新的OrderItem实例,并保留该实例。

CartCartItem可以是存储在数据库中的Django模型,也可以是普通的Python类,并将它们序列化以便在会话中存储。

将它们存储在数据库中可能更容易,但很可能比基于会话的解决方案生成更多数据库查询。这是否是一个问题取决于您的服务器容量和预期负载。这种方法在Oscar实现,这是Django的电子商务框架。

答案 2 :(得分:0)

您可以通过“添加动态字段”将其简化为订单明细窗体。

当用户点击“添加素材”按钮时,系统会添加一个新字段(例如带有素材列表的program tailrec use iso_fortran_env implicit none integer(int64) :: acc, x acc = 0 x = 500000000 call tailrecsum(x, acc) print *, acc contains recursive subroutine tailrecsum (x, running_total) integer(int64), intent(inout) :: x integer(int64), intent(inout) :: running_total integer(int64) :: ret_val if (x == 0) return running_total = running_total + x x = x - 1 call tailrecsum (x, running_total) end subroutine tailrecsum end program 字段)。

link将帮助您完成任务。