How to use select_related - django

How do I use select_related to get the first and last name of the employee class below.
class Employee(models.Model):
"""
Model, which holds general information of an employee.
"""
user = models.OneToOneField(User, related_name='users',
on_delete=models.CASCADE, unique=True)
photo_logo = models.FileField(null=True, blank=True)
Here is how I have implemented my query
emp=Employee.objects.filter(pk=1).select_related('user').values('user_first_name','user_last_name','id')
But I get the following logs after running a print statement in django shell
Cannot resolve keyword 'user_first_name' into field. Choices are: address, address_id, attendance, basic,

Since you need specific fields of user model, you dont need select_related in this case, just use:
emp=Employee.objects.filter(pk=1).values('user__first_name','user__last_name','id')
query.
Note that you shoulduse double underscore __ to perform join.

We should use __ for relation field
emp=Employee.objects.filter(pk=1).select_related(
'user'
).values('user__first_name','user__last_name','id')

Related

How to define models in django that provides custom values based on pre-selection for a field?

Given the following model that stores the user's wish list for reading books:
class ReadingList(models.Model):
user_id = models.ForeignKey(UserInfo, on_delete=models.DO_NOTHING, null=False, blank=False, default=None, db_column='user_id')
book= models.CharField(max_length=255, blank=False)
creation_time = models.DateTimeField(blank=True)
class Meta:
unique_together = (('user_id', book),)
I want to create a model that helps in tracking the time spent in the reading the book on different days which looks something like this:
class ReadingTracker(models.Model):
user_id = models.ForeignKey(ReadingList, on_delete=models.DO_NOTHING, related_name='user', blank=False, db_column='user_id')
book= models.ForeignKey(ReadingList, on_delete=models.DO_NOTHING, related_name='book-to-read', blank=False, db_column='book')
time = models.DateTimeField(blank=True)
time_spent = models.floatfield()
On the client-side (corresponding to ReadingTracker) for both the fields user_id and book
I see that ReadingList object (1), ReadingList object (2), ... are listed. But, this is not working as expected.
What I want to achieve are the following:
For user_id field I want to see the something like dummy_uid1, dummy_uid2, ... to be listed.
Consider dummy_uid1 wants to read book1 and book2 whereas dummy_uid2 wants to read book1 and book3.
When dummy_uid1 is selected as user_id, I want only book1 and book2 to be listed for selection.
How do I define the model in django rest framework to achieve this?
Any suggestions related to the above would be much appreciated and thank you in advance.
There are two parts to this question:
If you want to see a different value than ReadingList object (1) then you need to define the __str__ value of your model, you can do this like so:
class ReadingList(models.Model):
...
def __str__(self):
return f'{self.user_id}' # return whatever string you want to display
If you want to just display the books for a particular user then you can use a filter() (see the Django documentation):
reading_list = ReadingList.objects.get(...)
ReadingTracker.objects.filter(user_id=reading_list)
However, I would add that you have a user_id on your ReadingList object which does seem to connect to a User model, but your user_id on ReadingTracker is a ForeignKey relation to ReadingList, which is confusing. I would suggest renaming the field or actually making it link to the User model (though this is unnecessary as you can still filter by User through the ReadingList model).

How to make a model parameter unique by a other parameter in Django?

I want my id field to be unique per each customer field. Just like the option unique_for_date from Django (https://docs.djangoproject.com/en/1.11/ref/models/fields/#unique) but in this case, not date but customer.
class Sample(NGObject):
id = models.CharField(max_length=128, null=True, blank=False)
customer = models.ForeignKey(Customer, related_name="blood_samples", on_delete=models.SET(get_default_customer))
I believe this should be done, before the save() method?
When a User writes the wrong ID (that already exists) I would also like to present the information in the Admin Form just like it would for normal unique error.
class Meta:
unique_together = ('sample_id', 'customer',)
This has done the trick :)

Check if item exists in database by field value

I have a class called Product and I want to check if there is already a product in the database with the same title.
class Product(models.Model):
title = models.CharField(max_length=255)
...
for (something in something):
check if db contains product with a title of 'Some Product'
You can work with .exists() [Django-doc]:
Product.objects.filter(title='Some Product').exists()
It might however be better to enforce uniqness at the database level, with unique=True [Django-doc]:
class Product(models.Model):
title = models.CharField(max_length=255, unique=True)
then if the database enforces (most databases do), it will simply be impossible to create a new Product with the same title.
You can also obtain a Product, or create it if it does not yet exists, with .get_or_create(…) [Django-doc]:
my_prod, created = Product.objects.get_or_create(title='Some Product')

Authentication of different types of user of same name in django?

I have a model of teacher and student . If I created a Student and again create a teacher with same name and email and stuffs, It gets created .. Can't be a teacher and student of same people in a college. How to apply in rest api?
There are several way to solve this, depending on your requirements and preference.
One way would be at database level with constraints. In this case you'd have to create model with all people regardless of their status and add additional boolean field that differentiates between Students and Teachers. This would look like this:
class People(models.Model):
email = models.EmailField(unique=True)
is_teacher = models.BooleanField()
unique means that email must be unique throughout the table and if you try to add another person with the same email, IntegrityError will be raised.
There is also a possibility to use unique over several fields with unique_together like this.
class People(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Meta:
unique_together = (('first_name', 'last_name'),)
This means that first_name and last_name together must be unique.
Another approach would be to check if student or teacher is already in one or the other table before saving with filter() and exists().
teacher_exists = Teacher.objects.filter(teacher=something).exists()
student_exists = Teacher.objects.filter(student=something).exists()
exists() returns True if the QuerySet contains any results, and False if not.

Django order by related field

I want to sort a QuerySet of contacts by a related field. But I do not know how.
I tried it like this, but it does not work.
foundContacts.order_by("classification.kam")
Actually in a template I can access the kam value of a contact through contact.classification.kam since it is a OneToOne relationship.
The (simplified) models look like this:
class Classification(models.Model):
kam = models.ForeignKey(User)
contact = models.OneToOneField(Contact)
class Contact(models.Model):
title = models.ForeignKey(Title, blank=True, null=True)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
It should be:
foundContacts.order_by("classification__kam")
Here is a link for the Django docs on making queries that span relationships: https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships
You can also see some examples in the order_by reference:
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.order_by
as the documentation indicates, it should be used as in queries about related models
https://docs.djangoproject.com/en/3.0/ref/models/querysets/#order-by
foundContacts.order_by("classification__kam")
I've struggled a lot with this problem, this is how I solved it:
contact ordered by "kam" (Classification) field:
show_all_contact = Contact.objects.all().order_by(title__kam)
classification ordered by Users email (no sense in it, but only show how it works):
show_all_clasification = Classification.objects.all().order_by(kam__email)