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.

Reply via email to