在Django Admin界面中显示复杂实体

时间:2011-03-26 15:55:42

标签: django django-models django-admin

我不知道如何做以下事情:

我有几个实体:

PurchaseItem(用户购物车中的项目), 订单(订单 - 组合一个或多个PurchaseItems), OrderStatusHistory(这是订单的状态项 - 而不是更改,我创建新的,以便能够回顾性地预览状态随时间变化的方式)。

我不希望通过管理员创建任何这些 - 它们都是通过公共界面创建的,但我必须在管理面板中显示订单及其属性:

我需要能够显示订单列表。这很简单。

当我点击订单或其他东西时,我希望能够查看订单的详细信息: 购买物品清单。

我需要能够更改订单的状态 - 从下拉菜单中选择 - 但是,此操作显示会触发新的statusHistory项目创建。

管理界面是否可以实现这一切,还是应该忘记它并使用页面创建我自己的实现?

我的模特看起来像这样:

class Order(models.Model):
    dateCreated = models.DateTimeField(null=False,default=datetime.now())
    items = models.ManyToManyField(PurchaseItem)
    user_name = models.CharField(null=True,blank=True,max_length=200)
    phone = models.CharField(null=False,blank=False,max_length=11,validators=[validate_phone])
    phone_ext = models.CharField(null=True,blank=True,max_length=5,validators=[validate_phone_ext])
    email = models.CharField(null=False,blank=False,max_length=100,validators=[validators.EmailValidator])
    addressCity = models.CharField(null=False,blank=False,max_length=100)
    addressStreet = models.CharField(null=False,blank=False,max_length=200)
    notes = models.TextField(null=True,blank=True)
    accessKey = models.CharField(max_length=32,default=CreateAccessKey())

class PurchaseItem(models.Model):
    picture = models.ForeignKey(Picture, null=False)
    paperType = models.CharField(null=False,max_length=200)
    printSize = models.CharField(null=False,max_length=200)
    quantity = models.IntegerField(default=1, validators=[validators.MinValueValidator(1)])
    price = models.DecimalField(decimal_places=2,max_digits=8)
    dateCreated = models.DateTimeField(null=False)
    cost = models.DecimalField(decimal_places=2,max_digits=8)

class OrderStatusHistory(models.Model):
    orderId = models.ForeignKey(Order)
    dateSet = models.DateTimeField(null=False,default=datetime.now())
    status = models.IntegerField(choices=OrderStatus,default=0,null=False,blank=False)
    comment = models.TextField(null=True,blank=True)  

以下内联设置不起作用,因为Order没有到PurchaseItems的FK:

class OrderStatusHistoryAdmin(admin.StackedInline):
    model = OrderStatusHistory

class PurchaseItemAdmin(admin.StackedInline):
    model = PurchaseItem

class OrderAdmin(admin.ModelAdmin):
    model = Order
    inlines = [OrderStatusHistoryAdmin,PurchaseItemAdmin]

admin.site.register(Order,OrderAdmin)

2 个答案:

答案 0 :(得分:1)

第1部分:

您可以使用TabularInline或StackedInline管理模型“嵌套”模型。

class OrderAdmin(admin.ModelAdmin):
    model = Order
    inlines = [
        OrderStatusAdmin,
        PurchaseItemAdmin
    ]

class OrderStatusAdmin(admin.StackedInline):
    model = OrderStatus

class PurchaseAdmin(admin.StackedInline):
    model = PurchaseItem

可在此处找到更多信息:http://docs.djangoproject.com/en/dev/ref/contrib/admin/#inlinemodeladmin-objects

第2部分:

  

我需要能够更改订单的状态 - 从下拉菜单中选择 - 但是,此操作显示会触发新的statusHistory项目创建。

为此您可以使用信号。有一个post_save和pre_save。因此,每次保存订单时,您都可以添加额外的逻辑。 pre_save信号有一个发送者和一个实例,所以我认为你可以比较发送者和要保存的实例的状态,如果它改变了,你可以添加另一个OrderStatus模型。

更多信息可以在这里找到: http://docs.djangoproject.com/en/dev/ref/signals/#pre-save

答案 1 :(得分:1)

第1部分

使用Inlines,这是非常直接的,django擅长于此。

第2部分

当然,您可以覆盖保存示例并检查下拉项是否已更改。如果有,请生成订单状态历史记录对象。

def save(self, *args, **kwargs):
    if self._initial_data['status'] != self.__dict__['status']:
        self.orderstatushistory_set.create("Status Changed!")
    super(Order, self).save(*args, **kwargs)

你也可以在ModelAdmin中做同样的事情

def save_model(self, request, obj, form, change):
    if obj._initial_data['status'] != obj.__dict__['status']:
         # create whatever objects you wish!