django-modeltranslation icon indicating copy to clipboard operation
django-modeltranslation copied to clipboard

Actively prevent an update of the original field?

Open deschler opened this issue 12 years ago • 26 comments

I'm wondering if we can (and should) actively prevent the underlying value of the original field from being updated. With 0.5 we defined the state of the original field as undetermined. As we don't rely on the value anymore after the registration happened, that's basically fine... until we want to get rid of modeltranslation.

Consider someone tries modeltranslation and comes to the conclusion that he doesn't like it (yes, we must admit this can happen :)) or simply doesn't need it anymore. Now we can't assure that the original field hasn't been messed with and restoring the original state is unnecessarily hard. Of course we could say: "You have a backup, right?", but i think that's a weak argument. If we can prevent this from happening (i'm not sure we really can), is there a good reason not to do it? It would make the removal of modeltranslation much easier, as one could simply remove the translation fields modeltranslation added.

deschler avatar Jan 14 '13 22:01 deschler

I'm amazed how similary we think. :)

I had been thinking about the same issue about the time of update_translation_fields fix. I wrote the solution and concluded it is possible to retain original value, however i felt the amount of hackishness had increased.

I have pushed a new branch with that code: preserve_original

zlorf avatar Jan 15 '13 10:01 zlorf

However, I wonder about one thing: we have got rid of Rule 3, because:

  • it was no more needed as MultilingualManager and other changes were introduced
  • there were many problem with it - users had been reporting situations when the rule didn't work

So, is this issue much different? I just fear that we can overlook a scenario which led to changing the original field value.

When considering deinstalation of Modeltranslation (with original fields' values preserved), there should be a command "reverse" to update_translation_fields. The command which copy value from default language field to original field. Rationale is as follow: if someone was actively using Modeltranslation and changed some translation fields values, and he want to deactivate Modeltranslation, he doesn't want to lose changed values.

zlorf avatar Jan 15 '13 10:01 zlorf

And you wrote the code already! :-)

Good point regarding the problems we had with rule3, i'm not fully convinced myself. It might re-raise old problems or create completely new ones. If the change can be made solid however, we would at last have a good excuse why the original field is kept on database level at all (we know there are other reasons). ;)

A reverse variant of update_translation_fields is a nice idea, too.

deschler avatar Jan 15 '13 21:01 deschler

As you can see, the code was already written two weeks ago. :)

I feel this change needs more tests, especially a few regarding admin adding/changing.

And nice conclusion about original-field-keeping-excuse. :)

zlorf avatar Jan 15 '13 21:01 zlorf

Commenting here since #238 has been closed. I think a management command like update_translation_fields might not be enough.

Imagine an active legacy system, maintained by multilingual staff. Original field is being used by some third party apps all the time. Admin with Swedish language logs in to edit Swedish translation, then admin with Polish language logs in to edit Polish translation. As a results original value is being constantly changed, freaking out third party apps.

I actually have a real problem with this right now, I might have to to disable editing translations via admin completely.

malexeev avatar Mar 26 '14 18:03 malexeev

I see. We can (probably) force MT to keep original field intact (code is ready, but not tested completely). Would this be sufficient in your case? The third party app will always get the same values (as original fields won't be updated).

zlorf avatar Mar 26 '14 18:03 zlorf

Yes, I think that would be perfect solution.

malexeev avatar Mar 26 '14 18:03 malexeev

Fine, you can be the beta tester then. ;) I've rebased the preserve_original branch against master (lots have changed since the code was written (about a year passed!)).

Try this code with your app: https://github.com/deschler/django-modeltranslation/tree/preserve_original

zlorf avatar Mar 26 '14 21:03 zlorf

Great, seems to be almost working. There is a small problem with creating (inserting) new objects - it leaves original empty.

Say, original field has a "not null" db constraint and we are adding a new entry. We fill in all translated field and hit save. Operation fails with "cannot insert NULL into ". So, I think when inserting new it should put to the original field the translated value - based on request language, following standard rules.

malexeev avatar Mar 26 '14 22:03 malexeev

If a field is "not null", then it's default value (the one returned from field's get_default()) cannot be None, so this shouldn't happened.

zlorf avatar Mar 26 '14 22:03 zlorf

