Search code examples
pythondjangoformsmodeldatefield

Django: form validation - date not past and date for user unique


I have a problem with defining form in Django (python 3.7, django 3.0.8)

I create a model. This model has two very important fields: date and user_id.

Requirement: date and user_id are unique.

I create a form model to associated with the model. The logged in user completes the form and it is important that the defined date cannot be from the past and cannot appear in the database.

My problems:

One problem: My validation associated with date from the past WORKS CORRECT[!], but but if a past date is given, no error message is displayed.

Second problem: The second thing is that I have no idea how to prevent definition data, what it exist in database.

Code: models.py

class MyModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateField()
    ...(other fields)

    class Meta:
        unique_together = [['user', 'date']]

Code: forms.py

class AddMyModel(forms.Form):
    date = forms.DateField(widget=DateInput(attrs={'type': 'date'}),
                           )
    def clean_date(self):
        date = self.cleaned_data['date']
        if date < timezone.now().date():
            raise ValidationError("Date cannot be in the past")


        return date

Do you have any idea how to design the form to display in the template the error "date cannot be from the past" and error "the given date is already defined"?

views.py

def add(request):
    if request.user.is_authenticated:
        user = request.user.id

        if request.method == 'POST':
            form = AddMyModel(request.POST)
            if form.is_valid():
                date = form['date'].value()
                mymodel= MyModel(user=User(pk=user), date=date)
                mymodel.save()
                return render(request, 'mysite/successfuladd.html', {"login": True})
        form = AddMyModel()
        return render(request, 'mysite/add.html', {'form': form, 'login': True})
    else:
        return render(request, 'mysite/homepage.html', {'login': False})

Solution

  • I managed to fix the problem by myself. MyModels is the same.

    forms.py

    class AddMyModel(forms.ModelForm):
        def clean_date(self):
            date = self.cleaned_data['date']
            if date < timezone.now().date():
                raise forms.ValidationError(message='Date cannot be in the past')
            return date
    
        class Meta:
            model = MyModel
            fields = ('date')
            widgets = {
                'date': forms.DateInput(attrs={'type': 'date'})
            }
    

    views.py

    def add(request):
        if request.user.is_authenticated:
            user = request.user.id
            if request.method == 'POST':
                form = AddMyModel(request.POST)
                if form.is_valid():
                    date = form['date'].value()
                    if MyModel(user=User(pk=user), date=date):
                        unique_error = "User and date is already exist."
                        return render(request, 'mysite/add.html',
                                      {'form': form, 'login': True, 'unique_error': unique_error})
                    else:
                        mymodel= MyModel(user=User(pk=user), date=date)
                        mymodel.save()
                        return render(request, 'mysite/successfuladd.html', {"login": True})
                return render(request, 'mysite/add.html',
                              {'form': form, 'login': True})
            form = AddMyModel()
            return render(request, 'mysite/add.html', {'form': form, 'login': True})
        else:
            return render(request, 'mysite/homepage.html', {'login': False})