ModelForm et ForeignKey

29 novembre 2014
Aymeric

Je suis en train de développer un système d'invitation et je me suis retrouvé devant un problème que je souhaitais résoudre le plus élégamment possible.

L'explication en commentaire dans le code ci-dessous. Le code à été réduit au minimum pour se concentrer sur la partie Form

# Model
class Organisation(models.Model):
    name = models.CharField(max_length=255)

class Invite(models.Model):
    organisation = models.ForeignKey(Organisation)
    email = models.EmailField()

# Form
class InviteForm(ModelForm):
    def __init__(self, *args, **kwargs):
        # On passe la foreign_key en paramètre à partir de la view
        if kwargs.has_key('organisation'): self.organisation = kwargs.pop('organisation')
        super(InviteForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        # On sauve sans faire la requête SQL (commit=False) pour
        # pouvoir ajouter à l'instance l'organisation
        super(InviteForm, self).save(commit=False)
        # On ajoute à l'instance la foreign_key
        self.instance.organisation = self.organisation
        # On peut maintenant sauver
        super(InviteForm, self).save(commit)

    class Meta:
        model = model.Invite
        fields = ['email']

# View
def invite_add(request, oid):
    organisation = models.Organisation.objects.get(pk=oid)

    if request.method == 'POST':
        # Dans la vue j'envoie la foreign_key
        form = forms.InviteForm(request.POST, organisation=organisation)
        if form.is_valid():
            form.save()

Bien que je n'en soit pas entièrement satisfait, cette solution solution me convient pour plusieurs raisons:

  • La logique reste dans le Form (et pas dans la view comme j'ai pus le voir sur internet)
  • On n'altère pas le fonctionnement de save(). Le paramètre commit reste fonctionnel

Je n'ai pas trouvé d'autres solutions élégante pour faire cela, si vous en avez une je la prends avec plaisir ;).

Articles récents

Catégories

Tags