Obtaining queryset based on unrelated models - django

I've got the following models. I need to obtain a queryset of orders where the user's userprofile.setupstatus == 1. Is this possible or should I just add a foreign key field on the Order model to the UserProfile?
class Order(models.Model):
user = models.ForeignKey(UserCheckout, null=True, on_delete=models.CASCADE)
class UserCheckout(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
setupstatus = models.IntegerField(default=0)

It is surely possible with Django ORM
Your query should look somewhat like this
Order.objects.filter(user__user__userprofile__setupstatus=1)

Related

Django Rest Framework authentication with Custom User Model

I have multiple types of user in my django app: Employee and Patient. They have fields that are specific to each of them. They are implemented using the AbstractBaseUser model as below:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class User(AbstractBaseUser):
username = models.CharField(max_length=40, unique=True)
USERNAME_FIELD = 'identifier'
first_name = models.CharField(
max_length=50, null=False, blank=False)
last_name = models.CharField(
max_length=50, null=False, blank=False)
date_of_birth = models.DateField(null=False, blank=False)
USER_TYPE_CHOICES = (
(1, 'Patient'),
(2, 'Employee'),
)
user_type = models.PositiveSmallIntegerField(
choices=USER_TYPE_CHOICES, default=1, blank=False, null=False)
class Role(models.Model):
RoleName = models.CharField(max_length=50, null=False, blank=False)
class Employee(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True)
employment_start_date = models.DateField(null=False, blank=True)
employment_end_date = models.DateField(null=False, blank=True)
role = models.ForeignKey(
Role, on_delete=models.CASCADE, related_name='assigned_employees')
class Patient(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True)
I have a few questions with how to go forward with this:
How does just the choice in the User class limit the fields that a user has access to? If I had a HTML page would I create an Employee then a User would be created, or the other way round?
When I'm using Django Rest Framework, how can I implement a sign up and log in with the two different types?
I'm struggling to understand how this would work conceptually. Is like Employee and Patient a subclass of User? Or are they separate models? Any help or advice would be greatly appreciated
In your code you don't have two types of User. You have only one type - class User(AbstractBaseUser). Employee and Patient are normal models that are only related to User.
If you wanted to create two types of User with actual inheritence, then you should do following:
class AbstractUser(AbstractBaseUser):
class Meta:
abstract = True
# main user fields here
class Employee(AbstractUser):
# employee fields here
class Patient(AbstractUser):
# patient fields here
If you don't want to do this, your current approach is good. You can simply authenticate User in standard way. During creation you can make seperate forms for registering employee User, that creates automatically related Employee class. Similar for Patient. They will share only fields of User class with either approach.
To authenticate in different ways you can use custom authentication with authenticate() function. Read specifics in Django Docs

How to have multiple one to one relations to a specific model

I have a scientific info model that has a one-to-one relationship to my User model.
this is my model:
class ScientificInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
**other fields**
I want to add an interviewer field to it as well so that I can chose an interviewer from the user model so I added it like this:
class ScientificInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user')
interviewer = models.OneToOneField(User, on_delete=models.CASCADE, related_name='interviews')
**other fields**
but when I want to create a new user it gives me unique constraint failed error
You don't have to use OneToOneField because you're using two relations with the same table. You'd better use ForeignKey.
class ScientificInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='users')
interviewer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='interviews')
**other fields**

Django Rest Framework - How can I serialize a complex many-to-many object model with a custom table join?

I'm new to Django and Django REST Framework.
I have a fairly complex relationship model, the intent is to have a shopping cart with many orders:
class Product(models.Model):
name = models.CharField(max_length=200)
class Order(models.Model):
title = models.CharField(max_length=200)
items = models.ManyToManyField(Product, through='TableJoin')
class TableJoin(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
quantity = models.IntegerField()
I'm having trouble both using the ORM to pull a complete Order model (with relations), and to then serialize that.

It is possible to do a single complex query on these models rather than doing multiple queries?

With these models:
class User(AbstractUser):
pass
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="profile")
bio = models.CharField(max_length=250)
img = models.ImageField(upload_to='img_profiles/')
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="post")
text = models.CharField(max_length=260)
data = models.DateTimeField(auto_now_add=True)
class Following(models.Model):
follow = models.ForeignKey(User, on_delete=models.CASCADE, related_name="follow")
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name="follower")
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user_that_like")
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="post_like")
I would need to take data from Post, User and Profile for each Post that has Post.user=Following.follow where Following.follower=request.user.id. Added to that I nedd a Sum of Like.post for each Post catched.
The first part is ok with :
qs=Following.objects.values('follow__post__id','follow__post__text',
'follow__post__data','follow__username','follow__first_name','follow__last_name',
'follow__profile__img').filter(follower_id=request.user.id).order_by('-follow__post__data')
I would like to understand if it is possible to obtain the second part with the same query or if I need a second query / subquery
I would like to understand if it is possible to obtain the second part
with the same query
It is possible with annotation.
You can import Count from django.db.models import Count
and add .annotate(like_count=Count('follow__post__post_like')) to your query

Best way to filter queryset by counting number of ForeignKey in Django

I have 2 models, ChatRoom and Message:
Model ChatRoom:
class ChatRoom(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='chat_creator', null=True, blank=True)
with_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='room_user_with')
Model Message:
class Message(models.Model):
chat = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name='message_room')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='message_user')
content = models.TextField()
I want to filter ChatRoom queryset by getting ChatRoom which have more than 10 messages in it.
What is the best way to do this? Thank in advance!
ChatRoom.objects.annotate(cnt=Count('message_room')).filter(cnt__gt=20)
Your related_names are misleading :); they should refer to the model containing the foreign key from the perspective of the model the foreign key refers to, e.g. chat_messages and user_messages.