3 votes

Django UpdateView avec des champs uniques

Y a-t-il un moyen de mettre à jour un champ unique dans la vue de mise à jour ? J'ai un modèle qui a un champ name et un champ age mais lorsque j'essaie de mettre à jour l'age sans même changer la valeur du name, cela renvoie une erreur indiquant que le nom existe déjà dans la base de données.

models.py

class MyModel(models.Model)
  name = models.CharField(max_length=200, unique=True)
  age = models.IntegerField()

views.py

class MyModelUpdateView(UpdateView):
    def get(self):
        self.object = self.get_object()
        my_model = self.object

        form = MyModelForm(instance=my_model)

        return self.render_to_response(
            self.get_context_data(pk=my_model.pk, form=form)
        )

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()

        my_model = self.object

        form = MyModelForm(data=request.POST, instance=my_model)

        if form.is_valid():
            form.save()

            return some_url

        return self.render_to_response(
            self.get_context_data(pk=my_model.pk, form=form)
        )

forms.py

class MyModelForm(forms.ModelForm):

    class Meta:
        model = MyModel
        fields = (
            'name',
            'age',
        )

    def clean(self):
        cleaned_data = super().clean()

        if MyModel.objects.filter(
            actif=True, name=cleaned_data.get('name')
        ).exists():
            raise forms.ValidationError('MyModel existe déjà.')

        return cleaned_data

Qu'est-ce que j'ai manqué ici ? Merci.

2voto

CommuSoft Points 6439

Étant donné que vous mettez à jour un modèle et que vous ne modifiez pas le name, bien sûr un enregistrement avec ce nom existe déjà : cet enregistrement spécifique. Vous devriez donc modifier le code de vérification, pour :

class MyModelForm(forms.ModelForm):

    def clean(self, *args, **kwargs):
        cleaned_data = super().clean(*args, **kwargs)
        if MyModel.objects.exclude(pk=self.instance.pk).filter(
            active=True, name=cleaned_data.get('name')
        ).exists():
            raise forms.ValidationError('MyModel existe déjà.')
        return cleaned_data

    class Meta:
        model = MyModel
        fields = ('name', 'age')

Veuillez ne pas modifier la logique de base de la UpdateView, vous pouvez facilement implémenter ceci avec :

class MyModelUpdateView(UpdateView):
    form_class = MyModelForm
    success_url = 'URL quelconque'

Ceci étant dit, si vous avez déjà défini le champ comme unique=True, alors il n'est pas nécessaire de mettre en œuvre la vérification vous-même. Il semble qu'ici vous avez déjà une contrainte unique=True :

class MyModel(models.Model)
  name = models.CharField(max_length=200, unique=True)
  age = models.IntegerField()

Dans ce cas, vous pouvez simplement laisser le ModelForm faire le travail, alors votre formulaire ressemble à :

class MyModelForm(forms.ModelForm):

    class Meta:
        model = MyModel
        fields = ('name', 'age')

C'est seulement si vous voulez une unicité plus sophistiquée (comme avec active=True?), et que vous ne pouvez pas la représenter (facilement) vous devriez faire votre propre validation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X