【问题标题】:How to add custom function to admin forms?如何在管理表单中添加自定义功能?
【发布时间】:2016-12-11 20:32:54
【问题描述】:

我想实现一个功能,每次管理员在admin 网站上的SingleBook 添加一本书时,更新LibraryBook 中的quantity。我一直在寻找这样做的方法,但无济于事。任何包括文档链接在内的指针将不胜感激。 这是我的代码:

#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

【问题讨论】:

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


    【解决方案1】:

    覆盖 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 引用的约定)

    【讨论】:

    • 如何保存更改?
    • 在 ModelAdmin.save_model 中?它由对 super 的调用处理。相关模型可以通过obj.book_id.save()保存
    【解决方案2】:

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

    SingleBook 被移除时,还附加post_delete 信号以减少计数器。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-15
      • 2018-03-07
      • 2017-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多