2012-12-29 51 views
8

我对Python和Django相当陌生,在堆栈溢出方面全新,所以我希望我不会在这里违反任何规则,并且我尊重问题格式。Django自定义模型字段:to_python()没有调用

我面临一个问题,试图用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) 

但是,当我得到的球员,可以说,是这样的:(!甚至CardContainer实例的话)Player.objects.get(id=3).hand,而不是让一个Hand情况下,我刚开一个逗号分隔的整数字符串,如“1,2,3”,这在数据库中是正确的(这是我希望在数据库中看到的格式)...

在我看来,to_python没有被调用,所以返回的数据是原始值,因此是字符串。当我搜索这种类型的问题时,人们错过了__metaclass__ = models.SubfieldBase ...我希望我也可以错过,但是,嘿,这太简单了! 我错过了一些微不足道的事情,还是我错了整件事情? :D

非常感谢!

回答

10

在python 3中,不再支持模块全局变量__metaclass__。您必须使用:

class CardContainerField(models.CommaSeparatedIntegerField, metaclass=models.SubfieldBase): 
    ... 
+0

哇,谢谢,我完全不知道!我认为它产生的无声结果非常恼人,我已经为文档提交了一个[ticket](https://code.djangoproject.com/ticket/19539)(因为Django支持Python 3,我认为文档应该提到那)。 – astorije

0

Django的1.10和最新

class CardContainerField(models.CommaSeparatedIntegerField): 
    def from_db_value(self,value, expression, connection, context): 
     ....... 
相关问题