9

私は Python と Django はまったく初めてで、Stack Overflow もまったく初めてなので、ここでルールを破らないことを望み、質問形式を尊重します。

Django (Python 3.3.0、Django 1.5a1) でカスタム モデル フィールドを実装しようとして問題に直面していますが、同様のトピックは見つかりませんでした。

プレイヤーがいて、彼は(カードの)手札を持っています。Hand は CardContainer から継承します。これは基本的に、いくつかのヘルパー関数 (ここでは非表示) を持つカードのリストです。対応するコードは次のとおりです。

from django.db import models


class Card:
    def __init__(self, id):
        self.id = id


class CardContainer:
    def __init__(self, cards=None):
        if cards is None:
            cards = []
        self.cards = cards


class Hand(CardContainer):
    def __init__(self, cards=None):
        super(Hand, self).__init__(cards)


class CardContainerField(models.CommaSeparatedIntegerField):
    __metaclass__ = models.SubfieldBase

    def __init__(self, cls, *args, **kwargs):
        if not issubclass(cls, CardContainer):
            raise TypeError('{} is not a subclass of CardContainer'.format(cls))

        self.cls = cls
        kwargs['max_length'] = 10
        super(CardContainerField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if not value:
            return self.cls()

        if isinstance(value, self.cls):
            return value

        if isinstance(value, list):
            return self.cls([i if isinstance(i, Card) else Card(i) for i in value])

        # String: '1,2,3,...'
        return self.cls([Card(int(i)) for i in value.split(',')])

    def get_prep_value(self, value):
        if value is None:
            return ''

        return ','.join([str(card.id) for card in value.cards])


class Player(models.Model):
    hand = CardContainerField(Hand)

しかし、プレーヤーを取得すると、次のように言いましょう: Player.objects.get(id=3).hand、インスタンスを取得する代わりにHand(またはCardContainerインスタンスをまったく取得することさえありません!)、「1,2,3」のような整数のカンマ区切りの文字列を取得しているだけです。データベースでは問題ありません(データベースで見たい形式です)...

to_python が呼び出されないように思われるため、返されるデータは生の値、つまり文字列です。私がこのタイプの問題を検索したとき、人々は見落としていました__metaclass__ = models.SubfieldBase... 私もそれを見落としていればよかったのですが、ちょっと簡単すぎたでしょう! 些細なことを見逃したのでしょうか、それとも全体的に間違っていますか? :D

どうもありがとう!!

4

2 に答える 2

11

Python 3 では、module-global__metaclass__変数はサポートされなくなりました。以下を使用する必要があります。

class CardContainerField(models.CommaSeparatedIntegerField, metaclass=models.SubfieldBase):
   ...
于 2012-12-29T11:29:18.650 に答える
0

Django 1.10 以降の場合

class CardContainerField(models.CommaSeparatedIntegerField):
    def from_db_value(self,value, expression, connection, context):
      .......
于 2016-10-20T18:35:56.103 に答える