[Django]-How do I create trivial customized field types in Django models?


I’d do this with a subclass of Django’s 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
            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))

The get_db_prep_value method is responsible for converting value into something suitable for interacting with the database, in this case either an int or None.

The to_python method does the reverse, converting value into a Card. Just like before, you’ll need to handle the possibility of None as a value. Using the SubfieldBase ensures that to_python is called every time a value is assigned to the field.


Why can’t you do something like the following?

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

Certainly, this is quite simple, and fits comfortably with what Django does naturally.



Don’t be afraid to adapt the model classes in Django to your own needs. There’s nothing magical about them. And I guess this is the Right Place for this code: In the model.


Leave a comment