2017-02-01 8 views
9

djangoスニペットからコピーされたbase64フィールドがあります。 例えば、このフィールドを移行しながら、私は問題に直面していますdjangoカスタム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)),])] 

contrib_to_classの名前が変更されたため、移行自動検出機能が混乱していると思います。私は何が回避できるか分からない。

+0

contrib_to_class、get_dataおよびその他のメソッドがBase64Fieldクラス内にあるかどうかを確認してください。 – MicroPyramid

+0

彼らはクラス内にあります – Akamad007

+0

私は答えを提供しました、それはあなたを助けましたか? –

答えて

2
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_namenameとの間に、contribute_to_classが混在しているため、間違った値が使用されています(したがって、migrateを使用したときにはmakemigrationsは2度目にフィールドをピックアップしません)。

私は、super呼び出しとbase64関数の使用というpython3固有の変更を行いました。 set_dataメソッドが間違っている可能性があります(あまり気にしませんでした。なぜなら、Python2を使用している可能性があり、エンコーディングが異なるからです)。しかし、移行は機能します。

追加されました:private_only引数がcontribute_to_classメソッドから抜けていました。

from test_app import models 

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

e.attachment # Prints 'Hello world!' 
e.attachment_base64 # Prints b'SGVsbG8gd29ybGQh' 
関連する問題