Пользовательское поле Django с множественным наследованием - PullRequest
5 голосов
/ 02 апреля 2011

У меня есть два пользовательских поля Django: JSONField и CompressedField, оба из которых работают хорошо.Я также хотел бы иметь CompressedJSONField, и я скорее надеялся, что смогу сделать это:

class CompressedJSONField(JSONField, CompressedField):
    pass

, но при импорте получаю:

RuntimeError: maximum recursion depth exceeded while calling a Python object

Я могу найти информацию оиспользование моделей с множественным наследованием в Django, но ничего не нужно делать с полями.Это должно быть возможно?Или я должен просто сдаться на этом этапе?

edit:

Просто чтобы прояснить, я не думаю, это имеет какое-то отношение ксделать со спецификой моего кода, так как следующий код имеет точно такую ​​же проблему:

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

edit 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.

Ответы [ 2 ]

2 голосов
/ 08 апреля 2011

после нескольких быстрых тестов я обнаружил, что если вы удалите метакласс из полей JSON и сжатых полей и поместите его в поле сжатых JSON, оно скомпилируется. если вам нужны поля 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

Честно говоря ... Я действительно ничего не понимаю.

РЕДАКТИРОВАТЬ базовый метод взломать

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

другой способ - присвоить to_python () классам уникальные имена и вызывать их в ваших унаследованных классах методами to_python ()

или, может быть, посмотрите этот ответ

EDIT после некоторого чтения, если вы реализуете вызов super(class, self).method(args) в первой базе to_python (), он вызовет вторую базу. Если вы используете супер постоянно, то у вас не должно быть никаких проблем. 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    
0 голосов
/ 07 апреля 2011

Трудно понять, когда именно вы получаете эту ошибку.Но, глядя на код DJango, есть реализация simlar (множественное наследование)

, ссылающаяся на: class ImageFieldFile (ImageFile, FieldFile)
в django / db / models / fields

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...