如何向管理表单添加自定义功能?

时间:2016-08-05 12:15:17

标签: python django python-2.7 django-models django-admin

我希望每次管理员在quantity网站LibraryBook上添加图书时,都会在SingleBook中实施更新admin的功能。我一直在寻找这样做的方法,但无济于事。任何指针,包括文档链接将非常感谢。 这是我的代码:

#models.py
class LibraryBook(models.Model):
    book_title = models.CharField(max_length=100, blank=False)
    book_author_id = models.ForeignKey(BookAuthors, on_delete=models.CASCADE)
    category = models.ForeignKey(BookCategory, on_delete=models.CASCADE)
    quantity = models.IntegerField(blank=False, default=0)
    number_borrowed = models.IntegerField(default=0)

    def __unicode__(self):
        return unicode(self.book_title)

class SingleBook(models.Model):
    serial_number = models.CharField(primary_key=True , max_length=150, blank=False)
    book_id = models.ForeignKey(LibraryBook, on_delete=models.CASCADE)
    is_available_returned = models.BooleanField(default=True)
    is_borrowed = models.BooleanField(default=False)

    def __unicode__(self):
        return unicode(self.book_id)

#admin.py
class SingleBookAdmin(admin.ModelAdmin):
    list_display = ('book_id', 'serial_number')

class LibraryBookAdmin(admin.ModelAdmin):
    list_display = ('book_title', 'book_author_id', 'quantity')
    search_fields = ('book_title', 'book_author_id')
    fields = ('book_title', 'book_author_id', 'quantity')

PS:我省略了导入和admin.site.register代码

Django==1.9.8
django-material==0.8.0
django-model-utils==2.5.1
psycopg2==2.6.2
wheel==0.24.0

2 个答案:

答案 0 :(得分:3)

覆盖save_model

如果您只想在管理员更新记录时进行更改,最好的方法是覆盖ModelAdmin中的save_model方法

  

save_model方法给出了HttpRequest,一个模型实例,一个   ModelForm实例和基于是否添加的布尔值   或改变对象。在这里,您可以进行任何预存或后保存   操作

class SingleBookAdmin(admin.ModelAdmin):
    list_display = ('book_id', 'serial_number')

    def save_model(self, request, obj, form, change):
       admin.ModelAdmin.save_model(self, request, obj, form, change)


       if obj.is_borrowed:
          do something to obj.book_id.quantity
       else:
          do something to obj.book_id.quantity

post_save信号

from django.dispatch.dispatcher import receiver
from django.db.models.signals import post_save

@receiver(post_save, sender=SingleBook)
def user_updated(sender,instance, **kwargs):
    ''' Fired when a SingleBook is updated or saved
    we will use the opporunity to change quantity'''

    # your logic here

其他指针

另一方面,如果您想根据所有用户操作进行更改,那么捕获post_save信号就是您的选择。在任何一种情况下,您可能希望覆盖模型中的from_db方法以跟踪哪些字段已更改。

您可能还想将quantitynumber_borrowed更改为IntegerFields(除非您只使用sqlite,在这种情况下它并不重要)

同样book_author_id应该是book_author,而book_id应该是book(这不是规则,只是避免丑陋的book_id_id引用的约定)

答案 1 :(得分:0)

使用signals。只需将post_save信号附加到SingleBook模型,然后根据LibraryBook进行更新。 post_save信号采用created参数,因此您可以确定是新创建或编辑图书,并根据该图标应用您的操作。

同时附加post_delete信号以在删除SingleBook时减少计数器。

为了避免竞争条件(当2位管理员同时添加图书时),我建议在更改update计数器时使用queryset F方法和LibraryBook ,例如:

LibraryBook.objects.filter(id=single_book.book_id_id).update(quantity=F('quantity') + 1)

这样做将确保在数据库级别执行实际的数学运算。