I want to do a application with manages roles, and where one User can have multiple roles. I have created two models, one for the roles and other for the Users in models.py. My models.py looks like this:
class Role(models.Model):
DOCTOR = 1
NURSE = 2
DIRECTOR = 3
ENGENEER = 4
ROLE_CHOICES = {
(DOCTOR, 'doctor'),
(NURSE, 'nurse'),
(DIRECTOR, 'director'),
(ENGENEER, 'engeneer'),
}
id = models.PositiveIntegerField(choices = ROLE_CHOICES, primary_key = True)
def __str__(self):
return self.get_id_display()
class User(AbstractUser):
roles = models.ManyToManyField(Role)
Now what I want to do is establish the roles from the User form. My forms.py looks like this:
class UserCreationForm(UserCreationForm):
fields = ('username', 'password1', 'password2')
model = User
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Insert username'
self.fields['password1'].label = 'Insert password'
self.fields['password2'].label = 'Again'
class RoleCreationForm(forms.ModelForm):
class Meta:
model = Role
fields = ('id',)
And the views.py looks like this:
class UserCreateView(CreateView):
model = User
form_class = forms.UserCreationForm
template_name = 'user_form.html'
redirect_field_name = 'index.html'
success_url = reverse_lazy('accounts:index')
class RoleCreateView(CreateView):
model = Role
form_class = forms.RoleCreationForm
template_name = 'role_form.html'
redirect_field_name = 'index.html'
success_url = reverse_lazy('accounts:index')
How can I make to show all the roles in the User form and select multiple roles from there?
I assume your UserCreationForm
is subclass of forms.ModelForm
as well:
1) There are no password1
or password2
field in User
model - only password
. Hence, to make password confirmation you have to specify confirm_password
field and override clean
method to check that they are equal.
2) To show roles
in form, you can just specify 'roles'
in list of fields. Since roles
field exist in User
model, django will find correct widget, display and validate it correctly.
3) You didn't wrote about it, but I guess you added AUTH_USER_MODEL = '<you_app_name>.User'
to settings.py
? That will change default User
model to your app model.
4) Your UserCreateView
will store password in plain text, which is very bad idea. Read more about password management on how to properly store passwords.
class UserCreationForm(forms.ModelForm):
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta:
fields = ('username', 'password', 'confirm_password', 'roles')
model = User
widgets = {
'password': forms.PasswordInput(),
'roles': forms.CheckboxSelectMultiple()
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Insert username'
self.fields['password'].label = 'Insert password'
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"password and confirm_password does not match"
)
In reality you probably want to just create additional model with OneToOneField
to User
and ManyToManyField
to Role
instead of overriding django User
, since replacing django User
model can lead to problems.
Check out django authentication views . You can subclass AuthenticationForm
to add Roles
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.