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.






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






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

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)