2012-12-29 53 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): 
     ....... 
相關問題