How to make a query across multiple models in Django - django

I'm using Django and I want to know how to get objects through 3 models
These are my models
class Participant(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
is_leader = models.BooleanField(default=False)
team = models.ForeignKey(Team, on_delete=models.CASCADE, null=True, related_name="participants")
application_date = models.DateField(auto_now_add=True, null=True)
resolution_date = models.DateField(null=True, blank=True)
accepted = models.BooleanField(default=False)
class Team(models.Model):
name = models.TextField(default="")
is_public = models.BooleanField(default=False)
institution = models.ForeignKey(Institution, on_delete=models.CASCADE, null=True, related_name='teams')
campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE, null=True, related_name='teams')
class Campaign(models.Model):
name = models.TextField(default="")
description = models.TextField(default="")
initial_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
end_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
qr_step_enabled = models.BooleanField(default=True)
image_resolution = models.IntegerField(default=800)
sponsor = models.ForeignKey(Sponsor, on_delete=models.CASCADE, null=True, related_name='campaigns')
I have the user through a request, and I want to get all campaigns of that user.
I tried doing it with for loops but I want to do it with queries
this is what I had:
user = request.user
participants = user.participant_set.all()
for participant in participants:
participant.team.campaign.name
is there a way to make a query through these models and for all participants?
A user can have many participants, and each participant has a Team, each team has a campaign

The best way is to merge the two modela Team and Campaign in one model.

Something as simple as this should work:
Campaign.objects.filter(team__participant__user=request.user)
The Django ORM is smart enough to follow foreign key relationships in both directions.

Thanks to Daniel W. Steinbrook to guide me to the answer, I had to do this to get the query:
Campaign.objects.filter(teams__participants__user__exact=request.user)

Related

Write django query to select users and order users by latest conversation they had?

My models:
class User(models.Model):
id = models.UUIDField(primary_key=True)
first_name = models.Charfield()
class Conversation(models.Model):
id = models.UUIDField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
class Message(models.Model):
id = models.UUIDField(primary_key=True)
conversation = models.ForeignKey(Conversation, on_delete=models.PROTECT, null=False)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True, blank=True)
I tried to to order by adding annotate and adding order by. Can some body help me to select all users and order them by the latest message they had. I need user with latest message at to and then accordingly.
Try this
queryset = User.objects.all().order_by(
'-conversation__message__created_at'
).distinct()

Django: handle multi stock (related table) in Product Based List View

I need to manage Products shared by multiple Warehouses.
I tried to get through with annotate, prefetch_related, select_related but in my case, those solutions are upside-down for my need. I need first to get product and then, the related stock in each warehouse and display it in template and the foreignKey is in my Sststock, not in Product
I have :
Product models.py
class Product(models.Model):
famille = models.ForeignKey(Famille, on_delete=SET_NULL, null=True)
sku = models.CharField(max_length=100, unique=True)
nom = models.CharField(max_length=250)
fournisseur = models.ForeignKey(
Supplier, on_delete=models.SET_NULL, default=12, null=True)
qty = models.IntegerField()
mini = models.IntegerField()
maxi = models.IntegerField()
[...]
Warehouse models.py
class Warehouse(models.Model):
nom = models.CharField(max_length=100)
code = models.CharField(max_length=10, null=True)
adresse = models.CharField(max_length=255)
cp = models.IntegerField()
ville = models.CharField(max_length=50)
tel = models.CharField(max_length=10)
email = models.EmailField(default='sav#iturbo.fr', null=False, blank=False)
allow_store = models.BooleanField(default=False)
def __str__(self):
return self.nom.upper()
Sststock models.py
class SstStock(models.Model):
sst = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
mageid = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
qty = models.IntegerField()
last_update = models.DateTimeField(default=timezone.now)
For the time, I only have 3 warehouses but there could have more in the future.
First I had "hard-coded" my 3 warehouses in Product's model but this solution was not easily scalable.
What would be the best way to achieve my goal ?
I've seen solution with Mysql Stored Procedures in PhpMyAdmin for creating innerJoin tables but there is maybe possibilities within Django.

How to develop Cart models and Cart Items model in django rest framework

