Пользовательское поле Django выдает ошибку при редактировании в админке

Я пытаюсь реализовать пользовательское поле Django, которое будет хранить в БД имя одного из моих классов модели (например, "Cat", "Dog", "Restaurant", "SuperPrivateCommercialDataPiece" и т. Д.) И возвращать объект класса, когда просил:

class Cat(models.Model):
    ...

class SomeDataPiece(models.Model):
    relatedTo = MyGloriousFieldType(null=True)

...

newPiece = SomeDataPiece()
newPiece.relatedTo = Cat
print newPiece.relatedTo # should print <class 'myproj.myapp.models.Cat'>

И я действительно сделал это. Я подкласс models.Field, задавать __metaclass__, так далее.:

class MyGloriousFieldType(models.Field):

    description = "No description, just gloriosity."

    __metaclass__ = models.SubfieldBase

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 40
        super(BlockTypeField, self).__init__(*args, **kwargs)

    def db_type(self, connection):
        return 'char(40)'

    def to_python(self, value):
        if not value:
            return None
        elif inspect.isclass(value) and issubclass(value, models.Model):
            return value
        elif hasattr(myproj.myapp.models, value):
            return getattr(myproj.myapp.models, value)
        else:
            raise ValidationError("Invalid model name string")

    def get_db_prep_value(self, value, **kwargs):
        if inspect.isclass(value) and issubclass(value, models.Model):
            return value.__name__
        else:
            # it is actually never raised
            raise ValidationError("Invalid value, Model subclass expected")

    def value_to_string(self, instance):
        value = self._get_val_from_obj(obj)
        return self.get_prep_value(value)

И в приведенном выше коде это работает так же, как и ожидалось. Я также зарегистрировал некоторые из моих моделей, содержащих такие поля, в admin, и теперь я даже могу создавать такие объекты; ввод текста создается для полей MyGloriousFieldType.

Кризис начинается, когда я пытаюсь редактировать уже существующий объект с полем MyGloriousFieldType. Во-первых, он заполняет текстовое поле словом "объект Cat", а не просто "Cat". Во-вторых, когда я изменяю его обратно на "Cat" и нажимаю "сохранить изменения", это выдает ошибку:

TypeError at /admin/myapp/somedatapiece/3/
  unbound method prepare_database_save() must be
  called with Cat instance as first argument (got 
  MyGloriousFieldType instance instead)

Итак, что я делаю не так?

1 ответ

Решение

Ну, я понял это. Проблема внутри самого ядра Django. Поля просто не могут возвращать объекты Python, содержащие некоторые models.Field атрибуты, такие как prepare_database_saveв противном случае происходит ошибка. Мой взлом, чтобы решить, что должен был вернуть кортеж (MyClassObject, ) вместо просто MyClassObject в to_python(), Странно, но что я могу сделать... Может быть, я постараюсь опубликовать проблему где-нибудь на странице GitHub Джанго.

Другие вопросы по тегам