为什么GenericRelation字段在数据迁移中不起作用(Django) [英] Why GenericRelation fields does not work in Data Migrations(Django)

查看:60
本文介绍了为什么GenericRelation字段在数据迁移中不起作用(Django)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想进行数据迁移,以便在数据库中添加用户阅读的帖子。有这样的代码:

I want to make data migration in order to add user read post in database. There is such code:

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

并且在行中打印(comment.content_object .__ class __.__ name __) django引发错误:
AttributeError:注释对象没有属性 content_object

And in line print (comment.content_object.__class__.__name__) django raise error: AttributeError: 'Comment' object has no attribute 'content_object'

注释模型:

class GuidaComment(GenericRelationModel):

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

那我该怎么办?

谢谢。

推荐答案

RunPython 迁移脚本<$ c中$ c> apps.get_models()将获得模型的历史版本,而不是源代码中最新的Django模型。这些历史模型非常有限。摘录自 django文档

In RunPython migration scripts apps.get_models() will get historical version of models, not the latest django models you have in source. These historical models are quite limited. Excerpt from django documentation:


历史模型将没有定义了
的任何自定义方法。但是,它们将具有相同的字段,关系,
管理者(仅限于use_in_migrations = True的经理)和元
选项(也已版本化),因此它们可能与您当前的
不同)。

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

但这并不意味着您不能仅通过导入和使用最新的,功能齐全的模型。在这种情况下,您冒着将来迁移脚本无法正常运行的风险-因为最新版本的模型可以更改(例如,可以重命名,删除模型方法,更改逻辑等)。因此,有可能,但是您需要使用这种模型来意识到风险。

But that does not mean that you can't use latest and fully functional models by just importing them and using them. In that case you are risking that the migration script won't run correctly in the future - since latest version of model can change (e.g. model method can be renamed, deleted, logic changed etc.). So, it is possible but you need to be aware of the risk using models like this.

内容类型框架很老,几乎没有更改过Django contrib应用程序,恕我直言,它足以像这样使用它。

Content types framework is pretty old and rarely changed django contrib application and IMHO it is safe enough to use it like this.

答案和我制定和使用的解决方案,我已按照以下草案提出,希望您会发现有用:

Inspired by the answer and solution I made and use, I have made following draft I hope you will find useful:

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)

这篇关于为什么GenericRelation字段在数据迁移中不起作用(Django)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