I am trying to create models for backend in django rest framework. Most of the developers I saw used two models namely Cart and Cart Items for creating cart which is as follows:
class Cart(models.Model):
owner = models.OneToOneField(User,
related_name="cart",
on_delete=models.CASCADE,
null=True,
blank=True)
number_of_items = models.PositiveIntegerField(default=0)
total = models.DecimalField(default=0.00,
max_digits=5,
decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"User: {self.owner}, items in cart {self.number_of_items}"
class CartItem(models.Model):
cart = models.ForeignKey(Cart,
on_delete=models.CASCADE)
item = models.ForeignKey(Product,
on_delete=models.CASCADE)
quantity = models.IntegerField()
I am confused as to why one has to create two models. What is the actual use for it? And isnt the item should be many to many fields instead of the foreign key because we are supposed to add multiple products on the cart.
Also, why is there number_of_items and also quantity at same time? What is the difference??
My proposed model:
class Cart(models.Model):
owner = models.OneToOneField(User,related_name="cart",
on_delete=models.CASCADE,
null=True,
blank=True)
item = models.ManytoManyField(Product,blank =True, null =True)
number_of_items = models.PositiveIntegerField(default=0)
total = models.DecimalField(default=0.00,
max_digits=5,
decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
#Saroj Paudel - This is what I had used for my Cart Model in my e-commerce project. I had one model for the cart. That is the cartitem that had a reference to the product_id, user_id, quantity(number of items in the cart), and the date_added.
1 Product can belong to 1 or many cartitem and 1 cartitem can have 1 or many products. So, essentially it's an M2M but I am opting for 1 to Many as I don't see any harm other than the fact that my product_id might be repeating many items for different users but I am ok with that repetition.
class CartItem(TimeStampedModel):
date_added = models.DateTimeField(auto_now_add=True)
quantity = models.IntegerField(default=1)
product = models.ForeignKey(Product, unique=False, on_delete=models.PROTECT)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)

django charge users based on how many counties they want to access

I'm building a web app,
basically I currently have 3 models ,
1- State: which represents all US states
2- County: which represents all counties with foreign key of state
3- Home: which represents all homes with foreign key of County
the app will show homes,
but users needs to subscribe for certain counties (the counties prices can vary)
the goal is : when users subscribe to certain counties they can see the related "Homes" to these counties
I'm not sure how should I represent these relations between users, subscriptions and how to connect it to County model I have.
and how to make a view for the user to add new counties.
Thank you.
Update (My models):
class State(models.Model):
state_name = models.CharField(max_length=50)
def __str__(self):
return self.state_name
class County(models.Model):
county_name = models.CharField(max_length=50)
state = models.ForeignKey(State, on_delete=models.CASCADE)
def __str__(self):
return self.county_name
class Meta:
unique_together = ("county_name", "state")
verbose_name_plural = 'Counties'
class Home(models.Model):
owner_name = models.CharField(max_length=100, null=True, blank=True)
street_address = models.CharField(max_length=100, null=True, blank=True)
city = models.CharField(max_length=50, null=True, blank=True)
county = models.ForeignKey(County, on_delete=models.CASCADE)
postal_code = models.CharField(max_length=50, null=True, blank=True)
price = models.CharField(max_length=50, null=True, blank=True)
sqft = models.CharField(max_length=50, null=True, blank=True)
home_type = models.CharField(max_length=100, null=True, blank=True)
geom = models.PointField()
added = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return '{}, {}, {}'.format(self.street_address, self.city, self.county.state.state_name)
class Meta:
verbose_name = 'Home'
verbose_name_plural = 'Homes'
#property
def state_county(self):
return f'{self.county.county_name}_{self.state}'
#property
def state(self):
return self.county.state.state_name
Here is a basic idea, you should evaluate from this point.
class State(models.Model)
name = models.CharField(max_length=100)
class County(models.Model)
state = models.ForeignKey(State)
name = models.CharField(max_length=100)
class Home(models.Model)
county= models.ForeignKey(County)
name = models.CharField(max_length=100)
class Subscription(models.Model)
county = models.ForeignKey(County)
user = models.ForeignKey(User)
Basically, you can then charge your user per County (observe that one can have more than one County subscription)
Another aproach would be to use a hierarchy to have State>County>Home, on a MPTT, but maybe its not what you want.
One way would be to add ManyToMany County relationship field in the Subscriptions model and then you would query subscribed county and filter Home.
Something in the sense of:
class County(models.Model):
county = models.CharField(max_length=255)
class Home(models.Model):
county = models.ForeignKey(County, on_delete=models.PROTECT)
class Subscription(models.Model):
user = models.ForeingKey(User, on_delete=models.PROTECT)
county = models.ManyToMany(County)
Then you'd query subscriptions and filter based on that.
subscriptions = Subscription.objects.filter(user=request.user).values_list('county', flat=True)
homes = Home.objects.filter(county_id__in=subscriptions)
You could further improved that with models Manager on Subscription to avoid filtering user every time with something like:
class SubscriptionManager(models.Manager):
def user_subscriptions(self, user):
return super().get_queryset().filter(user=user)
class Subscription(models.Model):
user = models.ForeingKey(User, on_delete=models.PROTECT)
county = models.ManyToMany(County)
objects = SubscriptionManager()
and then filter either with:
subscriptions = Subscription.objects.filter(user=request.user).values_list('county', flat=True)
or
subscriptions = Subscription.objects.user_subscriptions(request.user).values_list('county', flat=True)

How do I get related Model field in Django using the Django Admin

I think that my problem here is Django specific and not necessarily a reflection on
my understanding of relational databases (hopefully).
I have a Django app that stores information on Contacts.
With that one table things seemed to work fine. When I wanted to categorize
the type of relationship - is this a professional relationship, family, friends, etc.
That's when things didn't show up like I wanted. I finally got the migration to work
with the new table.
I'm using python 3 with the latest version of django. I have a mysql
database. I want a one to many relationship, where one contact can
be characterized by many categories. When I work with the django admin
and try to enter a contact, I'm not seeing a field for entering relationship categories.
So, here is my models.py for the contacts app.
from django.db import models
class Resource(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
organization = models.CharField(max_length=60, null=True, blank=True)
street_line1 = models.CharField("Street Line 1", max_length=50, null=True, blank=True)
street_line2 = models.CharField("Street Line 2", max_length=50, null=True, blank=True)
city = models.CharField(max_length=40, null=True, blank=True)
state = models.CharField(max_length=40, null=True, blank=True)
zipcode = models.CharField(max_length=20, blank=True, null=True)
phone1 = models.CharField(max_length=20, null=True, blank=True)
phone2 = models.CharField(max_length=20, null=True, blank=True)
email = models.EmailField(max_length=60, null=True, blank=True)
website = models.URLField(max_length=90, null=True, blank=True)
def __str__(self):
return "%s %s \t%s" % (self.first_name, self.last_name, self.organization)
class Meta:
ordering = ('last_name',)
class Relationship(models.Model):
category = models.CharField(max_length=120)
resource = models.ForeignKey(Resource, related_name='category')
def __str__(self):
return self.category
class Meta:
ordering = ('category',)
Thanks in advance for any help,
Bruce