2016-03-28 14 views
1

Ich möchte eine Datenmigration durchführen, um einen Benutzerleseeintrag in der Datenbank hinzuzufügen. Es gibt einen solchen Code:Warum GenericRelation-Felder in Datenmigrationen nicht funktionieren (Django)

def user_read_posts(apps, schema_editor): 
    User = apps.get_model("main", "User") 
    Post = apps.get_model("main", "Post") 
    Comment = apps.get_model("comments", "Comment") 

    comments = Comment.objects.all() 
    for comment in comments: 
     print (comment.content_object.__class__.__name__) 
     if isinstance(comment.content_object, Post): 
      comment.user.read_posts.add(comment.content_object) 

class Migration(migrations.Migration): 

    dependencies = [ 
     ('main', '0039_auto_20160314_0906'), 
    ] 

    operations = [ 
     migrations.RunPython(user_read_posts), 
    ] 

Und in Zeile print (comment.content_object.__class__.__name__) django Fehler aus: AttributeError: 'Comment' object has no attribute 'content_object'

Kommentar Modell:

class GuidaComment(GenericRelationModel): 

    user = models.ForeignKey(GuidaUser) 
    text = models.TextField() 

Also, was soll ich tun?

Danke.

+0

Können Sie die Attribute der Klasse 'GenericRelationModel'? – ruddra

+0

Ich benutze django generic_helpers app.As in docs: 'von generic_helpers.models Import GenericRelationModel 'Hier ist ein Modell Modul https://github.com/marazmiki/django-generic-helpers/blob/master/generic_helpers/models.py –

+0

Erwägen Sie stattdessen die Verwendung dieses https://docs.djangoproject.com/en/1.9/ref/contrib/contenttypes/, da ich sehen kann, dass das Paket seit fast einem Jahr nicht mehr aktualisiert wurde. – ruddra

Antwort

0

In RunPython Migrationsskripten apps.get_models() erhalten historische Version von Modellen, nicht die neuesten Django-Modelle, die Sie in der Quelle haben. Diese historischen Modelle sind ziemlich begrenzt. Auszug aus django documentation:

historical models will not have any custom methods that you have defined. They will, however, have the same fields, relationships, managers (limited to those with use_in_migrations = True) and Meta options (also versioned, so they may be different from your current ones).

Aber das bedeutet nicht, dass Sie nicht letzte und voll funktionsfähige Modelle sie nutzen können sie nur durch den Import und Verwendung. In diesem Fall riskieren Sie, dass das Migrationsskript in Zukunft nicht korrekt ausgeführt wird - da sich die neueste Version des Modells ändern kann (z. B. Modellmethode kann umbenannt, gelöscht, Logik geändert usw. werden). Es ist also möglich, aber Sie müssen sich des Risikos bewusst sein, wenn Sie solche Modelle verwenden.

Content types framework ist ziemlich alt und selten geändert Django Contrib-Anwendung und IMHO ist es sicher genug, es so zu verwenden.

Inspiriert durch die answer und Lösung, die ich gemacht und zu verwenden, habe ich hoffe ich folgenden Entwurf gemacht Sie nützlich finden werden:

def user_read_posts(apps, schema_editor): 
    User = apps.get_model("main", "User") 
    Post = apps.get_model("main", "Post") 
    Comment = apps.get_model("comments", "Comment") 

    from django.contrib.contenttypes.models import ContentType 

    comments = Comment.objects.all() 
    for comment in comments: 
     try: 
      # assuming that Comment has object_id field holding reference to PK 
      # of the referenced object 
      ct = ContentType.objects.get(model=comment.content_type.model, 
             app_label=comment.content_type.app_label) 
      content_object = ct.get_object_for_this_type(pk=comment.object_id) 
     except Exception, ex: 
      # TODO: can happen if some content type/model is deleted. 
      continue 

     print (content_object.__class__.__name__) 
     if isinstance(content_object, Post): 
      # TODO: maybe you will need to copy/adapt read_posts.add method's logic here 
      comment.user.read_posts.add(content_object)