0

I want to get a message (ValidationError) on the form insted the of page with IntegretyError, from the 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)

I belive the best approuch would be to writr def clean() but since solicitante isn't one of the fields on the form i couldn't figure how to acess in clean.

I also plan to limit to 3 anwsers per user. I plan to use a query basead on the user in the clean field, bu again i couldn't figure how to access it.

1 Answers1

0
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!')

Victor
  • 2,864
  • 1
  • 12
  • 20