[英]How to add a custom method to a model field in Django?
I have two models that will use the same CardNumberField()
to store credit card numbers.我有两个模型将使用相同的CardNumberField()
来存储信用卡号。 How can I add a custom method to the field to mask the card numbers?如何在字段中添加自定义方法来屏蔽卡号?
I have created the CardNumberField()
which inherits from models.Charfield
:我创建了继承自models.Charfield
的CardNumberField()
:
# CARD NUMBER FIELD
class CardNumberField(models.CharField):
description = _('card number')
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 19
super().__init__(*args, **kwargs)
The CardNumberField()
is then imported and used in my customers/models.py :然后将CardNumberField()
导入并在我的customers/models.py中使用:
# CARD MODEL
class Card(models.Model):
number = CardNumberField()
...
def __str__(self):
return 'Card [{number}]'.format(number=self.number)
...and in my transactions/models.py : ...在我的transactions/models.py 中:
# TRANSACTION MODEL
class Transaction(models.Model):
card_number = CardNumberField()
...
def __str__(self):
return 'Transaction ...'
So, how can I add the following method to my CardNumberField()
to be used by both of my models?那么,如何将以下方法添加到我的CardNumberField()
以供我的两个模型使用?
def masked_number(self):
# display masked card number
number = self.number
return number[-4:].rjust(len(number), '#')
Also, how will I grab this field method in a DRF serializer class?另外,我将如何在 DRF 序列化器 class 中获取此字段方法?
Use an abstract model instead, making a field subclass is useful to create completely new columns types, not for this purpose.使用抽象 model 代替,制作字段子类对于创建全新的列类型很有用,而不是为此目的。
class ModelWithCardNumber(models.Model):
card_number = models.CharField(max_length=19)
@property
def masked_number(self):
return self.card_number[-4:].rjust(len(number), '#')
class Meta:
abstract = True
class Card(ModelWithCardNumber):
def __str__(self):
return 'Card [{number}]'.format(number=self.number)
class Transaction(ModelWithCardNumber):
def __str__(self):
return 'Transaction ...'
Now in your serializer you can access Card.masked_number
and Transaction.masked_number
.现在在您的序列化程序中,您可以访问Card.masked_number
和Transaction.masked_number
。
You can override the contribute_to_class
method to not only contribute the field, but also include an extra method:您可以覆盖contribute_to_class
方法,不仅可以贡献该字段,还可以包含一个额外的方法:
from functools import partialmethod
def _mask_number(self, field):
number = getattr(self, field.attname)
return number[-4:].rjust(len(number), '#')
# CARD NUMBER FIELD
class CardNumberField(models.CharField):
description = _('card number')
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 19
super().__init__(*args, **kwargs)
def contribute_to_class(self, cls, name, **kwargs):
super().contribute_to_class(cls, name, **kwargs)
setattr(
cls, f'masked_{self.name}',
partialmethod(_mask_number, field=self)
)
If you add a field foo
to a model class, it will automatically add a masked_ foo
method to that class.如果将字段foo
添加到 model class 中,它将自动向该 class 添加masked_ foo
方法。 This thus also means that if you have two or more CardNumberField
s, it will add two or more masked_ foo
methods.因此,这也意味着如果您有两个或更多CardNumberField
,它将添加两个或更多masked_ foo
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.