Can't convert 'DeferredAttribute' object to str implicitly - django

When Iam trying to get the degree of a student and do the return value with that code:
def __str__(self):
return self.student_subject + " " + Student.last_name
I got the above error message.
Here is the whole Django code:
from django.db import models
# Create your models here.
class Student(models.Model):
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=15)
age = models.IntegerField(default=0)
birth_date = models.DateTimeField()
def __str__(self):
return self.first_name + " " + self.last_name
class Degree(models.Model):
student_id = models.ForeignKey(Student, on_delete=models.CASCADE)
student_subject = models.CharField(max_length=150)
student_degree = models.IntegerField(default=0)
def __str__(self):
return self.student_subject + " " + Student.last_name
the error is happening because I trying to inherite the return from the above class Student
And here is the error message:
TypeError at /admin/sellingportal/degree/
Can't convert 'DeferredAttribute' object to str implicitly
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/sellingportal/degree/
Django Version: 1.10.1
Exception Type: TypeError
Exception Value:
Can't convert 'DeferredAttribute' object to str implicitly
Exception Location: C:\Users\Muham\PycharmProjects\managementsite\managementstudio\sellingportal\models.py in __str__, line 22
Python Executable: C:\Python34\python.exe
Python Version: 3.4.4
Python Path:
['C:\\Users\\Muham\\PycharmProjects\\managementsite\\managementstudio',
'C:\\Windows\\SYSTEM32\\python34.zip',
'C:\\Python34\\DLLs',
'C:\\Python34\\lib',
'C:\\Python34',
'C:\\Python34\\lib\\site-packages']
Server time: Fri, 16 Sep 2016 01:04:08 +0200

Just change it to:
def __str__(self):
return self.student_subject + " " + self.student_id.last_name
and all should be fine.
You cannot set Student.last_name because you have to show from which object, should the last name be taken from.

Related

Average age from birth date in django

