Ticket #327 (closed defect: fixed)

Opened 6 years ago

Last modified 6 years ago

contribute_to_class can be called multiple times for fields

Reported by: carl@… Owned by: andrew
Priority: major Milestone: 0.7
Component: commands Version: 0.6-pre
Keywords: Cc:


I have a custom field that adds another field to the model in its contribute_to_class method. If I try to do a data migration on a model with this field, using the fake ORM, I get "multiple assignments to same column" errors from Postgres. This is because apparently the fake ORM calls contribute_to_class on a field twice, instead of once as Django does. This results in the extra field being added twice.

Haven't had the time yet to wrap my head around the fake ORM code and figure out why this happens and if it's avoidable.

Change History

comment:1 Changed 6 years ago by andrew

  • Status changed from new to assigned
  • Milestone set to 0.7

Yes, that sounds just like the kind of bug I'd introduce; most of the core fields don't mind being called more than once. Scheduling for 0.7.

comment:2 Changed 6 years ago by carl@…

Except I'm wrong. What's actually happening is that the auto-added field gets frozen with all the others (which needs to happen, otherwise changes to it won't get autodetected). But when the fake ORM boots up, it gets this auto-added field normally from the frozen fields, and then my custom field adds it again, so it ends up on the fake ORM model twice.

If you can think of a way for South to do this better, that's awesome. But I can't, so feel free to close as wontfix/invalid. I guess it just means that custom fields which add other fields must first check if their auto-added field already exists in order to be compatible with the South FakeORM. Or I might be able to add a flag argument that tells the field not to add its counterpart, and then use introspection rules to tell South to use that argument in its frozen version...

comment:3 Changed 6 years ago by carl@…

The latter approach (preventing creation of the added field when rehydrating frozen models via an arg/attribute and introspection rule) works great; adds a little cruft to the custom field, but that's worth it to get the full benefit of South. You can see the code here: http://bitbucket.org/carljm/django-markitup/src/tip/markitup/fields.py#cl-68

Guess it's up to you if this gotcha is significant enough to warrant a spot in the docs: took up half a day for me :-)

comment:4 Changed 6 years ago by andrew

  • Status changed from assigned to closed
  • Resolution set to fixed

Ah, the custom introspection solution is nice and clean; I'll stick a paragraph or two in the docs about it, and close this one.

Note: See TracTickets for help on using tickets.