代码之家  ›  专栏  ›  技术社区  ›  Charles Merriam

如何在Django模型中创建琐碎的自定义字段类型?

  •  3
  • Charles Merriam  · 技术社区  · 17 年前

    我试图在Django中创建一些映射到标准Django类型的类型。这个 custom model field documentation 涉及复杂的案件;我只是想用一堆方便的方法从类中存储一个基本的Django类型。

    例如,如果我在存储扑克牌,我想要这样的东西:

    class Card(object):
        """ A playing card.  """
        def as_number(self):
            """ returns a number from 1 (Ace of Clubs) and 52 (King of Spades)."""
            return self.number + self.suit_rank() * 13
        def __unicode(self): ...
        def is_highest(self, other_cards, trump=None):...
        def __init__(self, number, suit):  ...
         ...
    

    我希望我的模型有这样的东西:

    class my_game(models.Model):
        ante = models.IntegerField()
        bonus_card = Card()   # Really stored as an models.IntegerField()
        ....
    

    我希望答案看起来像是继承了正确的类型,为卡添加了一些特别命名的get/store字段,并重命名 初始化 ().有人有示例代码或更好的文档吗?

    3 回复  |  直到 17 年前
        1
  •  4
  •   jpwatts    17 年前

    我会用Django的PositiveIntegerField的一个子类来实现这一点:

    from django.db import models
    
    class Card(object):
        """The ``Card`` class you described."""
        ...
    
    class CardField(models.PositiveIntegerField):
        __metaclass__ = models.SubfieldBase
    
        def get_db_prep_value(self, value):
            """Return the ``int`` equivalent of ``value``."""
            if value is None: return None
            try:
                int_value = value.as_number()
            except AttributeError:
                int_value = int(value)
            return int_value
    
        def to_python(self, value):
            """Return the ``Card`` equivalent of ``value``."""
            if value is None or isinstance(value, Card):
                return value
            return Card(int(value))
    

    这个 get_db_prep_value 方法负责转换 value 转换为适合与数据库交互的东西,在这种情况下,要么 int None .

    这个 to_python 方法则相反,转换 进入a Card 和以前一样,你需要处理以下可能性 没有一个 作为一种价值。使用 SubfieldBase 确保 to_python 每次为字段赋值时都会调用。

        2
  •  1
  •   S.Lott    17 年前

    你为什么不能做以下事情?

    class Card(models.Model):
        """ A playing card.  """
        self.suit = models.PositiveIntegerField()
        self.rank = models.PositiveIntegerField( choices=SUIT_CHOICES )
        def as_number(self):
            """ returns a number from 1 (Ace of Clubs) and 52 (King of Spades)."""
            return self.number + self.suit * 13
        def __unicode__(self):
            return ...
        def is_highest(self, other_cards, trump=None):...
    

    当然,这很简单,很适合Django的自然工作。

        3
  •  0
  •   rebra    17 年前

    不要害怕根据自己的需要调整Django中的模型类。他们没有什么神奇的。我想这是这段代码的正确位置:在模型中。

    推荐文章