In my django(3.0.5) application I am trying to get average age from date of birth in a model. I am using MySql database.
Here is how I tried:
Model:
class ShippingStaff(models.Model):
full_name = models.CharField('Full Name', max_length=200)
birth_date = models.DateField('Date of Birth', null=True, blank=True)
Customer Filter:
#register.filter(name='age')
def age(bday, d=None):
if d is None:
d = datetime.date.today()
return (d.year - bday.year) - int((d.month, d.day) < (bday.month, bday.day))
Views:
def home(request):
shipping_staff = ShippingStaff.objects.aggregate(staff_count=Count('full_name'),
avg_age=Avg(custom_time.age('birth_date'))
I get error like:
Exception Value:
'str' object has no attribute 'year'
Exception Location: /home/smrashel/jahaji/crewdatabd/templatetags/custom_time.py in age, line 31
which is
return (d.year - bday.year) - int((d.month, d.day) < (bday.month, bday.day))
How can I solve this?
Any help will be much appreciated.
You need to change str to date. So you could use datetime.strptime like this:
from datetime import datetime
datetime_str = '08/12/12'
d = datetime.strptime(datetime_str, '%m/%d/%y')
print(d.year)
>>> 2012
In your case:
#register.filter(name='age')
def age(bday, d=None):
b = datetime.strptime(datetime_str, '%m/%d/%y')
if d is None:
d = datetime.date.today()
return (d.year - bday.year) - int((d.month, d.day) < (bday.month, bday.day))
Of course it depends how your str date looks like, you need to adapt it to your needs

How to join 2 attributes to create a name in Django model instance?

I have a model:
class Subject(models.Model):
level = models.CharField(choices=LEVEL_CHOICES, max_length=2)
subject_name = models.CharField(max_length=50)
teacher_name = models.ForeignKey(Teacher, on_delete=models.CASCADE)
total_seats = models.IntegerField()
subject_details = models.CharField(max_length=100)
subject_img = models.ImageField()
I want to display each instance as level and then subject name. For example, if the instance has a level 'Advanced' and subject_name as 'Physics', I want the instance to be displayed as 'Advanced Physics'.
I have tried using str method but it shows subject_name is not defined:
def __str__(self):
return self.level+ ''+ subject_name
EDIT:
I forgot to mention that level field takes in choices, as so:
LEVEL_CHOICES = (
('09', 'Class 9 O level'),
('10', 'Class 10 O level'),
('11', 'AS level'),
('12', 'A2 level'),
)
How do I display the data that is visible to human? ie. the ones on the right as the level
These are attributes defined on the self object, so you implement this as:
def __str__(self):
return self.level + '' + self.subject_name
or you perhaps can use string formatting here:
def __str__(self):
return f'{self.level}{self.subject_name}'
If you want to use the display value for the choice of level, you can call the get_level_display method:
def __str__(self):
return self.get_level_display() + '' + self.subject_name
You need to refer to self to access subject_name as such:
def __str__(self):
return self.level + ' ' + self.subject_name
or formatted via Python3:
def __str__(self):
return '{0} {1}'.format(self.level, self.subject_name)
and to get the human readable value, you can simply use the .get_FOO_display() method:
def __str__(self):
return '{0} {1}'.format(self.get_level_display(), self.subject_name)
Model.get_FOO_display(): https://docs.djangoproject.com/en/3.0/ref/models/instances/#django.db.models.Model.get_FOO_display

My pre_save signal isn't applying my string generator

I wrote a simple string generator for my order_id field.
I tested the generator script in shell, and it works perfectly.
But when I run the server, and try to create an order in django admin, the order id field remains empty when I click save.
What am I doing wrong?
from datetime import date
from django.db import models
from django.db.models.signals import pre_save
from cartapp.models import Cart
class Order(models.Model):
order_id = models.CharField(max_length=120)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
status = models.CharField(max_length=50, default='Waiting', null=True, blank=True)
order_total = models.DecimalField(default=0.0, max_digits=10, decimal_places=1)
date_created = models.DateTimeField(auto_now_add=True)
def order_id_generator(instance):
today = date.today().strftime("%Y-%m-%d")
last_order_raw = Order.objects.latest('order_id').date_created
last_order_date = str(last_order_raw).split(' ')[0]
if today != last_order_date:
new_order_id = str(today + " 1")
else:
last_order = Order.objects.latest('order_id')
extract = last_order.order_id.split(' ')[1]
increment = int(extract) + 1
new_order_id = today + " " + str(increment)
return new_order_id
def pre_save_order_id(sender, instance, *args, **kwargs):
if not instance.order_id:
instance.order_id = order_id_generator(instance)
pre_save.connect(pre_save_order_id, sender=Order)
I noticed that you are passing instance to order_id_generator but doesn't use it there. You can avoid using signals and you can use your function as the model field default:
class Order(models.Model):
order_id = models.CharField(max_length=120, default=order_id_generator)
and you doesn't need an arg instance in your function:
def order_id_generator():
today = date.today().strftime("%Y-%m-%d")
last_order_raw = Order.objects.latest('order_id').date_created
last_order_date = str(last_order_raw).split(' ')[0]
if today != last_order_date:
new_order_id = str(today + " 1")
else:
last_order = Order.objects.latest('order_id')
extract = last_order.order_id.split(' ')[1]
increment = int(extract) + 1
new_order_id = today + " " + str(increment)
return new_order_id

Django : Primary Key is getting null value

Consider the following model :
from django.db import models
class Album(models.Model):
id = models.IntegerField(primary_key=True,null=False)
artist = models.CharField(max_length=200)
album_title = models.CharField(max_length = 250)
genre = models.CharField(max_length=100)
album_logo = models.CharField(max_length = 200)
def __str__(self):
return "id = " + str(self.id) + " artist = " + self.artist + " album = " + self.album_title + " genre = " + self.genre
class Song(models.Model):
id = models.IntegerField(primary_key=True)
album = models.ForeignKey(Album,on_delete=models.CASCADE)
file_type = models.CharField(max_length = 200)
song_title = models.CharField(max_length = 200)
def __str__(self):
return "id = " + str(self.id) + "album = " + self.album.album_title + "song = " + self.song_title
When i am inserting a row in either Album or Song using positional parameters and not giving, django is providing NULL to that particular row. Why so?
First of all, there is no need of explicitly declaring a field named 'id' as Django already creates an id field with every model by default and auto-increments it.
In any case, if you want to deliberately declare a primary key it is recommended do it in the following manner:
id = models.AutoField(primary_key=True)
This is an auto-incrementing primary key.
Reference Official Django Docs:
https://docs.djangoproject.com/en/1.11/topics/db/models/#automatic-primary-key-fields

invalid literal for int() with base 10: 'John Doe'

i have a model patient and another one exam, now i want to retrieve patient's exams based on the name, but i am stuccoed with the error invalid literal for int() with base 10: 'John Doe'
ValueError at /labtech/John Doe/see_exam
invalid literal for int() with base 10: 'John Doe'
Request Method: GET
Request URL: http://homasoft.com:8000/labtech/John%20Doe/see_exam
Django Version: 1.8
Exception Type: ValueError
Exception Value:
invalid literal for int() with base 10: 'John Doe'
Exception Location: /Library/Python/2.7/site- packages/django/db/models/fields/__init__.py in get_prep_value, line 985
Python Executable: /usr/bin/python
Python Version: 2.7.5
Python Path:
['/Users/mymacbookpro/Documents/Virtualenvs/hospital/src',
'/Library/Python/2.7/site-packages/pip-1.4.1-py2.7.egg',
'/Users/mymacbookpro/Documents/Virtualenvs/hospital/src',
'/Users/mymacbookpro/Documents/Virtualenvs/hospital/src/django-social-auth',
'/Users/mymacbookpro/Documents/Virtualenvs/hospital/src/django-socialprofile',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat- darwin',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
'/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
'/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC',
'/Library/Python/2.7/site-packages']
Server time: Mon, 1 Jun 2015 12:27:27 +0000
here is my view
def see_exam(request, name):
exam = Test.objects.filter(patient__user__exact=name)
context = {
'exam' : exam
}
return render(request, 'account/labtechs/see_results.html', context)
model exam
class Test(models.Model):
exam = models.ForeignKey(Exam)
patient = models.ForeignKey(Patient)
date = models.DateField()
result = models.TextField(default="negative")
done_by = models.CharField(max_length=120)
def __unicode__(self):
return self.exam.name
model for patient
class Patient(models.Model):
"""docstring for Patient"""
user = models.OneToOneField(MyUser)
date_of_birth = models.DateTimeField(blank=True, null=True)
age = models.IntegerField(default=1)
sex = models.OneToOneField(Sex)
religion = models.CharField(max_length=120, blank=True, null=True)
village = models.CharField(max_length=120)
status = models.OneToOneField(Status, blank=True, null=True)
relative = models.CharField(max_length=120)
phone = models.IntegerField(default=1)
allergies = models.TextField(default="", blank=True, null=True)
defficiencies = models.TextField(default="", blank=True, null=True)
created_at = models.DateTimeField(auto_now=True)
updated_at = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return "%s %s" %(self.user.first_name, self.user.last_name)
Change the query
exam = Test.objects.filter(patient__user__exact=name)
to
exam = Test.objects.filter(patient__user__name__exact=name)
#------------------------------------------^
Note the user__name added. Here I'm assuming your MyUser class has attribute name that you want to compare.
In your query you are trying to compare string name with object user (or rather internally id of that object) which is not compatible.