Bonjour!

J'apprends à utiliser et django et j'ai commencé à développer une app
web simple il y a 1 mois, mais j'ai un problème, quelque chose que je
n'arrive pas à faire.

J'ai un modèle appelé WeeklyPlaylist (models.py):
[code]
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)
[/code]

où 'position' désigne la position d'une vidéo dans une playlist.

J'aimerais permettre à l'admin d'intervertir les positions de 2 vidéos
faisant partie d'une même playlist, via le formulaire de modification/mise
à jour du modèle ci-dessus (admin.py):
[code]
class WeeklyPlaylistAdmin(admin.ModelAdmin):
    (...)
    readonly_fields = ('position',)
    form = WeeklyPlaylistAdminForm

    def get_changelist_form(self, request, obj=None, **kwargs):
        return WeeklyPlaylistAdminForm
[/code]

J'ai défini un formulaire spécial pour ce type d'objet (tjs dans
admin.py):
[code]
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
[/code]

Ce que j'ai en tête consiste simplement à ajouter un tag html 'select'
au formulaire de changement/mise à jour du modèle WeeklyPlaylist où l'on
pourrait entrer la nouvelle position de la vidéo dans la playlist, avec
les vérifications nécessaires dans la méthode clean_ correspondante pour
s'assurer que la position désirée est vallide.

Jusqu'ici tout va bien. Mon problème est le suivant : lorsque l'admin
clique sur 'save', comment puis-je simultanément sauvegarder l'objet
modifié ainsi que celui avec lequel il échange sa position dans la
playlist? J'ai essayé de faire ça dans la méthode save() du formulaire,
avec le code ci-dessous :

[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
[/code]

Mais pour une raison que j'ignore, 'commit' est tjs 'False' lorsque la
méthode est appelée, alors que 'm' est bien mis à jour dans la BDD
après la modification! Du coup, comme 'other.save()' n'est pas appelé,
l'autre objet n'est pas mis à jour, et les 2 objets se retrouvent avec la
même position! Et si j'enlève le 'if' qui vérifie la valeur de 'commit',
il me sera impossible par la suite de faire un save(commit=False) sur les
objets de type WeeklyPlaylistAdminForm, ce qui est pénalisant...

Merci d'avance pour votre aide!
Adrien
_______________________________________________
django mailing list
[email protected]
http://lists.afpy.org/mailman/listinfo/django

Répondre à