You are not logged in.

Change Language:

Freelancer? Consultant? Check out: WorkTrail - Time Tracking made easy
Board » Django Standard Library » Admin » Form to swap 2 objects in database with Django

I'm new to django and I've been developping a simple application for the past month or so, but I have a problem, something I did not manage to do. I have a simple model called WeeklyPlaylist (from my models.py):
class WeeklyPlaylist(models.Model):
    total_num_entries_in_playlist = 8
    get_pos_choices = get_integer_choices(1, total_num_entries_in_playlist)
    sched = models.ForeignKey(Schedule)
    week = models.IntegerField(choices=get_integer_choices(1, 52))
    position = models.IntegerField(choices=get_pos_choices)


where 'position' simply indicates the position of a video in a playlist. I'd like to provide the admin with the ability to swap the position of one video in a playlist with another video in that same playlist, through the change/update form of the model above (from my admin.py):

class WeeklyPlaylistAdmin(admin.ModelAdmin):
    (...)
    readonly_fields = ('position',)
    form = WeeklyPlaylistAdminForm

    def get_changelist_form(self, request, obj=None, **kwargs):
        return WeeklyPlaylistAdminForm


and I'm defining my own form for this object (still from admin.py):

class WeeklyPlaylistAdminForm(ModelForm):
    class Meta:
        model = WeeklyPlaylist
        fields = ('position',)

    swap_with_position = forms.IntegerField(widget=forms.Select(choices=WeeklyPlaylist.get_pos_choices))

    def clean_swap_with_position(self):
        swap_with_position = self.cleaned_data['swap_with_position']
        instance = getattr(self, 'instance', None)
        if instance and instance.id and swap_with_position == self.instance.position:
            raise forms.ValidationError("You must specify a different position than the actual one.")

        # select the database obj to swap position with
        other = WeeklyPlaylist.objects.filter(sched__screen__name=self.instance.sched.screen.name, sched__year__exact=self.instance.sched.year, week=self.instance.week, position=swap_with_position)
        if other.count() != 1:
            raise forms.ValidationError("The desired position does not correspond to any existing WeeklyPlaylist entry.")

        return swap_with_position


What I had in my mind basically was to provide an extra 'select' html tag to the admin in the change/update form of the WeeklyPlaylist model where he could enter the new position in the playlist for the current video, with the necessary checks in the associated clean_ method to make sure the desired playlist position is valid. So far so good. Now, my problem is the following: when the admin clicks on the 'save' button, how can I simultaneously save the modified object, and the one it is exchanging its position with? I've tried doing this in the save() method of the form, using the following code:

def save(self, commit=True, *args, **kwargs):
    m = super(WeeklyPlaylistAdminForm, self).save(commit=False, *args, **kwargs)
    cleaned_data = self.cleaned_data
    swap_with_position = cleaned_data.get("swap_with_position")
    if commit:
        # select the database obj to swap position with
        other = WeeklyPlaylist.objects.get(sched__screen__name=m.sched.screen.name, sched__year__exact=m.sched.year, week=m.week, position=swap_with_position)
        m.position, other.position = other.position, m.position
        m.save()
        other.save()
    return m


That seems perfectly fine, except that for some reason, commit is always false, even though 'm' is saved after the operation is finished, which is something I don't understand. But as a consequence, other.save() is never called, and if I remove the if statement checking the value of commit, I won't be able to do a save(commit=False) on the WeeklyPlaylistAdminForm objects, which can be annoying... So, any suggestions to help me? Many thanks in advance! Cheers! Adrien
On django 1.3, in admin application I use save_model function and not save, so probabily you overload a not correct function.
You find documentation here:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model
Make me know if this is the solution.

--- Last Edited by arwa at 2012-01-24 09:19:38 ---





Powered by Sphene Community Tools