2017-02-01 4 views
9

Ich habe ein Base64-Feld, das aus dem Django-Snippet kopiert wird.Wie django benutzerdefinierte base64-Feld zu migrieren. Feld existiert nicht

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 

ich Fragen ist vor, während dieses Feld Migration z.B.

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

Der Fehler, den ich immer bin während der Migration ist

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

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

Jetzt kann ich sehen, warum das geschieht. Aber ich kann keinen Weg finden. Ich denke, dass ich etwas im Bereich der Dekonstruktion ändern muss. Ich habe mehrere Dinge ausprobiert, aber alle sind kaputt gegangen.

z.B. Entfernen der _base64. Es funktioniert nicht beim Speichern und Abrufen von Daten.

Ich habe versucht, den Namen in der Migrationsdatei ändern, es funktioniert nicht.

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)),])] 

Ich denke, der Migrationen Auto-detecter wegen des Namenswechsels in contribute_to_class verwirrt erhält. Ich bin mir nicht sicher, was eine Arbeit sein kann.

+0

Überprüfen Sie, ob die Methoden contribute_to_class, get_data und andere Methoden in der Base64Field-Klasse enthalten sind. – MicroPyramid

+0

Sie sind in der Klasse – Akamad007

+0

Ich habe eine Antwort zur Verfügung gestellt, hat es Ihnen geholfen? –

Antwort

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')) 

Dies scheint zu funktionieren. Es gab eine Verwechslung zwischen self.field_name und name in contribute_to_class, was dazu führte, dass der falsche Wert verwendet wurde (daher makemigrations das Feld nicht beim zweiten Mal aufnehmen/wenn migrate verwendet wurde).

Ich habe python3 spezifische Änderungen gemacht, nämlich die super Aufrufe und die Verwendung von base64 Funktionen. Die set_data Methode kann falsch sein (ich habe nicht zu viel darüber nachgedacht, da Sie möglicherweise Python2 verwenden und die Codierung würde sich unterscheiden), aber Migrationen funktionieren.

Zusätzlicher Bonus: das private_only Argument fehlte von Ihrer contribute_to_class Methode.

Hier ist, was ich bekomme:

from test_app import models 

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

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