Show complex entity in Django Admin interface

I'm stuck trying to figure how to do the following:

I have a few entities:

PurchaseItem (an item in user's cart), Order (an order - combines one or many PurchaseItems), OrderStatusHistory (that's status items for the Order - instead of changing, I create new ones to be able to retrospectively preview how status changed over time).

I don't want any of these to be created via admin - they are all created via public interface, but I have to show the Order and its attributes in the admin panel:

I need to be able to show list of orders. That's simple.

When I click on an order or something I want to be able to view the order's details: list of Purchase items.

I need to be able to change the status of the order - selecting from a drop down or something - however, this action show be triggering a new statusHistory item creation.

Is this all possible with admin interface or should I forget about it and create my own implementation with pages and all?

My models look like this:

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)  

The following inline setup doesn't work because Order doesn't have a FK to PurchaseItems:

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)

Part 1

Use Inlines, that's very straight forward and django excels at this.

Part 2

Sure you could override your save for example and check if the drop down item has changed. If it has, generate your order status history object.

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)

You could do the same thing in the ModelAdmin too

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

Part 1:

You can 'nest' models with TabularInline or StackedInline admin models.

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

class OrderStatusAdmin(admin.StackedInline):
    model = OrderStatus

class PurchaseAdmin(admin.StackedInline):
    model = PurchaseItem

More information can be found here: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#inlinemodeladmin-objects

Part 2:

I need to be able to change the status of the order - selecting from a drop down or something - however, this action show be triggering a new statusHistory item creation.

For this you can use signals. There is a post_save and pre_save. So each time you save an order you can add extra logic. The pre_save signal has a sender and an instance so I think you can compare the status of the sender and the instance to be saved and if it changed you can add an other OrderStatus model.

More info can be found here: http://docs.djangoproject.com/en/dev/ref/signals/#pre-save

链接地址: http://www.djcxy.com/p/65422.html

上一篇: Django管理员:根据FK'd属性进行内联排序

下一篇: 在Django Admin界面中显示复杂的实体