I'm sorry that it took so long for you to get a reply... I hope you have
solved the issue already. If so, it would be nice if you could comment. If
not, I hope this is still relevant:
This is quite surprising: The code seems to create a foreign key from
SpecificProfile to UserProfile, before creating the UserProfile table. The fact
that it seemed to work is probably a bug; it seems to be triggered by creating
a FK to an abstract class ("orm['myapp.UserProfile']" is the UserProfile class
before the migration -- the abstract version).
> Now, in the data migration process, I would like to create one
> UserProfile entry per SpecificProfile and assign UserProfile.user_id
> to SpecificProfile.user_profile_id.
>
> So, my data migration forwards is:
>
> class Migration(DataMigration):
>
> def forwards(self, orm):
> for spec in orm.SpecificProfile.objects.all():
> user_profile = orm.UserProfile()
> user_profile.user_id = spec.user_profile_id
> user_profile.save()
>
> This seems correct for me, but it does not create any new entry for
> the UserProfile model, which is strange.
> I used pdb to debug the issue and I verified that
> orm.SpecificProfile.objects.all() is returning an empty list, BUT
> orm.SpecificProfile.objects.count() returns 8 and
> orm.SpecificProfile.objects.values_list('user_profile_id') returns the
> 8 different values I have in the db.
>
> How is this possible?
The Data Migration uses the definitions after the Schema Migration; according
to these, the database records for SpecificProfile objects are made by joining
the SpecificProfile table with the UserProfile table -- and this, indeed, should
return no records; the result from count() and values_list(), apparently, use
only the SpecificProfile table. This, in itself, is *not* a bug -- these would
be correct optimizations, if the FK constraint would be enforced. In the
situation you describe, it is clearly violated -- the FK probably doesn't
exist in the database.
The right way to do this is:
1) A Schema migration which only adds the UserProfile table, without modifying
the SpecificProfile table
2) A Data migration which creates the records in UserProfile
3) A Schema migration to fix the SpecificProfile table and its FK.
There is a little problem with this: As far as I can see, there's no way to
generate the Schema migrations automatically; you have to edit the migrations
manually. It's unfortunate that you ran into this limitation of the automatic
process on your very first migration, but that's life.
Hope this helps (anybody),
Shai.
Thanks for your reply and explanations.
To work around this problem, I iterated over the values returned by
"values_list" like this:
for (_id,) in orm.SpecificProfile.objects.values_list('user_profile_id'):
spec_profile = orm.SpecificProfile.objects.get(pk=_id)
#manipulations as described before
This worked fine.
As you said, it's unfortunate that it happened in the 1st time I was
using south, but that's ok. I've been using south since then without any
problems.
Best regards,
Eduardo
Eduardo S. Klein
Kleintech
Diretor de Tecnologia - CTO
www.frugar.com.br