2012-12-29 25 views
8

Tôi khá mới với Python và Django, và hoàn toàn mới trên Stack Overflow, vì vậy tôi hy vọng tôi sẽ không vi phạm bất kỳ quy tắc nào ở đây và tôi tôn trọng định dạng câu hỏi.Trường mô hình tùy chỉnh Django: to_python() không được gọi là

Tôi đang đối mặt với sự cố khi triển khai trường mô hình tùy chỉnh với Django (Python 3.3.0, Django 1.5a1) và tôi không tìm thấy bất kỳ chủ đề tương tự nào, tôi thực sự khá mắc kẹt về vấn đề này ...

Vì vậy, có một Người chơi, anh ấy có một Bàn tay (của Thẻ). Bàn tay kế thừa từ CardContainer, về cơ bản là một danh sách các thẻ với một số hàm trợ giúp ẩn (ở đây). Đây là đoạn mã tương ứng:

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) 

Nhưng khi tôi nhận được một máy nghe nhạc, cho phép nói, như thế này: (! Hoặc thậm chí một trường hợp CardContainer tại tất cả) Player.objects.get(id=3).hand, thay vì nhận được một trường hợp Hand, tôi chỉ nhận được một chuỗi số nguyên được phân cách bằng dấu phẩy như "1,2,3", là tốt trong cơ sở dữ liệu (đó là định dạng tôi muốn thấy trong cơ sở dữ liệu) ...

Dường như với tôi rằng to_python không được gọi, vì vậy dữ liệu trả về là giá trị thô, do đó chuỗi. Khi tôi tìm kiếm loại vấn đề này, mọi người đã bỏ lỡ số __metaclass__ = models.SubfieldBase ... Tôi hy vọng tôi có thể đã bỏ lỡ điều đó nhưng, hey, nó sẽ quá đơn giản! Tôi đã bỏ lỡ điều gì đó tầm thường, hay là tôi sai cho toàn bộ sự việc? : D

Cảm ơn rất nhiều !!

Trả lời

10

Trong python 3 biến toàn cầu mô-đun __metaclass__ không còn được hỗ trợ. Bạn phải sử dụng:

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

Wow, cảm ơn, tôi hoàn toàn không biết rằng !! Tôi nghĩ rằng kết quả im lặng nó tạo ra là khá khó chịu, và tôi đã gửi một [ticket] (https://code.djangoproject.com/ticket/19539) cho các tài liệu (như Django hỗ trợ Python 3, tôi nghĩ rằng doc nên đề cập đến cái đó). – astorije

0

cho Django 1.10 và mới nhất

class CardContainerField(models.CommaSeparatedIntegerField): 
    def from_db_value(self,value, expression, connection, context): 
     ....... 
Các vấn đề liên quan