Как создать тривиальные настраиваемые типы полей в моделях Django? - PullRequest
3 голосов
/ 02 декабря 2008

Я пытаюсь создать некоторые типы в Django, которые соответствуют стандартным типам Django. документация по полям пользовательской модели подходит для сложных случаев; Я просто хочу сохранить базовый тип 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 для карточки и переименование init () У кого-нибудь есть пример кода или лучшая документация?

Ответы [ 3 ]

3 голосов
/ 02 декабря 2008

Я бы сделал это с подклассом 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 выполняет обратное преобразование value в Card. Как и раньше, вам нужно обработать возможность None в качестве значения. Использование SubfieldBase гарантирует, что to_python вызывается каждый раз, когда значение присваивается полю.

1 голос
/ 02 декабря 2008

Почему вы не можете сделать что-то вроде следующего?

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 делает естественно.

0 голосов
/ 02 декабря 2008

Не бойтесь адаптировать модельные классы в Django под свои нужды. В них нет ничего волшебного. И я думаю, что это правильное место для этого кода: в модели.

...