我是Python和Django的新手,在Stack Overflow上是全新的,所以我希望我不会违反任何规则,我尊重问题格式。
我在尝试使用Django(Python 3.3.0,Django 1.5a1)实现自定义模型字段时遇到问题,我没有找到任何类似的主题,我实际上完全被这个问题困住了...... < / p>
所以有一个玩家,他有一手牌(卡)。 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)
但是当我得到一个播放器时,让我们这样说:Player.objects.get(id=3).hand
,而不是获得Hand
实例(甚至是CardContainer
实例!),我只是获取逗号分隔的整数字符串,如“1,2,3”,这在数据库中很好(这是我想在数据库中看到的格式)......
在我看来,to_python没有被调用,因此返回的数据是原始值,因此是字符串。当我搜索这类问题时,人们错过了__metaclass__ = models.SubfieldBase
...我希望我也可能错过了,但是,嘿,这太简单了!
我错过了一些微不足道的事情,还是我错了整件事? :d
非常感谢!!
答案 0 :(得分:10)
在python 3中,不再支持模块全局__metaclass__
变量。你必须使用:
class CardContainerField(models.CommaSeparatedIntegerField, metaclass=models.SubfieldBase):
...
答案 1 :(得分:0)
for Django 1.10 and latest
class CardContainerField(models.CommaSeparatedIntegerField):
def from_db_value(self,value, expression, connection, context):
.......