-
Notifications
You must be signed in to change notification settings - Fork 2
[New Instrument Name] Delete Instrument Names and set umil_label
#373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
- indicates a name has been deleted but preserves in the db refs: #340
…ment name from UMIL - allow admin to filter instrument names by deletion status - change deletion UI message to better reflect that the name will persist on the the UMILdb - only display instrument names that are `deleted`=`false` - create migration file refs: #340
- change constraint: `umil_label` = `true` only when verified and not deleted - existing_umil_label: other instrument_name in language where umil_label=true - replacement_umil_label: first verified, non-deleted instrument name added in language - `umil_label` set to `true`: unset `existing_umil_label` -`umil_label` set to `false`: reassign if possible to `replacement_umil_label` -`umil_label` set to `true` and `deleted` = `true`: indicates that name has been deleted from frontend --> reassign if possible, otherwise there are no verified instrument names refs: #350
…ruments will never be verified refs:#350
… where `umil_label` = `true` refs:#350
…ument names for the label in a language refs:#350
…ion must set `umil_label`=`true` refs:#350
- make use of the update function and querysets - eliminate recusivity - specify constraint name refs:#350
- otherwise update would set all other verified, non-deleted names as umil_label - order by id to get the correct first added name - consider scenario where the replacement_umil_label IS the current umil_label: avoid redundant resetting - remove unique umil_label constraint, the process of swapping labels will violate the constraint (seemingly the constraints are checked ebfore the custom save logic) refs:#350
- consider constraint migration refs:#350
- replacement_umil_label can be the existing_umil_label (umil_label=true) - prevents reassignment of a current umil_label - check for existing label when umil_label is "unset" to false refs: #350
|
@kunfang98927 this is an interesting case:
If an instrument name is verified and not deleted, it must have Instead of returning a ValueError, I can ensure that the alias is assigned as the label on UMIL ? |
I imagine there could be more cases like this. Even when making new items, the restriction is to have at least a label, an alias, or a description, but there's no requirement to have all three (and that's not even getting into people adding to an extant item with an alias rather than a label, or removing an incorrect label but leaving a correct alias, etc...) |
|
fwiw it looks like this particular case was due to a single edit last November https://www.wikidata.org/w/index.php?title=Q193666&diff=prev&oldid=2272030511 where somebody changed the labels in a whole bunch of languages--sometimes to clean up capitalization, but in other cases for no obvious reason (like Hebrew or Azerbaijani, for which there is a corresponding wikipedia article under the old label but no label on the wikidata item.) |
| "instrument", | ||
| "language", | ||
| "name", | ||
| "source_name", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment on this function is now out of date.
| condition=models.Q(umil_label=True), | ||
| name="unique_umil_label_per_instrument_language", | ||
| ) | ||
| models.CheckConstraint( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So are you getting rid of the UniqueConstraint?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that with my reassignment logic, where if an admin sets umil_label=true on a name and then the existing umil_label name is set as false, there is a brief point in time where there are two names with umil_label=true which is prevented by this Constraint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean by "reassignment logic"? I think this would just require a different order (set umil_label = False on existing label name and then umil_label = True on the new one)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wall I've run into here regarding the Unique Constraint is that partial unique constraints (unique constraints with a condition) cannot be deferred.
The issue is that if we enforce the Unique constraint of AT MOST one umil_label per instrument language, this is always broken when an admin sets another name's umil_label=true regardless if in the custom save function swaps the existing umil_label before calling the super().save
I thought I could get around this by deferring the Unique Constraint (https://docs.djangoproject.com/en/5.2/ref/models/constraints/#deferrable), so that the constraint is not enforced until the end of the transaction. Otherwise the constraint is immediate and enforced after every command.
With a bit of debugging it seems like when I click save on the django admin interface for an instrument name object, we do not seem to ever enter the custom save function so I think that although the state is not written to the database, there is still some sort of updating of the object that triggers the constraint.
I'm not finding much documentation specifically on partial unique constraints and deferral but after I compose up, the app fails to build with a Value Error indicating that partial unique constraints cannot be deferred.
The solution to this is implementing a check in the custom save function where a ValueError is raised if we detect more than one umil_label for names in the instrument language, evaluated after a potential swap/reassignment happens. But this will require the removal of the Unique Constraint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: looking into the difference between the save_model() in admin vs. save() in the view...
Assuming they must be different processes because the delete_name function is able to bypass the Check Constraint (when a contributer deletes a name on the frontend)
| ).exclude(id=self.id) | ||
|
|
||
| existing_umil_label = existing_umil_label_qs.first() | ||
| print("Existing UMIL label:", existing_umil_label) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this print statement in a deployed setting? Was this just for debugging in development?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry ! Forgot to delete this, was part of debugging !
| existing_umil_label_qs.update(umil_label=False) | ||
|
|
||
| # If a verified name is removing itself as umil_label | ||
| if not self.umil_label: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be an else statement following from line 82 right?
| return f"{self.name} ({self.language.en_label}) - {self.instrument.wikidata_id}" | ||
|
|
||
| def save(self, *args, **kwargs): | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't we give the user/superuser a choice in this case? Like alert them that they are deleting an instrument label and give them a choice of selecting another one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since a user can only delete their own name entries, umil_label reassignment would only be done on the admin interface page.
We can display a warning message on the django admin page that the admin is deleting the label and should choose another, however it opens the possibility that no verified instrument names are assigned as the label, which doesn't make sense on the frontend (visible verified names, but "no label available").
I think that Unique Constraint only ensures that "at most" one object with umil_label=true, which does not solve this problem (but then also it would be impossible to choose a different label)
In the current implementation when umil_label is unassigned, the custom save function will reassign umil_label to the earliest available verified, non-deleted name. If an admin assigns a name as the umil_label, it will unset the existing label. This ensures that there is always ONE umil_label at all times if possible.
What could be more informative to an admin is to:
- reinstate the unique constraint
- maintain the current check constraint to prevent impossible states
- if an admin unassigns a
umil_label, provide a warning message but allow - if an admin wants to reassign the
umil_label, they must unassign the currentumil_label(unique constraint)
The only downside to this is the case mentioned above (no automatic reassignment)
If a user deletes a label from the front end, the page will have to exist with "No verified label in [language]", until a new label is assigned manually (even if there are other verified names in that language displayed/available).
I think that the best final option to maintain clarity to the admin is to keep my current automatic reassignment logic, but provide a warning messages for unassignment and reassignment of the umil_label, where an admin it notified what name gained or lost umil_label=true respectively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I was confused about the purpose of this a bit.
So, it seems like the only case where we need any custom "save" logic is when the object in question is trying to save with a change in umil_label from its previous value or if the object is being saved with umil_label = True and deleted = True.
Is that right?
If so, we can exit early from this function in all other cases.
I'm less concerned about giving a choice because I reviewed the code for adding a name and it looks like we randomly assign a umil_label to initial names, so I think this is fine.
Since this process involves multiple database operations/modifications, you will need to think about database consistency and atomicity (what happens if one of the database operations fails? is your database ever in an invalid state?) You will need to use database transactions: https://docs.djangoproject.com/en/5.2/topics/db/transactions/.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I see what you mean ! I can check if the in memory status of the name regarding umil_label does not match the database status, which will trigger the custom save logic.
In addition to the case of umil_label = True and deleted = True, I think a final case to consider would be when the first non-deleted instrument name is verified (by a reviewer). In this case, the reviewer must be forced to save the instrument name as the umil_label.
I'm a bit confused by what you mean regarding adding a name, because another change to this process is that umil_label will always be False with a new name because it is unverified.
This opens another possible case of an admin adding an instrument name on the backend, and setting it as the umil_label, which would not be considered as the label status changing. However, I think that this can be flagged by the Unique Constraint, which I will try to reinstate with what you pointed out in here.
So to summarize, I will modify my save function so that it only considers:
-
umil_labelhas changed -
umil_label=Trueanddeleted=True(contributor has deleted the label from the frontend) -
umil_label=False,verification_status=Trueanddeleted=False, and there is no other verified name entry -
and reinstate the Unique Constraint so that it prevents an admin from adding an instrument name as
umil_labelwhen there is an existingumil_labelfor that instrument language.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused by what you mean regarding adding a name, because another change to this process is that
umil_labelwill always beFalsewith a new name because it is unverified.
Ah, good point.
Makes sense.
|
This PR has been hanging for a while. What is the current status? |
|
Just wanted to bump this; @kunfang98927 is this still something needed? |

refs:
umil_labelafter instrument name is (soft) deleted #350