So, I am a beginner and I'm coding a django application that has a 3 user types in total but to make the code readable and understandable I'm just gonna assume we have 2 user types. One is a doctor and one is a patient.
I've created this custom user so far:
in models.py
class User(AbstractUser):
is_doc = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
objects = UserManager()
manager.py
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
if email is None:
raise TypeError('Users must have an email address.')
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.save()
return user
def create_patient(self, email, password):
if password is None:
raise TypeError('Must have a password')
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.is_patient = True
user.save()
def create_superuser(self, email, password):
if password is None:
raise TypeError('Superusers must have a password.')
user = self.create_user(email, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
Patient Model is as follows:
class Patient(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=70)
last_name = models.CharField(max_length=70)
address = models.CharField(max_length=210)
phone = models.CharField(max_length=15)
email = models.EmailField(max_length=110)
password = models.CharField(max_length=65)
def __str__(self):
return self.first_name " " self.last_name
My form for Patient:
class PatientForm(forms.ModelForm):
class Meta:
model = Patient
fields = ['first_name', 'last_name', 'address', 'phone', 'email', 'password']
widgets = {
'first_name': forms.TextInput(attrs={'placeholder': 'First Name'}),
'last_name': forms.TextInput(attrs={'placeholder': 'Last Name'}),
'address': forms.TextInput(attrs={'placeholder': 'Address'}),
'phone': forms.TextInput(attrs={'placeholder': 'Phone Number'}),
'email': forms.EmailInput(attrs={'placeholder': 'Email'}),
'password': forms.PasswordInput(attrs={'placeholder': 'Password (Minimum Length: 8)'}),
}
Current Views.py:
def RegPatient(request):
if request.method == "POST":
form = PatientForm(request.POST)
if form.is_valid():
FName = form.cleaned_data['first_name']
LName = form.cleaned_data['last_name']
C_Address = form.cleaned_data['address']
C_Phone = form.cleaned_data['phone']
C_Email = form.cleaned_data['email']
C_Password = form.cleaned_data['password']
Reg = Patient(first_name= FName, last_name= LName, address= C_Address, phone= C_Phone, email= C_Email, password= C_Password)
Reg.save()
return HttpResponseRedirect('/Login/')
else:
for field in form.errors:
form[field].field.widget.attrs['class'] = ' is-invalid'
return render(request, 'Home/RegPatient.html', {'form': form})
else:
form = PatientForm()
return render(request, 'Home/RegPatient.html', {'form': form})
I have separate signups for patient and doctor and don't want a user type field in my form so I have all the detail fields in my form except user type. How should my view look like so that it saves Patient with a user type is_patient? and am I missing something out? Cause I've tried to edit it so many times, tried getting help from Django Docs but I'm still stuck.
CodePudding user response:
First, lets talk about the Manager
and Models
. The Manager
you are using is not really necessary, its possible to just set up the field on User
object creation. As for the Model
you can use model inheritance to have an extended Patient
model based on your User
model:
class User(AbstractUser):
is_doctor = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
class Patient(User):
address = models.CharField(max_length=210)
phone = models.CharField(max_length=15)
class Meta:
verbose_name_plural = "Patients"
Although, I would say the right approach to your problem is to use Django authentication groups, instead of adding fields to your User
model.
As for the signup form, it should contain confirmation and validation of the password and the username
field unless you are doing a login with email. To hold the information of is_patient
field, use an HiddenInput
(I couldn't replicate it with 'ModelForm' will need to dig further into that.):
forms.py
from django.contrib.auth.hashers import make_password
from django.forms import ValidationError
class PatientSignUpForm(forms.Form):
username = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'username'}))
first_name = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'first name'}))
last_name = forms.CharField(
required=False,
widget=forms.TextInput(attrs={'placeholder': 'last name'}))
email = forms.EmailField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'email'}))
address = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'address'}))
phone = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'XXX-XXXXXXXXX'}))
password = forms.CharField(required=True, widget=forms.PasswordInput)
password_confirmation = forms.CharField(required=True, widget=forms.PasswordInput)
is_patient = forms.BooleanField(widget=forms.HiddenInput)
def clean(self):
password = self.cleaned_data['password']
password_confirmation = self.cleaned_data['password_confirmation']
if len(password) < 8 or len(password_confirmation) < 8:
raise ValidationError("Passwords must have at least 8 characters")
elif password != password_confirmation:
raise ValidationError("Passwords must be equal")
else:
self.cleaned_data['password'] = make_password(self.cleaned_data['password_confirmation'])
del self.cleaned_data['password_confirmation']
return self.cleaned_data
Lastly, in views.py
create an instance of PatientSignUpForm
with an initial value for is_patient
field.
from app import models, forms
def patient_signup(request):
if request.method == 'POST':
form = forms.PatientSignUpForm(request.POST)
if form.is_valid():
models.Patient.objects.create(**form.cleaned_data)
return redirect('')
else:
form = forms.PatientSignUpForm(initial={'is_patient': True})
return render(request, 'patient_signup.html', {'form': form})