The second commit should address the objects adding.

zlorf avatar Mar 26 '14 22:03 zlorf

Great, now it seems to be working just fine!

malexeev avatar Mar 26 '14 23:03 malexeev

Nice to hear. I'll wait some time before I merge this into master: more tests needs to be written and I'll wait for you to give feedback after some time. And management command needs to be added.

zlorf avatar Mar 26 '14 23:03 zlorf

Ok, we will be testing it and I will let you know about the results.

malexeev avatar Mar 26 '14 23:03 malexeev

Hello, I have a question. I tried using the library in my django app but the original column is always getting filled with the same value as the first language I set my model with.

Example:

p = ModelX(id=1)
p.attr = "foo"
p.save()
# now attr_en and attr columns have ""
# now in a "pt" context
p = ModelX.objects.get(id=1)
p.attr = "bar"
p.save()
# attr_en and attr columns still have "" and attr_pt have "bar"

I tried the using the mentioned branch but the behavior is the same. Is this the expected behavior for both branches or is something wrong with my app?

arthurprs avatar Jul 03 '14 19:07 arthurprs

I think this is correct behavior - you need to provide explicit translations for every language or use "populate" (https://django-modeltranslation.readthedocs.org/en/latest/usage.html#auto-population).

In general - we've been using this branch for a long time now and it seems to work for us perfectly.

malexeev avatar Jul 04 '14 06:07 malexeev

Well, this branch should - as it's name suggest - retain value of attr column (and set to current active language on object creation). So it's something wrong with the beginning of your example. If pt is active language, then attr also should end with "foo" in database and this "foo" should persist later.

zlorf avatar Jul 04 '14 08:07 zlorf

Sorry, seems like I messed up the example and also wasn't clear enough. Example 2.0:

# in "en" context
p = ModelX(id=1)
p.attr = "foo"
p.save()
# now both attr_en and attr columns in the dabase have "foo"
# attr collum shouldn't have anything though
# "pt" context
p = ModelX.objects.get(id=1)
p.attr = "bar"
p.save()
# attr_en and attr columns still have "foo" and attr_pt have "bar"

I'm hoping to prevent the original column from getting saved in the database (instead remain "" or NULL) but even with the preserve_original branch it keeps getting the same value as the first translated value.

arthurprs avatar Jul 04 '14 11:07 arthurprs

Example is correct and exactly as it should be. Generally, this branch makes sure that no action change the attr column value. Except for object creation, when attr gets value of current language. But then it is not changed anymore.

Extending your example:

# attr_en and attr columns still have "foo" and attr_pt have "bar"
# "en" context again
p = ModelX.objects.get(id=1)
p.attr = "qwe"
p.save()
# now: attr_en = "qwe", attr_pt = "bar" and attr = "foo"

zlorf avatar Jul 04 '14 12:07 zlorf

Thanks for the clarification. I assume at this time there's no way to prevent the original column from being set.

arthurprs avatar Jul 04 '14 12:07 arthurprs

All you want is to keep it null or empty string? I think we could add some settings flag that control whether original column is set at object creation time.

zlorf avatar Jul 04 '14 12:07 zlorf

Yes, as the number of translated columns piles up it takes a lot of page space. Overall I don't see any reason to set it, I guess it could be disabled completely.

arthurprs avatar Jul 04 '14 12:07 arthurprs

Looking at the code it looks like it can be as simple as returning None or another default value in OriginalTranslationField.pre_save Do you plan merging this in master? What do you think about not writing the original column at all?

arthurprs avatar Jul 07 '14 04:07 arthurprs

Yes, its just this line tweak: https://github.com/deschler/django-modeltranslation/commit/6d4800b7265a5470a1b9de0474f09f9028b55619#diff-c2c534a5635a4794b16631a64b85edffR90

Merging - we need to consider.

zlorf avatar Jul 07 '14 07:07 zlorf

This issue seems to be still outstanding after a year. Is there any plans to merge this to master?

jtiai avatar Nov 03 '15 09:11 jtiai

Since we do have great need for this feature I made it optional through options setting. So in order to preserve original field value it must be explicitly be done so in model translation options. Would that be a good solution?

jtiai avatar Nov 27 '15 06:11 jtiai