【问题标题】:How to migrate django custom base64 field. Field does not exist如何迁移 django 自定义 base64 字段。字段不存在
【发布时间】:2017-06-17 17:43:03
【问题描述】:

我有一个从 django sn-p 复制的 base64 字段。

https://djangosnippets.org/snippets/1669/

class Base64Field(models.TextField):
    """
    https://djangosnippets.org/snippets/1669/
    Example use:
    class Foo(models.Model):
        data = Base64Field()

    foo = Foo()
    foo.data = 'Hello world!'
    print foo.data # will 'Hello world!'
    print foo.data_base64 # will print 'SGVsbG8gd29ybGQh\n'

    """

    def contribute_to_class(self, cls, name):

        if not self.db_column:
            self.db_column = name

        self.field_name =name+ '_base64'
        super(Base64Field, self).contribute_to_class(cls, self.field_name)
        setattr(cls, name, property(self.get_data, self.set_data))

    def get_data(self, obj):
        return base64.decodestring(getattr(obj, self.field_name))

    def set_data(self, obj, data):
        setattr(obj, self.field_name, base64.encodestring(data))

    def deconstruct(self):
        ame, path, args, kwargs = super(Base64Field, self).deconstruct()
        from pprint import pprint
        pprint(vars(self))
        return ame, path, args, kwargs

我在迁移此字段时遇到问题 例如

class EmailStatus(models.Model):
    attachment = Base64Field(null=True, blank=True, db_column='attachment', name="attachment", verbose_name="attachment")

我在迁移时遇到的错误是

raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, field_name))

django.core.exceptions.FieldDoesNotExist: EmailStatus has no field named u'attachment'

现在我明白为什么会这样了。但想不出解决办法。我想我可能需要在解构领域改变一些东西。我为此尝试了多种方法,但都失败了。

例如删除 _base64。它在保存和检索数据时不起作用。

我尝试更改迁移文件中的名称,但它不起作用。

class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(name='EmailStatus',
            fields=[('attachment', gradsite.gradnotes.models.Base64Field(blank=True, null=True)),])]

我认为迁移自动检测器会因为contribute_to_class 中的名称更改而变得混乱。我不确定可以解决什么问题。

【问题讨论】:

  • 请检查contribute_to_class、get_data等方法是否在Base64Field类中。
  • 他们在班级里
  • 我已经提供了答案,对您有帮助吗?
  • 嘿@RaphaëlGomès 它没有。我仍在尝试找出一些更精细的细节。
  • 我可以帮助您了解这些细节吗?迁移不起作用吗?

标签: django django-migrations


【解决方案1】:
class Base64Field(models.TextField):
    def contribute_to_class(self, cls, name, private_only=False):
        if not self.db_column:
            self.db_column = name

        self.field_name = name + '_base64'
        super().contribute_to_class(cls,
                                    name)
        setattr(cls, self.field_name, property(self.get_data, self.set_data))

    def get_data(self, obj):
        return base64.b64encode(getattr(obj, self.name).encode('utf-8'))

    def set_data(self, obj, data):
        setattr(obj, self.field_name, base64.b64decode(data).decode('utf-8'))

这似乎有效。 self.field_namecontribute_to_class 中的 self.field_namename 之间存在混淆,导致使用了错误的值(因此 makemigrations 在第二次/使用 migrate 时没有拾取该字段)。

我已经对 python3 进行了特定的更改,即super 调用和base64 函数的使用。 set_data 方法可能是错误的(我没有仔细研究,因为您可能使用的是 python2 并且编码会有所不同),但迁移工作。

额外的好处:contribute_to_class 方法中缺少 private_only 参数。

这是我得到的:

from test_app import models

e = models.EmailStatus()
e.attachment = "Hello world!"

e.attachment  # Prints 'Hello world!'
e.attachment_base64  # Prints b'SGVsbG8gd29ybGQh'

【讨论】:

    【解决方案2】:
    猜你喜欢
    • 1970-01-01
    • 2011-10-28
    • 2013-07-05
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    • 2015-04-27
    • 2013-08-24
    • 2020-08-09
    相关资源
    最近更新 更多