I have an appointment model for patient to book appointment with a doctor, i used a custom user model for both doctor and patients, using is_staff
and is_patient
to differentiate them...
class Appointment(models.Model):
doctor = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='staff',
on_delete=models.SET_NULL, null=True)
patient = models.ForeignKey(settings.AUTH_USER_MODEL, related_name=' ', on_delete=models.SET_NULL, null=True)
aptTime = models.DateTimeField(blank=True, null=True)
pending_approval = models.BooleanField(default=True, null=True)
approved = models.BooleanField(default=False, null=True)
in my views.py i am trying to set the patient to request.user
and doctor to the context i passed through the url, so i have the form_valid
method to create appointment like this...
class AppointmentCreateView(CreateView):
model = Appointment
fields = ['aptTime']
template_name = 'patients/Appointment-Createview.html'
def form_valid(self, form, *args, **kwargs):
form.instance.doctor = self.kwargs['pk'] #TODO change to doctor instance
form.instance.aptTime = self.object.aptTime
form.instance.patient = self.request.user
form.save()
i got an error saying ValueError: Cannot assign "1": "Appointment.doctor" must be a "User" instance. Internal Server Error: /patient/Appointment-Create/1/
After searching around SO i was able to change my code to...
...Some code...
def form_valid(self, form, *args, **kwargs):
User = get_user_model()
doc = User.objects.get(id=self.kwargs['pk'])
form.instance.doctor = doc #TODO change to doctor instance
form.instance.aptTime = self.object.aptTime
form.instance.patient = self.request.user
form.save()
now i'm getting a new error saying
form.instance.aptTime = self.object.aptTime
AttributeError: 'NoneType' object has no attribute 'aptTime'
I am using a model form, i don't understand why i'm getting this error. Someone please help me out.
CodePudding user response:
A CreateView
has no self.object
, this is always assigned None
. You do not have to access this anyway, since this is already assigned to the object wrapped in the form, so:
from django.contrib.auth.mixins import LoginRequiredMixin
class AppointmentCreateView(LoginRequiredMixin, CreateView):
model = Appointment
fields = ['aptTime']
template_name = 'patients/Appointment-Createview.html'
def form_valid(self, form):
form.instance.doctor_id = self.kwargs['pk']
form.instance.patient = self.request.user
return super().form_valid(form)
Your Appointment
model however seems a bit odd. For example why not work with a nullable field approved
that is NULL
/None
if it is not yet approved, True
if the doctor approved, and False
if the doctor rejected, this is probably better since otherwise the pending_approval
can be False
whereas approved
can still be None
resulting in a state that at least seems illogical:
class Appointment(models.Model):
doctor = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='appointments',
on_delete=models.SET_NULL,
null=True,
)
patient = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name=' ',
on_delete=models.SET_NULL,
null=True,
)
apt_time = models.DateTimeField()
approved = models.BooleanField(default=None, null=True)
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin
mixin [Django-doc].
Note: normally the name of the fields in a Django model are written in snake_case, not PascalCase, so it should be:
apt_time
instead of.aptTime