django: ValidationError с UniqueConstraint для Model.Forms, clean () - PullRequest
0 голосов
/ 31 марта 2020

Я хочу получить сообщение (ValidationError) в форме, вставленной на страницу с IntegretyError, из UniqueConstraint.

models.py    
class Solicitacao(models.Model):
    '''Modelo de solicitação'''
    solicitante = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
    validators=[])
    disciplina = models.ForeignKey("Disciplina", on_delete=models.CASCADE,
                                   validators=[])
    [..some other data...]
    data_solicitacao = models.DateTimeField(
        ("Data da solicitação"), auto_now_add=True)

    class Meta:
        ordering = ['-data_solicitacao', 'solicitante']
        constraints = [
            models.UniqueConstraint(fields=['solicitante', 'disciplina'], name='unique_solicitação')                                                  
        ]

views.py

 @login_required
def nova_solicitacao(request):
    if request.method == 'POST':
        form = SolicitacaoForm(request.user, request.POST)
        form.instance.solicitante = request.user
        if form.is_valid():
            solicitacao = form.save(commit=False)
            solicitacao.save()
            return redirect(reverse_lazy('cc:solicitacoes'))
    else:       
        form = SolicitacaoForm(request.user)        
    return render(request, 'cc/solicitacao_form.html', {'form': form})

forms.py

class SolicitacaoForm(forms.ModelForm):
       class Meta():
            model = Solicitacao
            fields = ['disciplina', 'justificativa', 'documentos']

    def __init__(self, user, *args, **kwargs):
        super(SolicitacaoForm, self).__init__(*args, **kwargs)
        if not user.is_staff:
            curso = user.curso
        self.fields['disciplina'].queryset = Disciplina.objects.filter(curso=curso)

Я верю, что лучшим подходом будет писатель def clean(), но с solicitante это не одно из полей в форме, я не могу понять, как получить доступ к чистой.

Я также планирую ограничить до 3 пользователей на пользователя. Я планирую использовать запрос basead для пользователя в чистом поле, но опять же, я не мог понять, как получить к нему доступ.

1 Ответ

0 голосов
/ 31 марта 2020
class SolicitacaoForm(forms.ModelForm):
    class Meta():
        model = Solicitacao
        fields = ['disciplina', 'justificativa', 'documentos']

    def __init__(self, user, *args, **kwargs):
        super(SolicitacaoForm, self).__init__(*args, **kwargs)
        # Set the instance's solicitante to the passed user. With this, you no longer have to do it in your views.py as well
        self.instance.solicitante = user
        if not user.is_staff: # note that I moved the queryset filtering inside the if statement to avoid logical errors when user.is_staff is True
            self.fields['disciplina'].queryset = Disciplina.objects.filter(curso=user.curso)

    def clean(self, *args, **kwargs):
        super().clean(*args, **kwargs)
        # Get the values
        disciplina = self.cleaned_data['disciplina']
        solicitante = self.instance.solicitante  

        # Find the duplicates
        duplicates = Solicitacao.objects.filter(
            disciplina=disciplina, 
            solicitante=solicitante
        )
        if self.instance.pk: # if the instance is already in the database, make sure to exclude self from list of duplicates 
             duplicates = duplicates.exclude(pk=self.instance.pk)
        if duplicates.exists():
             raise forms.ValidationError('Solicitacao with similar disciplina and solicitante already exists!')

...