Como faço para criar tipos de campo personalizado trivial em modelos de Django?

votos
3

Eu estou tentando fazer alguns tipos de Django que mapeiam para tipos Django padrão. A documentação de campo modelo personalizado vai para casos complicados; Eu só quero armazenar um tipo básico Django de uma classe com um monte de métodos práticos.

Por exemplo, se eu estivesse armazenar cartas de jogar, eu quero algo como:

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):  ...
     ...

Quero que os meus modelos para ter algo como:

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

Estou esperando a resposta será algo como herança do tipo correto, acrescentando alguns especialmente chamados campos get / loja para cartão, e renomeando o init (). Alguém tem código de exemplo ou melhor documentação?

Publicado 02/12/2008 em 19:41
fonte usuário
Em outras línguas...                            


3 respostas

votos
3

Eu faria isso com uma subclasse de PositiveIntegerField do Django:

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))

O get_db_prep_valuemétodo é responsável por converter valueem algo adequado para interagir com a base de dados, neste caso, quer um intou None.

O to_pythonmétodo faz o contrário, convertendo valueem um Card. Assim como antes, você vai precisar para lidar com a possibilidade de Nonecomo um valor. Usando os SubfieldBasegarante que to_pythoné chamado cada vez que um valor é atribuído ao campo.

Respondeu 02/12/2008 em 21:27
fonte usuário

votos
1

Por que você não pode fazer algo como o seguinte?

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):...

Certamente, isso é bastante simples, e se encaixa confortavelmente com o Django faz naturalmente.

Respondeu 02/12/2008 em 20:55
fonte usuário

votos
0

Não tenha medo de se adaptar as classes de modelo em Django às suas próprias necessidades. Não há nada mágico sobre eles. E eu acho que este é o lugar certo para este código: No modelo.

Respondeu 02/12/2008 em 21:14
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more