2012-12-29 19 views
8

Jestem nowicjuszem w Pythonie i Django i całkowicie nowym w Stack Overflow, więc mam nadzieję, że nie złamam tutaj żadnych zasad i szanuję format pytań.Niestandardowe pola modelu Django: to_python() nie nazywane

Mam do czynienia z problemem próbującym zaimplementować niestandardowe pole modelu za pomocą Django (Python 3.3.0, Django 1.5a1), a nie znalazłem żadnych podobnych tematów, właściwie utknąłem na tym ...

Więc jest gracz, ma rękę (karty). Hand dziedziczy po CardContainer, czyli w zasadzie listę kart z niektórymi (ukrytymi tutaj) funkcjami pomocniczymi. Oto odpowiedni kod:

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) 

Ale kiedy się odtwarzacz, powiedzmy, na przykład: (! A nawet wystąpienie CardContainer w ogóle) Player.objects.get(id=3).hand, zamiast się Hand instancji, jestem po prostu coraz oddzielony przecinkami ciąg liczb całkowitych, takich jak "1,2,3", co jest w porządku w bazie danych (jest to format, który chciałbym zobaczyć w bazie danych) ...

Wydaje mi się, że to_python nie jest wywoływana, więc zwrócone dane są wartością nieprzetworzoną, stąd ciąg znaków. Kiedy szukałem tego typu problemów, ludzie spóźnili się na __metaclass__ = models.SubfieldBase ... Miałem nadzieję, że też mogłem to przegapić, ale, hej, byłoby to zbyt proste! Czy tęskniłem za czymś trywialnym, czy też nie mam racji? : D

Wielkie dzięki!

Odpowiedz

10

W pythonie 3 zmienna globalna modułu __metaclass__ nie jest już obsługiwana. Należy użyć:

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

Wow, dzięki, ja zupełnie nie wiedziałem, że !! Myślę, że cichy wynik, jaki tworzy, jest dość denerwujący i przesłałem [ticket] (https://code.djangoproject.com/ticket/19539) do dokumentacji (ponieważ Django obsługuje Python 3, myślę, że dokument powinien wspomnieć że). – astorije

0

dla Django 1.10, a ostatni

class CardContainerField(models.CommaSeparatedIntegerField): 
    def from_db_value(self,value, expression, connection, context): 
     ....... 
Powiązane problemy