1

I'm working on a Django (4.0+) project,, where I'm using the default User model for login, and a custom form for signup, and I have a Boolean field named: blogger in signup form, if user check this, i have to set is_staff true, otherwise it goes as normal user.

Here's what I have:

Registration Form:

class UserRegistrationForm(UserCreationForm):
    first_name = forms.CharField(max_length=101)
    last_name = forms.CharField(max_length=101)
    email = forms.EmailField()
    blogger = forms.BooleanField()

    class Meta:
        model = User
        fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2', 'blogger', 'is_staff']

views.py:

def register(request):
    if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            print(form['blogger'])
            if form['blogger']:
                form['is_staff'] = True
            form.save()

            messages.success(request, f'Your account has been created. You can log in now!')    
            return redirect('login')
        else:
            print(form.errors)
    else:
        form = UserRegistrationForm()

    context = {'form': form}
    return render(request, 'users/signup.html', context)

Its giving an error as:

TypeError: 'UserRegistrationForm' object does not support item assignment

How can i achieve that?

Abdul Rehman
  • 5,326
  • 9
  • 77
  • 150
  • Is there then a difference between `blogger` and `is_staff`? If `blogger` is True, then `is_staff` is `True` and vice versa, or not? – Willem Van Onsem Apr 08 '23 at 09:37

2 Answers2

0

You need to first save the user object, without commiting it to the database.

Also it's best practice to use form.cleaned_data to check the submitted data

form = UserRegistrationForm(request.POST)
if form.is_valid():
    user = form.save(commit=False)
    if form.cleaned_data['blogger']:
        user.is_staff = True
    user.save()
lucutzu33
  • 3,470
  • 1
  • 10
  • 24
  • Please *don't* work with `commit=False`. If later many-to-many relations are added, these will not be saved: https://www.django-antipatterns.com/antipattern/using-commit-false-when-altering-the-instance-in-a-modelform.html – Willem Van Onsem Apr 08 '23 at 09:52
  • That is why `save_m2m()` exists. But I agree that the method in your link is a little bit cleaner. – lucutzu33 Apr 08 '23 at 10:19
0

You can handle this in the .save(…) method [Django-doc] where you can first set the cleaned data of is_staff to True if blogger is set to True:

class UserRegistrationForm(UserCreationForm):
    first_name = forms.CharField(max_length=101)
    last_name = forms.CharField(max_length=101)
    email = forms.EmailField()
    blogger = forms.BooleanField()

    def save(self, *args, **kwargs):
        self.cleaned_data['is_staff'] |= self.cleaned_data['blogger']
        return super().save(*args, **kwargs)

    class Meta:
        model = User
        fields = [
            'username',
            'first_name',
            'last_name',
            'email',
            'password1',
            'password2',
            'blogger',
            'is_staff',
        ]

Then we can use the form like any other form:

def register(request):
    if request.method == 'POST':
        form = UserRegistrationForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            messages.success(
                request, f'Your account has been created. You can log in now!'
            )
            return redirect('login')
    else:
        form = UserRegistrationForm()

    context = {'form': form}
    return render(request, 'users/signup.html', context)

Since your view however follows a boilerplate format, it might be easier to work with a class-based view:

from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView


class RegisterView(SuccessMessageMixin, CreateView):
    form_class = UserRegistrationForm
    success_url = reverse_lazy('login')
    template_name = 'users/signup.html'
    success_message = 'Your account has been created. You can log in now!'
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555