2016-03-28 49 views
1

我想进行数据迁移以便在数据库中添加用户阅读帖子。有这样的代码:为什么GenericRelation字段在Data Migrations中不起作用(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), 
    ] 

并且符合print (comment.content_object.__class__.__name__) Django的提高错误: AttributeError: 'Comment' object has no attribute 'content_object'

评价模型:

class GuidaComment(GenericRelationModel): 

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

那么,应该怎么办?

谢谢。

+0

你能给类GenericRelationModel'的'属性? – ruddra

+0

我使用django generic_helpers app.As在文档中:'from generic_helpers.models import GenericRelationModel'这是一个模型模块https://github.com/marazmiki/django-generic-helpers/blob/master/generic_helpers/models.py –

+0

考虑使用这个:https://docs.djangoproject.com/en/1.9/ref/contrib/contenttypes/,因为我可以看到这个软件包已经有近1年没有更新过了。 – ruddra

回答

0

RunPython迁移脚本apps.get_models()将获得历史版本的模型,而不是您在源代码中的最新django模型。这些历史模型相当有限。从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).

但是,这并不意味着你不能只导入它们,使用它们使用最新的,功能齐全的机型。在这种情况下,您冒着转移脚本将来无法正确运行的风险 - 因为最新版本的模型可能会发生变化(例如,模型方法可能会被重命名,删除,逻辑更改等)。所以,这是可能的,但您需要了解使用这种模型的风险。

Content types framework是相当古老,很少更改django contrib应用程序和恕我直言,它是足够安全的使用它像这样。

answer和解决方案我提出和使用的激励下,我做了下面的草案,我希望你会发现有用:

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)