Django自定义模型字段:未调用to_python() [英] Django custom model fields: to_python() not called

查看:46
本文介绍了Django自定义模型字段:未调用to_python()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Python和Django还是很陌生,在Stack Overflow上还是一个全新的人,所以我希望这里不会违反任何规则,并且尊重问题格式.

I am quite new to Python and Django, and totally new on Stack Overflow, so I hope I won't break any rules here and I respect the question format.

我在尝试使用Django(Python 3.3.0,Django 1.5a1)实现自定义模型字段时遇到了问题,但是我没有找到任何类似的主题,实际上我很迷恋于这个主题...

I am facing a problem trying to implement a custom model field with Django (Python 3.3.0, Django 1.5a1), and I didn't find any similar topics, I am actually quite stuck on this one...

有一个玩家,他有一个(牌)手.Hand继承自CardContainer,后者基本上是具有一些帮助功能(在此隐藏)的卡的列表.这是相应的代码:

So there is a Player, he has got a Hand (of Card). The Hand inherits from CardContainer, which is basically a list of cards with some (hidden here) helper functions. Here is the corresponding code:

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",这在数据库中很好(这是我使用的格式)d想在数据库中看到)...

But when I get a player, lets say, like this: Player.objects.get(id=3).hand, instead of getting a Hand instance (or even a CardContainer instance at all!), I am just getting a comma-separated string of integers like "1,2,3", which is fine in the database (it is the format I'd like to see IN the database)...

在我看来to_python没有被调用,所以返回的数据是原始值,因此是字符串.当我搜索此类问题时,人们错过了 __ metaclass__ = models.SubfieldBase ...我希望我也可以错过它,但是,嘿,那太简单了!我是否错过了一些琐碎的事情,还是整个事情我都错了?:D

It seems to me that to_python doesn't get called, so the returned data is the raw value, hence the string. When I searched for this type of problems, people missed the __metaclass__ = models.SubfieldBase... I hoped I could have missed that too but, hey, it would have been too simple! Did I miss something trivial, or am I wrong for the whole thing? :D

非常感谢!

推荐答案

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

In python 3 the module-global __metaclass__ variable is no longer supported. You must use:

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

这篇关于Django自定义模型字段:未调用to_python()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