I am attempting to modify a page on my Django admin so that a trusted race administrator can manually rearrange a leader board of race results. The results go from 1 to N competitors in a race, and are mutually exclusive. Draw results are not allowed, so race administrators apply often complex and arcane tie breaking rules to avoid draws, which is the reason why they require the facility to manually re-arrange results.
I have a model and validators here: ``` def number_of_ranks(value): number_of_results = Rank.objects.all().count() if value > number_of_results: raise ValidationError( _('%(value)s is bigger than number of results which is %(number_of_results)s'), params={'value': value, 'number_of_results': number_of_results}, ) class Rank(models.Model): result = models.PositiveIntegerField(validators=[ MinValueValidator(1), number_of_ranks]) # 1st, 2nd, 3rd = 1,2,3 etc - may be assigned by administrator team = models.ForeignKey( # team that achieved this result 'team', related_name='team_in_rank', on_delete=models.PROTECT ) ``` and an admin page for Rank here: ``` @admin.register(Rank) class RankAdmin(admin.ModelAdmin): list_display = ('result', 'team',) sortable_by = ('') ordering = ('result',) list_editable = ('result',) list_display_links = None def has_add_permission(self, request): return False def has_delete_permission(self, request): return False def save_model(self, request, obj, form, change): print('-------------save_model called------------') print(request) print('================================') print('All objects and results BEFORE change') print([(rank, rank.result) for rank in Rank.objects.all()]) print('================================') print('Changed object and changed result') print(obj, obj.result) print('================================') super().save_model(request, obj, form, change) print('All objects and results AFTER change') print([(rank, rank.result) for rank in Rank.objects.all()]) ``` This achieves some of what I want. That is 1. The admin can neither remove or add teams in the race, nor change the names of any of the teams, only results. 2. Any result must be in the range 1 to N competitors. 3. The display of the teams is arranged in order of result. 1 on the top row and N on the Nth row. The over-ride of save_model() achieves nothing functional but is merely an effort to discover something using print() calls about the validation and save sequence. It seems to indicate to me that there is a separate and individual call made to save_model() for each and every record that is changed. So that if I have four teams initially 1 Red, 2 Blue, 3 Yellow, 4 Green and the admin wants to change this to 1 Blue, 2 Red, 3 Yellow, 4 Green then that triggers two separate calls to save_model(): eg 1 Red, 2 Blue, 3 Yellow, 4 Green -> 1 Red, 1 Blue, 3 Yellow, 4 Green and 1 Red, 1 Blue, 3 Yellow, 4 Green -> 1 Blue, 2 Red, 3 Yellow, 4 Green (the actual stages can vary - the reds could change first) What I want to be able to do is perform a final validation only after the final record is changed so that I can check that every record has a unique result in the range 1..N - i.e. there are no duplicated results. But in the intermediate call(s) to save_model() there will inevitably be at least one duplicated result - just one if the admin exchanges two results, but potentially more if he attempts a more complicated reshuffle. So I want to hook into / over-ride a procedure which is called just once when triggered by pressing the Save button, after all the separate save_model() calls are complete. I haven't been able to discover from the docs how to do this, or even if it can be done. Possibly my approach to this is wrong, either entirely or in part? Any advice would be helpful. Thanks -- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/399790a5-af0e-479b-a0fd-acf6ca3bfd59n%40googlegroups.com.