Django - Name Error when views call model's method
Django - Name Error when views call model's method
I am a newbie in Django. I have defined the models and a method
from django.db import models
from django.contrib.auth.models import User
class Practice(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=200)
phone = models.IntegerField()
def __str__(self):
return self.name
class Doctor(models.Model):
specialisation = models.CharField(max_length=50)
practice = models.ForeignKey(Practice, related_name='doctor',on_delete=models.DO_NOTHING)
name = models.ForeignKey(User, related_name ='doctor', on_delete=models.DO_NOTHING)
selected = models.BooleanField()
def __str__(self):
return self.specialisation
def get_list_doctors(self):
all_doctors = User.objects.exclude(pk=1).filter(doctor__isnull=False)
all_doctors_names = all_doctors.values_list('last_name', 'first_name')
return all_doctors_names
class Patient(models.Model):
name = models.ForeignKey(User, related_name='patient', on_delete=models.DO_NOTHING)
height = models.DecimalField(max_digits=6, decimal_places=2)
weight = models.DecimalField(max_digits=6, decimal_places=2)
practice = models.ForeignKey(Practice, related_name='patient',on_delete=models.DO_NOTHING)
primary_doctor = models.ForeignKey(Doctor, related_name='patient',on_delete=models.DO_NOTHING)
class Appointment(models.Model):
start_time = models.DateTimeField()
end_time = models.DateTimeField()
doctor = models.ForeignKey(Doctor, related_name='appointment',on_delete=models.DO_NOTHING)
practice = models.ForeignKey(Practice, related_name='appointment',on_delete=models.DO_NOTHING)
patient = models.ForeignKey(Patient, related_name='appointment',on_delete=models.DO_NOTHING)
This is my view
def login_user(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, ('You Have Been Logged In!'))
doctor_list = get_list_doctors()
context = 'doctor_name': doctor_list
return render(request, 'homeunimed.html', context)
I am trying to use the method in the view. The reason for defining it in the model is so that I can reuse.
NameError at /
name 'get_list_doctors' is not defined
Request Method: POST
Request URL: http://localhost:8000/
Django Version: 2.1
Exception Type: NameError
Exception Value:
name 'get_list_doctors' is not defined
Exception Location: /Users/vinoojacob/Django/my_app/authenticate/views.py in login_user, line 27
Python Executable: /Users/vinoojacob/Django/bin/python
Python Version: 3.6.5
Python Path:
['/Users/vinoojacob/Django/my_app',
'/Users/vinoojacob/Django/lib/python36.zip',
'/Users/vinoojacob/Django/lib/python3.6',
'/Users/vinoojacob/Django/lib/python3.6/lib-dynload',
'/Users/Shared/anaconda3/lib/python3.6',
'/Users/vinoojacob/Django/lib/python3.6/site-packages']
However, I get this error. Any pointers to what is wrong. I thought you could access any methods defined in the model as long as the model is imported. Thanks for your help.
Thank you very much. Solved it now calling on model instance of Doctor.
– Vinoo P Jacob
Sep 16 '18 at 9:21
Just one comment: as you do not use the instance in your method, consider making this method a staticmethod by putting the deocrator @classmethod before the method and remove the self parameter. This will not change the functionality but would be the correct solution.
– ger.s.brett
Sep 16 '18 at 14:24
2 Answers
2
As you wrote you can access it via model. So decorate your method with @staticmethod, leave out self as argument and call it this way doctor_list = Doctor.get_list_doctors()
.
doctor_list = Doctor.get_list_doctors()
@staticmethod
def get_list_doctors():
all_doctors = User.objects.exclude(pk=1).filter(doctor__isnull=False)
all_doctors_names = all_doctors.values_list('last_name', 'first_name')
return all_doctors_names
Thank you! I think an instance is required, does not seem to work directly on model.
– Vinoo P Jacob
Sep 16 '18 at 9:22
@VinooPJacob Please see the edited answer. I would suggest not to call your method on object instance, since than you have to have an instance first. Your method returns all the doctors, so it is more universal to call it on Doctor model. This way you will be able to call it in any view, even in the views not containing the instance of a doctor.
– Uroš Trstenjak
Sep 16 '18 at 11:06
Thank you!! I don't need an instance, so makes lot of sense to make it static.
– Vinoo P Jacob
Sep 19 '18 at 2:45
@VinooPJacob Accepting the answer as correct would be great.
– Uroš Trstenjak
Sep 19 '18 at 16:13
The function get_list_doctors(self)
is pretty useless and exclude a user hardcoding its pk. This is pretty bad.
get_list_doctors(self)
A couple of suggestions:
1) Change the line in Doctor
name = models.ForeignKey(User, related_name ='doctor', on_delete=models.DO_NOTHING)
With:
user = models. OneToOneField(User, related_name ='doctor', on_delete=models.CASCADE)
The relation is a user and if the user is gone, then you must remove the Doctor too. And also, the relation is one to one!
2) You can get the list of the doctor very easily in your view
def login_user(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
messages.success(request, ('You Have Been Logged In!'))
doctors_list = Doctor.objects.exclude(user=user)
context = 'doctors_list': doctors_list
return render(request, 'homeunimed.html', context)
In your template, you can access the name of the doctors through the user (this is a very naive example)
% for doctor in doctors_list %
First name: doctor.user.first_name
Last name: doctor.user.last_name
% endfor %
Thank you. I will add CASCADE on delete, will keep it tidy and not have orphans! On your second suggestion, I am filtering (pk=1), just to remove 'admin' user from the list, not the logged-in-user. I can now see it is not an elegant way to do it, will rather have the flag set correctly in the data so that admin is filtered out rather than having to do it in the code. Good catch though.
– Vinoo P Jacob
Sep 19 '18 at 2:46
You can easily get all the not admin users:
User.objects.all().exclude(is_superuser=True)
– Karim N Gorjux
Sep 19 '18 at 3:48
User.objects.all().exclude(is_superuser=True)
Aha, that reads much better, thanks, learning a lot here!!
– Vinoo P Jacob
Sep 19 '18 at 7:15
Vote the answer if you’re satisfied
– Karim N Gorjux
Sep 19 '18 at 8:39
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy
The get_list_doctors is belonging to the model class. So you can only call it on a model instance of Doctor.
– ger.s.brett
Sep 16 '18 at 6:45