问题
I need to perform a datamigration of a model Answer in app Question. In that script there is a dependency such that I need to create an instance of a model Chapter which is in the app Journal. So, I coded it as follows:
def forwards(self, orm):
for answer_object in orm.Answer.objects.all():
#This Works.
blog, is_created = orm['blog.Post'].objects.get_or_create(title=answer_object.answer[:100])
blog.save()
#This DOES NOT work
chapter, is_created = orm['journal.Chapter'].objects.get_or_create(content_object=blog)
chapter.save()
#cleanup task, not relevant to this question below
answer_object.chapter_ptr = chapter
answer_object.save()
But as expected this throws an error on " orm['journal.Chapter'].objects.get_or_create(content_object=blog)" saying that
django.core.exceptions.FieldError: Cannot resolve keyword 'content_object' into field.
This is presumably due to content_object being a GenericForeignKey so some operations are not allowed. But I also tried other alternatives for creating the "chapter" object like,
chapter = orm['journal.Chapter'](content_object=blog)
ERROR > TypeError: 'content_object' is an invalid keyword argument for this function
and
chapter = orm.journal.Chapter(content_object=blog)
ERROR > AttributeError: The model 'journal' from the app 'questions' is not available in this migration. (Did you use orm.ModelName, not orm['app.ModelName']?)
So where am I going wrong? Any pointers appreciated. Thanks.
UPDATE
So since my earlier approach was failing I tried a new tack. The model whose instantiation was failing in my code above i.e. Chapter in the Journal app, I decided to create a datamigration for that instead. I also made sure to --freeze
the models I am referring to in the forwards
definition. Now this should have been straight forward, I would think. I have my forward code as follows -
def forwards(self, orm):
for answer_object in orm['questions.Answer'].objects.all():
#Works, AGAIN!
blog, is_created = orm['blog.Post'].objects.get_or_create(title=answer_object.answer[:100])
blog.save()
# DOES NOT WORK, AGAIN!
chapter = orm.Chapter(rank=1, content_object=blog)
chapter.save()
I would have thought that now since I am creating instance of a model (Chapter) which exists in the subject app (Journal) everything should have worked out. But i am getting the same error.
TypeError: 'content_object' is an invalid keyword argument for this function
It fails at the same point, namely, "content_object". I will post below the model definition if that might help.
class Chapter(models.Model):
rank = models.IntegerField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
UPDATE 2 Wanted to add that all the models being touched in these forwards methods, namely - blog, chapter, questions; are fully defined in the 00n_*.py files created by South's schemamigration.
回答1:
After getting help from Rob and folks on the South & Django user groups I was able to resolve this issue. Below is the definition of my forwards
datamigration script.
def forwards(self, orm):
for answer_object in orm['questions.Answer'].objects.all():
blog, is_created = orm['blog.Post'].objects.get_or_create(title=answer_object.answer[:100])
blog.save()
#I have to manually lookup the content_type ans set it in the chapter creation.
ct = orm['contenttypes.ContentType'].objects.get(app_label="blog", model="post")
chapter = orm.Chapter(rank=1, content_type=ct, object_id=blog.id)
chapter.save()
回答2:
This has sort of been answered before here Django South: Creating schemamigration for more than one app
Basically south doesn't currently support multiple applications.
If you don't want to entangle your applications even more than they are, I would use raw SQL in a db.execute as a quick fix.
It looks like blog and journal are very inter-related. Are you sure you want them in separate applications?
回答3:
In order to create a migration via manage.py, pass --freeze=other_app as arguments to add the models definitions of this other_app to the migration itself.
回答4:
This is a comment on Chantz's answer, which worked great for me (Don't have the rep to post this as a comment)
To save some others some time, you also need to freeze the contenttype app when you create your migration:
python manage.py datamigration yourapp migrationname --freeze contenttypes
来源:https://stackoverflow.com/questions/6976879/in-django-south-howto-create-an-instance-of-a-model-from-a-different-app-during