5

JSONFieldaと aの 2 つのカスタム Django フィールドがありCompressedField、どちらもうまく機能します。私も を持ちたいと思ってCompressedJSONFieldいます。私はむしろこれができることを望んでいました:

class CompressedJSONField(JSONField, CompressedField):
    pass

しかし、インポート時に次のようになります:

RuntimeError: maximum recursion depth exceeded while calling a Python object

Django で複数の継承を持つモデルを使用することに関する情報は見つかりますが、フィールドで同じことを行うことについては何もありません。これは可能でしょうか?それともこの段階であきらめるべきでしょうか?

編集:

明確にするために、次のコードにはまったく同じ問題があるため、これは私のコードの詳細とは何の関係もないと思います。

class CustomField(models.TextField, models.CharField):
    pass

編集2:

現在、Python 2.6.6 と Django 1.3 を使用しています。以下は、ストリップされた右下のテスト例の完全なコードです。

customfields.py

from django.db import models


class CompressedField(models.TextField):
    """ Standard TextField with automatic compression/decompression. """

    __metaclass__ = models.SubfieldBase
    description = 'Field which compresses stored data.'

    def to_python(self, value):
        return value

    def get_db_prep_value(self, value, **kwargs):
        return super(CompressedField, self)\
                        .get_db_prep_value(value, prepared=True)


class JSONField(models.TextField):
    """ JSONField with automatic serialization/deserialization. """

    __metaclass__ = models.SubfieldBase
    description = 'Field which stores a JSON object'

    def to_python(self, value):
        return value

    def get_db_prep_save(self, value, **kwargs):
        return super(JSONField, self).get_db_prep_save(value, **kwargs)


class CompressedJSONField(JSONField, CompressedField):
    pass

models.py

from django.db import models
from customfields import CompressedField, JSONField, CompressedJSONField

class TestModel(models.Model):

    name = models.CharField(max_length=150)
    compressed_field = CompressedField()
    json_field = JSONField()
    compressed_json_field = CompressedJSONField()

    def __unicode__(self):
        return self.name

この行を追加するとすぐに、compressed_json_field = CompressedJSONField()Django の初期化時にエラーが発生します。

4

2 に答える 2

3

いくつかの簡単なテストを行った後、JSON および圧縮フィールドからメタクラスを削除し、compressedJSON フィールドに配置すると、コンパイルされることがわかりました。JSON または Compressed フィールドが必要な場合は、それらをサブクラス化し、追加するだけです__metaclass__ = models.SubfieldBase

私はこれで重いテストを行っていないことを認めなければなりません:

from django.db import models                                                       


class CompressedField(models.TextField):                                           
    """ Standard TextField with automatic compression/decompression. """           

    description = 'Field which compresses stored data.'                            

    def to_python(self, value):                                                    
        return value                                                               

    def get_db_prep_value(self, value, **kwargs):                                  
        return super(CompressedField, self).get_db_prep_value(value, prepared=True)


class JSONField(models.TextField):                                                 
    """ JSONField with automatic serialization/deserialization. """                

    description = 'Field which stores a JSON object'                               

    def to_python(self, value):                                                    
        return value 

    def get_db_prep_save(self, value, **kwargs):                                   
        return super(JSONField, self).get_db_prep_save(value, **kwargs)            


class CompressedJSONField(JSONField, CompressedField):                             
    __metaclass__ = models.SubfieldBase                                            

class TestModel(models.Model):                                                     

    name = models.CharField(max_length=150)                                        
    #compressed_field = CompressedField()                                          
    #json_field = JSONField()                                                      
    compressed_json_field = CompressedJSONField()                                  

    def __unicode__(self):                                                         
        return self.name

次に、JSON フィールドと Commpressed フィールドを別々に使用する場合は、このアイデアが機能すると思います。

class JSONFieldSubClass(JSONField):
    __metaclass__ = models.SubfieldBase

正直なところ...私はこれのどれも本当に理解していません。

EDIT基本メソッドハック

class CompressedJSONField(JSONField, CompressedField):
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        value = JSONField.to_python(self, value)
        value = CompressedField.to_python(self, value)
        return value

もう 1 つの方法は、クラスの to_python() に一意の名前を付け、継承されたクラスの to_python() メソッドでそれらを呼び出すことです。

または多分この答えをチェックしてください

super(class, self).method(args)最初のベース to_python() への呼び出しを実装する場合、いくつかの読み取り後に編集すると、2番目のベースが呼び出されます。スーパーを一貫して使用する場合、問題はないはずです。http://docs.python.org/library/functions.html#superはチェックアウトする価値があり、http: //www.artima.com/weblogs/viewpost.jsp?thread=237121

class base1(object):                                                               
    def name(self, value):                                                         
        print "base1", value                                                       
        super(base1, self).name(value)                                             

    def to_python(self, value):                                                    
        value = value + " base 1 "                                                 
        if(hasattr(super(base1, self), "to_python")):                              
            value = super(base1, self).to_python(value)                            
        return value                                                               

class base2(object):                                                               
    def name(self, value):                                                         
        print "base2", value                                                       

    def to_python(self, value):                                                    
        value = value + " base 2 "                                                 
        if(hasattr(super(base2, self), "to_python")):                              
            value = super(base2, self).to_python(value)                            
        return value                                                               

class superClass(base1, base2):                                                    
    def name(self, value):                                                         
        super(superClass, self).name(value)                                        
        print "super Class", value    
于 2011-04-08T06:04:57.763 に答える
-2

そのエラーが発生した正確な時期を理解するのは困難です。しかし、DJango のコードを見ると、simlar 実装 (多重継承) があります。

参照: django/db/models/fields のクラス ImageFieldFile(ImageFile, FieldFile)

于 2011-04-07T07:00:35.787 に答える