Home > Back-end >  Django no access to certain methods AbstractUser using UserManager
Django no access to certain methods AbstractUser using UserManager

Time:12-16

I am new to Django I am trying to get access to form.save() using form = self.form_class(request.POST) but I have been having to use methods like self.get_form_class() to access form.is_valid() and form.save() but cannot get method set_password() from user = form.save(commit=False) I am not sure what the problem is. Why cant I access user.set_password()? Even when I try to create a BaseUserManager self.model() does not give me a definition for user.set_password() or user.save() why is this?

# views.py
class RegistrationView(CreateView):

    template_name = "AskQuestions/customuser_form.html"
    form_class = RegistrationForm
    model = CustomUser
    success_url = "questions/login"

    def get(self, request, *args, **kwargs):
        form = self.get_form_class()
        form = form(initial=self.initial)
        return render(request, self.template_name, {"form": form})

    def post(self, request):
        form = self.get_form_class()
        form = form(request.POST)
        if (form.is_valid()):
            user = form.save(commit=False)

            # user.set_password() no definition
            user.set_password()

            messages.add_message(request, messages.SUCCESS, "Your account has been successfully created.")
            return redirect("AskQuestions:login")
        else:
            return render(request, self.template_name, {"form": form})

# models.py
class CustomUser(AbstractUser):

    phone_number = models.CharField(max_length=20)

    REQUIRED_FIELDS = ["first_name", "last_name", "phone_number"]

# forms.py
class RegistrationForm(forms.ModelForm):
    confirm_password = forms.CharField(label="Confirm password:", max_length=200, widget=forms.PasswordInput(attrs={"class": "form-control"}))
    class Meta:
        model = CustomUser
        fields = ["first_name", "last_name", "username", "phone_number", "password",]

        labels = {
            "first_name": "Name:",
            "last_name": "Last name:",
            "username": "Username",
            "phone_number": "Phone number:",
            "password": "Password",
            "confirm_password": "Confirm password:",
        }

        widgets = {
            "first_name": forms.TextInput(attrs={"class": "form-control"}),
            "last_name": forms.TextInput(attrs={"class": "form-control"}),
            "username": forms.TextInput(attrs={"class": "form-control"}),
            "phone_number": forms.TextInput(attrs={"class": "form-control"}),
            "password": forms.PasswordInput(attrs={"class": "form-control"}),
        }

    def clean(self):
        data = self.cleaned_data

        first_name = data["first_name"]
        last_name = data["last_name"]
        username = data["username"]
        password = data["password"]
        confirm_password = data["confirm_password"]
        
        if not first_name:
            raise forms.ValidationError("You must supply a name.")
        if not last_name:
            raise forms.ValidationError("You must supply a last name.")
        if not username:
            raise forms.ValidationError("You must supply a username.")
        else:
            username_exists = CustomUser.objects.filter(username=username).exists()
            if (username_exists):
                self.add_error("username", "This username has already been taken.")

        if not password:
            raise forms.ValidationError("You must supply a password.")
        if not confirm_password:
            raise forms.ValidationError("You must supply a password to compare against.")
        if not password == confirm_password:
            raise forms.ValidationError("Passwords do not match.")
        return data

CodePudding user response:

  1. You could create RegistrationForm inherited from UserCreationForm
# forms.py
from django.contrib.auth.forms import UserCreationForm


class RegistrationForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ("first_name", "last_name", "username", "phone_number",)

regarding clean method - you dont have to check if user send some certain field, just in your CustomUser model you have to add those fields without null=True, blank=True. as an example:

class CustomUser(AbstractUser):
    first_name = models.CharField(_("first name"), max_length=150)

and now i could delete checks for first_name in your Registration form clean-method. As result of this refactoring - clean-method should be deleted. Dont worry about confirm_password field, it exists in UserCreationForm but called as password2, original password called as password1. and checks for password in this form also exists

  1. Answer for your question with the set_password from the previous point we got a form inherited from UserCreationForm which have this set_password logic already written in save method. You just need to call form.save() so your post-method in view:
    def post(self, request):
        form = self.get_form_class()
        form = form(request.POST)
        if form.is_valid():
            form.save()

            messages.add_message(request, messages.SUCCESS, "Your account has been successfully created.")
            return redirect("AskQuestions:login")
        return render(request, self.template_name, {"form": form})
  • Related