2016-03-28 55 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)