Django ModelForm as a layer of data validation

Question:

I have an authorization form, and I get an error – "already have a user with this email". I want to use the forms as a layer of validating the data.

I now, that i can pass instance of CustomUser in my form, but i can`t do it. Need other solution.

@require_http_methods(["POST"])
@not_logged_in_user_only()
def auth(request: WSGIRequest):
    form = UserAARForm(data=request.POST)

    if not form.is_valid():
        return JsonResponse({'status': 'error', 'message': f'{form.errors.as_json()}'})

    else:
        service = AuthenticateAndAuthOrRegistrUser()
        service.execute(req=request, data=form.clean())

        if service.errors:
            return HttpResponseServerError()
        
        return redirect("profile_page")

class SoundHomeUsers(models.Model):
    email = models.EmailField(
        max_length=254, 
        unique=True, 
        validators=[UserEmailValidator().is_valid])
    password = models.CharField(
        max_length=254,
        validators=[UserPasswordValidator().is_valid])

class UserAARForm(ModelForm):
    class Meta:
        model = SoundHomeUsers
        fields = ['email', 'password']

Asked By: Mark Markov

||

Answers:

Make the form a new and edit form, that way you won’t get that error!

General format:

# Grab existing object by email and edit, or grab None and create new
def auth_0(request: WSGIRequest):
    user_instance = None
    if request.POST.get('email'):
        # will return `None` if it doesn't find a User
        user_instance = SoundHomeUsers.objects.filter(email=request.POST.get('email')).first()

    form = UserAARForm(data=request.POST, instance=user_instance)
    # do the things

# Grab existing object by pk or None
#   Generally I always do it by PK and just post using hidden fields
#   Usually it's loaded into a `user's profile` or something
def auth_1(request: WSGIRequest):
    user_instance = None
    if request.POST.get('pk'):
        # will return `None` if it doesn't find a User
        user_instance = SoundHomeUsers.objects.filter(pk=request.POST.get('pk')).first()

    form = UserAARForm(data=request.POST, instance=user_instance)
    # do the things
Answered By: Nealium

I solve the problem, by extending ModelView and overriding method validate_unique. This allow me to use default ModelView validation queue, as just fields validation.

class BaseLayerValidationForm(ModelForm):
    def validate_unique(self):
        pass

class UserAARForm(BaseLayerValidationForm):
    class Meta:
        model = SoundHomeUsers
        fields = ['email', 'password']
Answered By: Mark Markov