django继承自助手类

时间:2018-01-05 17:45:02

标签: python django oop

我想在我的模特中为BTC和LTC硬币制作钱包。但是,由于大多数代码与coin_nametx_fees相同。
所以,我想创建一个这样的辅助类:

电子钱包课(摘录)

class Wallet(models.Model):
    name = models.CharField(max_length=80, editable=False)
    trading_amt = models.FloatField(default=0, validators=[MinValueValidator(0.0), ])
    wallet_amt = models.FloatField(default=0, validators=[MinValueValidator(0.0), ])
    wallet_address = models.CharField(default='', blank=True, max_length=100)
    coin_name = ''  <-- will it serve the purpose ?
    tx_fee = 0      <-- and this ?

    def __init__(self, coin_name, tx_fee):
        self.coin_name = coin_name
        self.tx_fee = tx_fee

    @transaction.atomic
    def moveToTrading(self, amount):
        if amount > self.wallet_amt:
            return "Insufficient balance"
        else:
            self.trading_amt += amount
            self.wallet_amt -= amount
            return True

    @transaction.atomic
    def withdraw(self, amount, withdrawal_wallet_addr):
        if amount > self.wallet_amt:
            return "Insufficient balance"
        else:
            # First check if withdrawal address entered by user is
            # correct, using wallet daemon , if not return error
            if check_wallet(withdrawal_wallet_addr, "btc"):
                # initiate checkout
                return initiate_checkout(withdrawal_wallet_addr, self.coin_name, self.tx_fee)
            else:
                return "Incorrect Wallet address"

    def save(self, *args, **kwargs):
        self.name = gen_random_string('btc_wallet')
        super(Wallet, self).save(*args, **kwargs)

    def deposit(self, amount):
        self.wallet_amt += amount

    def __unicode__(self):
        return self.name

    def __str__(self):
        return self.name

仅在创建钱包地址coin_name时使用name:_btc_wallet_&lt; 64 char随机字符串&gt; _
并且tx_fee作为常量存储在每个硬币的 helpers.py 中 因此,将它们保存在数据库中是没有意义的。

问题1:

我在OOP编程中是一个小菜鸟(我知道它们是什么,但是编码不多)所以很困惑这是什么才是正确的用法:

用法1:

class BtcWallet(Wallet):
    def __init__(self, coin_name, tx_fee):
        self.tx_fee = BTC_FEES
        self.coin_name = "BTC"
        super(BtcWallet, self).__init__(coin_name, tx_fee)

OR

class BtcWallet(Wallet):
    def __init__(self, coin_name, tx_fee):
        self.tx_fee = BTC_FEES
        self.coin_name = "BTC"

即。我是否需要初始化超级初始化程序

如果使用super,那么应该如何使用,例如:

super(BtcWallet, self).__init__(coin_name, tx_fee)

super(Wallet, self).__init__(coin_name, tx_fee)

问题2:

由于coin_nametx_fees未保存在数据库中,所以何时会失败?就像什么时候不接受这些价值。

也许,它不应该失败因为无论在哪里使用它都会有一个对象?

BtcWallet userprofile 模型的外键元素。如果我像这样使用它会失败  request.user.profile.BTC_wallet.withdraw()
(我可以在其中一个视图中使用它)

UserProfile模型(摘录)

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    joining_date = models.DateTimeField(default=timezone.now)
    BTC_wallet = models.OneToOneField(BtcWallet, on_delete=models.SET_NULL, related_name='profile', null=True,
                                      blank=True)

更新:

更改为新表单后(之前我的代码中没有任何钱包类,而钱包类是BtcWallet类),并将迁移结果转换为:

jame@vostro:~/mywebsite# python manage.py makemigrations account
You are trying to add a non-nullable field 'wallet_ptr' to btcwallet without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option: 

1 个答案:

答案 0 :(得分:0)

__ pycache __ ,#django的其中一个人帮助我解决了这个问题。

对于抽象类,钱包类必须是抽象类 Meta Class optionshere

原因

抽象类不会被制作成表格模型,并且可以作为辅助类使用。

新代码

class Wallet(models.Model):
    name = models.CharField(max_length=80, editable=False)
    trading_amt = models.FloatField(default=0, validators=[MinValueValidator(0.0), ])
    wallet_amt = models.FloatField(default=0, validators=[MinValueValidator(0.0), ])
    wallet_address = models.CharField(default='', blank=True, max_length=100)
    coin_name = ''
    tx_fee = 0

    @transaction.atomic
    def moveToTrading(self, amount):
        if amount > self.wallet_amt:
            return "Insufficient balance"
        else:
            self.trading_amt += amount
            self.wallet_amt -= amount
            return True

    @transaction.atomic
    def withdraw(self, amount, withdrawal_wallet_addr):
        if amount > self.wallet_amt:
            return "Insufficient balance"
        else:
            # First check if withdrawal address entered by user is
            # correct, using wallet daemon , if not return error
            if check_wallet(withdrawal_wallet_addr, self.coin_name):
                # initiate checkout
                return initiate_checkout(withdrawal_wallet_addr, self.coin_name, self.tx_fee)
            else:
                return "Incorrect Wallet address"

    def save(self, *args, **kwargs):
        self.name = gen_random_string(self.coin_name.lower()+'_wallet')
        super(Wallet, self).save(*args, **kwargs)

    def deposit(self, amount):
        self.wallet_amt += amount

    def __unicode__(self):
        return self.name

    def __str__(self):
        return self.name

    class Meta:                 <-------Added this
        abstract = True

**和BtcWallet课程:**

class BtcWallet(Wallet):
    def __init__(self, *args, **kwargs):
        self.coin_name = "BTC"
        self.tx_fee = COINS[self.coin_name]['tx_fee']
        super(BtcWallet, self).__init__(*args, **kwargs)

注意

需要调用

super,因为我们要重写 init 方法,并且需要为每个被覆盖的函数调用它。

Python 2.x --> super(subclassName, self).__init__(*args, **kwargs)
Python 3.x --> super().__init__(*args, **kwargs)

由Raymond Hettinger在超级上查看this nice article,非常有帮助且明确。