如何在Django admin中引入一个模型class方法

How to introduce a model class method in Django admin

我有一个具有 class 方法的模型。在测试 class 方法时,可以根据我的需要更改模型实例。问题是在管理员中使用此 class 方法。当应用程序无法支付滞纳金时,将创建另一笔交易来改变余额。模型中的方法用@class方法装饰器装饰:

class Transactions(models.Model):

    application = models.ForeignKey(Application, 
    related_name='application_id', blank=True, null=True)
    transaction_type = models.CharField(max_length=56, 
    choices=TRANSACTION_TYPE, null=True)
    transaction_source = models.CharField(max_length=56, 
    choices=TRANSACTION_SOURCE, null=True)
    transaction_method = models.CharField(max_length=56, 
    choices=TRANSACTION_METHOD, null=True)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    created_date = models.DateField()
    posted_date = models.DateField()
    external_reference = models.CharField(max_length=100, null=True, 
    verbose_name='External Reference')

    def __unicode__(self):
        return self.application.forename + " " + 
        self.application.surname + "(" + str(self.application.id) + ")"

    @classmethod
    def late_payment_fee(cls, app, desired_action):
        """
        This function enacts a late payment fee to an application as a 
        transaction
        :param app: application the fee is going to be applied to
        :param desired_action: either True or False, when reversing the 
        fee the transaction shouldn't be deleted,
        just another transaction of the opposite effect in order to 
        help loans collection with tracking, True will
        enact a feee, False will reverse the fee
        :return: a transaction which is stored in the database
        """
        today = str(date.today())
        if desired_action:
            trans_type = MISSEDREPAYMENTFEE
            amount = float(12)
        else:
            trans_type = MISSEDREPAYMENTFEEREVERSAL
            amount = float(-12)
        cls.create_trasaction(app, trans_type, INTERNALBOOKING, 
        INTERNALBOOKING, amount, today, today, None)

我需要获取它,以便在状态更改时,或者在应用程序的管理员中选中复选框时,它会触发 class 方法。我在管理员中用谷歌搜索了覆盖模型,但找不到任何东西。这是管理员:

class ApplicationAdmin(ImportExportModelAdmin):
    resource_class = ApplicationResource
    search_fields = ['forename', 'surname']
    list_filter = ('status', 'underwritingresult', 'test', 'signed', 
    'mandateapproved', 'dealership', 'brand')
    list_select_related = ('instalment',)
    list_display = ('id', 'SPV_ID', 'forename', 'surname'......
    inlines = [
        InstalmentInline,
        AddressInline
    ]
    exclude = ['customer', 'accountnumber', 'sortcode']
    readonly_fields = ('Account_Number', 'Sort_Code', 'SPV_ID')

    def get_readonly_fields(self, request, obj=None):
        readonly_fields = []
        if obj.locked :
            for field in self.model._meta.fields:
                readonly_fields.append(field.name)
        else:
            readonly_fields = ('Account_Number', 'Sort_Code', 'SPV_ID')
        return readonly_fields

    def Account_Number(self, obj):
        return Decrypt(obj.accountnumber)

    def Sort_Code(self, obj):
        return Decrypt(obj.sortcode)

    def SPV_ID(self, obj):
        return obj.spv.id

    def has_delete_permission(self, request, obj=None):
        return False

非常感谢您阅读本文。

我现在找到了解决方案(抱歉,如果我最初的问题不是很清楚)。事实证明,我需要覆盖应用程序模型中的保存功能。但是,这样做时又提出了另一个问题。如果用户更改了一些良性的东西,比如客户的名字,那么 class 方法就会触发并创建新的交易,即使没有真正的改变。因此,我们必须覆盖模型中的 init 和保存功能,但仍然实际保存。对于此模型,我们有兴趣查看状态是否已更改或已收取滞纳金。为此,我们必须通过覆盖模型中的 init 方法来存储初始状态值:

__initial_status = None
__initial_fee_status = None

def __init__(self, *args, **kwargs):
    """
    This function overrides the __init__ function in order to
    save initial_status facilitating comparisons in the save function
    :param args: allows the function to accept an arbitrary number of 
    arguments and/or keyword arguments
    :param kwargs: same as above
    """
    super(Application, self).__init__(*args, **kwargs)
    self.__initial_status = self.status
    self.__initial_fee_status = self.feeadded 

现在我们已经存储了它们,我们可以通过我们的保存功能传递它们。如果有变化,我们可以使用 class 方法:

def save(self, *args, **kwargs):
    """
    This function overrides the standard save function. The application
    is still saved, however, other functions are fired when it is 
    saved.
    :return: creates reversal commission and dealership transactions
    if the status is CANCELLED
    """
    if self.signed and self.status != self.__initial_status:
        if self.status == Application.CANCELLED:
            Transactions.create_commision_trasaction(app=self, 
            reverse=True)
            Transactions.create_dealership_trasaction(app=self, 
            reverse=True)
        elif self.status == Application.OK:
            Transactions.create_commision_trasaction(app=self, 
            reverse=False)
            Transactions.create_dealership_trasaction(app=self, 
            reverse=False)

    if self.signed and self.feeadded != self.__initial_fee_status:
        if self.feeadded:
            Transactions.late_payment_fee(app=self, desired_action=True)
        elif self.feeadded is False:
            Transactions.late_payment_fee(app=self, desired_action=False)

    super(Application, self).save(*args, **kwargs)