0

I am using a Userprofile form with an UpdateView and encountering an issue where validation errors are not being raised, even when the conditions for the errors to be raised are met. What could be causing this unexpected behavior?

forms.py.

class UserProfileForm(forms.ModelForm):
    
    class Meta:
        model = UserProfile
        fields = ("avatar","username","first_name","last_name","age","gender")
        # fields = ("avatar",)
        Gender = (
            ('one','Male'),
            ('two','Female'),
            )
            
        widgets ={
            'age' : forms.TextInput(attrs={'class':'form-control'}),
            'gender' : forms.Select(choices=Gender,attrs={'class': 'form-control'}),
        }
     # TRIED THIS AS WELL    
    # def clean_age(self):
    #     age = self.cleaned_data["age"]
    #     print(age,'hm here')
    #     if age < 18:
    #         print(age,'hm here')
    #         raise forms.ValidationError("You're age should be 18 plus")
    #     return age

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

        age = cleaned_data.get('age')
        print('haye',age)
        if age < 18:
            print(age,'hm here')
            # raise forms.ValidationError("You're age should be 18 plus")
            age = "You're age should be 18 plus"
            self.add_error('age',age)
            raise forms.ValidationError("You're age should be 18 plus")

views.py here i'm updated user model fields and then userprofile field and then saving them respectively.

class UserProfileUpdateView(UpdateView):
    refirect_field_name ='accounts:profile'
    template_name = 'accounts/profiles/profile_update.html'
    form_class = UserProfileForm
    model = UserProfile

    def get_object(self, *args, **kwargs):
        return self.request.user.userprofile
    
    def get_context_data(self, *args, **kwargs):
        context = super(UserProfileUpdateView, self).get_context_data(*args, **kwargs)
        update_form = UserProfileForm(instance = self.request.user.userprofile)
        context['form']=update_form
        return context
    
    def form_valid(self, form):
            username = form.cleaned_data['username']
            print('username :',username)
            first_name = form.cleaned_data['first_name']
            print('first name :',first_name)
            last_name = form.cleaned_data['last_name']
            print('last name :',last_name)
            age = form.cleaned_data['age']
            print('age :',age)
            gender = form.cleaned_data['gender']
            print('gender :',gender)
            # usermodel save
            user = User.objects.get(username=self.request.user)
            print('GOT reqested User',user)
            user.username = username
            print('changed username :',user.username)
            user.age = age
            print('changed age :',user.age)
            user.gender = gender
            print('changed gender:',user.gender)
            user.first_name = first_name
            print('changed first name :',user.first_name)
            user.last_name = last_name
            print('changed last name :',user.last_name)
            user.save()
            # userprofile save
            profile = UserProfile.objects.get(user=self.request.user)
            print('GOT reqested User',profile)
            profile.username = username
            print('changed username :',profile.username)
            profile.age = age
            print('changed age :',profile.age)
            profile.gender = gender
            print('changed gender:',profile.gender)
            profile.first_name = first_name
            print('changed first name :',profile.first_name)
            profile.last_name = last_name
            print('changed last name :',profile.last_name)
            profile.save()
            form.save()
            return super().form_valid(form) 

models.py

class UserProfile(models.Model):

    user = models.OneToOneField(auth.models.User,related_name='userprofile', on_delete=models.CASCADE)
    avatar = models.ImageField(("displays"), upload_to='displays', height_field=None, width_field=None, max_length=None,default ='user.jpg')
    create_date = models.DateTimeField(default = timezone.now)
    Gender = (
    ('one','Male'),
    ('two','Female'),
    )
    first_name = models.CharField(("first_name"), max_length=50,null=True)
    last_name = models.CharField(("last_name"), max_length=50,null=True)
    username = models.CharField(("username"), max_length=50,null=True)
    age = models.IntegerField(("age"),null=True)
    gender = models.CharField(("gender"), max_length=50,choices=Gender,null=True)


    def __str__(self):
        return f'{self.user.username} UserProfile'
    
    def clean_fields(self, exclude=None):

        if self.age < 18:
            raise ValidationError(
                {"age": "You're age should be 18+"}
            )
        return super().clean_fields(exclude=exclude)

    def save(self,*args, **kwargs):
        if not self.username:
            self.username  = self.user.username
        if not self.age:
            self.age = self.user.age
        if not self.gender:
            self.gender  = self.user.gender
        if not self.first_name:
            self.first_name  = self.user.first_name
        if not self.last_name:
            self.last_name  = self.user.last_name
        super(UserProfile,self).save(*args, **kwargs)

Please tell me how can i fix this issue and raise errors on unvalid details. If more information is require then tell me in a comment section, I'll update my question with that information.

Ahmed Yasin
  • 886
  • 1
  • 7
  • 31

1 Answers1

0

By using both methods there is no need to override form's clean method and the object is validated whenever you create an instance.

Method 1: Override clean_fields method of class UserProfile in models.py

def clean_fields(self, exclude=None):

    if self.age < 18:
        raise ValidationError(
            {"age": "You're age should be 18+"}
        )

    return super().clean_fields(exclude=exclude)

Method 2: Add min value validation for age field while defining it

age = models.PositiveIntegerField(
    help_text="Age of the user.",
    validators=[
        MinValueValidator(
            18, "You're age should be 18+"
        )
    ]
)

Your views:

def form_valid(self, form):
    # userprofile save
    profile = form.save(commit=False)
    # usermodel save
    user = self.request.user
    user.username = profile.username
    user.age = profile.age
    user.gender = profile.gender
    user.first_name = profile.first_name
    user.last_name = profile.last_name
    user.save()
    return super().form_valid(form)
Agawane
  • 173
  • 1
  • 8
  • never mind, I didn't show you my models.py and you are saying me to add the first method in the models.py right ?. I'm having an issue in understanding what you tell in your answer, , can you please tell me what I have to remove in my code and what I have to add and where I have to add . – Ahmed Yasin Jan 05 '21 at 13:01
  • I have added models.py with adding the first method you told me to add in models.py , Check and tell me if i'm going wrong cause that is not working. – Ahmed Yasin Jan 05 '21 at 13:06
  • I failed to notice your form_valid in views earlier. Try method 2. To make it work with method 1, you will need to call profile.full_clean() before profile.save() – Agawane Jan 05 '21 at 13:33
  • From where i import `MinValueValidato` ? – Ahmed Yasin Jan 05 '21 at 13:37
  • from django.core.validators import MinValueValidator – Agawane Jan 05 '21 at 13:38
  • i believe you are using a custom user model that has age, gender, fields as well – Agawane Jan 05 '21 at 13:44
  • Oky I did that and thats not saving the wrong input but not showing error. On the wrong data. – Ahmed Yasin Jan 05 '21 at 13:44
  • Yeah I'm using custom user moel – Ahmed Yasin Jan 05 '21 at 13:45
  • You will need to show errors in your template. https://stackoverflow.com/questions/14647723/django-forms-if-not-valid-show-form-with-error-message – Agawane Jan 05 '21 at 13:54