How would I do this query in Django? - django

So let's say I have three models: User, CarBrand, CarModel, CarCharacteristics. The CarCharacteristics model describes how a user rates the characteristics of a car. So there can be many CarCharacteristics objects for a user, and a user can have many CarCharacteristics.
This is what my models look like:
class User(models.Model):
id = models.AutoField(primary_key=True)
class CarBrand(models.Model):
idcar_brand = models.AutoField(primary_key=True)
class CarModel(models.Model):
idcar_model = models.AutoField(primary_key=True)
car_brand = models.ForeignKey(CarBrand, null=True, on_delete=models.SET_NULL)
class CarCharacteristics(models.Model):
idcar_characteristics = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.PROTECT)
car_model = models.ForeignKey(CarModel, on_delete=models.PROTECT)
What I would like to do is to get all CarBrand objects where a User has a CarCharacteristics. This is what am I doing right now:
car_chars = CarCharacteristics.objects.filter(user=user_id)
car_brands_ids = []
for car_char in car_chars:
brand_id = car_char.car_model.car_brand.idcar_brand
if brand_id not in car_brands_ids:
car_brands_ids.append(brand_id)
brands = CarBrand.objects.filter(idcar_brand__in=brand_ids)
Is there a simpler way of doing this? And how do I get all the CarModels where there exists a CarCharacteristics?

Try this:
CarBrand.objects.exclude(carmodel__carcharacteristics__user=None).distinct()

I think I figured it out. I think this works:
user_id = request.user.pk
brands = CarBrand.objects.exclude(~Q(carmodel__carcharacteristics__user=user_id))
EDIT
Is what I have above also equivalent to this:
user_id = request.user.pk
car_models = CarModel.objects.filter(carcharacteristics__user=user_id)
brands = CarBrand.objects.filter(carmodel__in=car_models).distinct()

CarBrand.objects.filter(carmodel__carcharacteristics__user=request.user).distinct()

Related

how to use filter in query twice in django

I am trying to filter some data using this query,
get_members = PaymentDetails.objects.filter(participants_name=Participants.objects.filter(participants_name=Profile.objects.get(user=request.user)))
but I am getting this error The QuerySet value for an exact lookup must be limited to one result using slicing. My models looks like this
class Committee(models.Model):
committee_creator = models.ForeignKey(Profile, on_delete=models.CASCADE)
committee_name = models.CharField(max_length=100)
class Participants(models.Model):
participants_name = models.ForeignKey(Profile, on_delete=models.CASCADE)
participants_committee_name = models.ForeignKey(Committee, on_delete=models.CASCADE)
class PaymentDetails(models.Model):
participants_name = models.ForeignKey(Participants, on_delete=models.CASCADE)
participants_paid_status = models.BooleanField(default=False)
participants_amount_paid = models.IntegerField()
try this i will assume that you have OneToOne Relationship between User and Profile.
get_members = PaymentDetails.objects.filter(participants_name__participants_name_id = request.user.profile.pk)

Django - counting foreign keys in models

I know how I can count things with annotate (in my view) but I would like to do the same in model (so it would be more reusable).
For example (lets take an example from django documentation) I have this model:
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
class Publisher(models.Model):
name = models.CharField(max_length=300)
class Book(models.Model):
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
rating = models.FloatField()
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
pubdate = models.DateField()
class Store(models.Model):
name = models.CharField(max_length=300)
books = models.ManyToManyField(Book)
and I can use in view this:
from django.db.models import Count
pubs = Publisher.objects.annotate(num_books=Count('book'))
But how I do that in model?
I know this question is pretty basic (probably) but I'm pretty much beginner in django.
Thanks for answers!
You can use custom managers:
Django docs: Managers
class BookManager(models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(num_books=Count('book'))
class Publisher(models.Model):
name = models.CharField(max_length=300)
books = BookManager()
Now you can call it like this:
pubs = Publisher.books.all()
And you will have num_books with your objects.
You can use classmethod for this.
class Publisher(models.Model):
...
#classmethod
def get_book_count(cls):
return cls.objects.annotate(num_books=Count('book'))
You can call this method as
pubs = Publisher.get_book_count()
Edit - Also check out the answer by #Navid2zp which might be a better solution for you.

Serialization and permissions in Django Rest Framework

I'm new in Django and DRF, have questions with serialization.
I have models:
class Commodity(models.Model):
shop = models.ForeignKey(Company, on_delete=models.PROTECT)
price = models.DecimalField(max_digits=10, decimal_places=2)
active = models.BooleanField(default=False)
class Clother(models.Model):
commodity = models.ForeignKey(Commodity, related_name='commodity', on_delete=models.CASCADE)
color = models.ManyToManyField(Color, related_name='color')
material = models.ManyToManyField(Material, related_name='material')
gender = models.CharField(max_length=2, choices=GENDER_CHOICES, default=UNISEX)
class Outwear(models.Model):
clother = models.ForeignKey(Clother, on_delete=models.CASCADE)
name = models.CharField(max_length=30, blank=True)
outwear_type = models.ForeignKey(OutwearType, on_delete=models.CASCADE)
size = models.ManyToManyField(ClotherSize)
So I suppose to make a Serializer like that:
class OutwearSerializer(serializers.ModelSerializer):
commodity = CommoditySerializer(many=False, read_only=False)
clother = ClotherSerializer(many=False, read_only=False)
class Meta:
model = Outwear
fields = ('commodity', 'clother', 'name', 'outwear_type', 'size')
As I understand that read_only fields let me add or edit Outwear object further, but I supposed to have 2 types of permition:
All users can see only active Commodity objects.
Only Companies can create and edit their own objects.
Do I need to make 2 Serializer Models for read_only=True/False?
What is the best practice and where can I find good examples of something familiar?
I call User - unauthorized User. Company is authorized User.
Thanks!
For your first question:
class CommoditySerializer(ModelSerializer):
class Meta:
model = Commodity
fields = (shop, price)
Class CommodityActiveAPIView(generics.ListAPIView):
serializer_class = serializers.CommoditySerializer
queryset = Commodity.objects.filter(active=True)
second question is ambiguous. first define user role please

related objects queries django rest framework

I have the following models
class STUser(AbstractBaseUser):
email = models.EmailField(unique=True)
name = models.CharField(max_length=255)
companyname = models.CharField(max_length=200, blank=True, null=True)
...
class VenuePermissions(models.Model):
user = models.ForeignKey(STUser, on_delete=models.CASCADE)
venue = models.ForeignKey(Venue, on_delete=models.CASCADE)
signupvaildatestring = models.CharField(max_length=200, blank=True, null=True)
...
I want to grab all the STUser objects and grab all their permissions.
So what I would like is to grab all the VenuePermissions objects. And grab the user and venue object of each venuePermission
Two ways I can do this. use the VenuePermissions_set attribute on STUser but then how do I grab the venue when its just going to be a pk value?
Or focus on the VenuePermissions objects and grab the user and venue from the pk values but how?
I remember nested queries, and I kinda did one in my browse code.
here is an example:
rooms = Room.objects.filter(venue=OuterRef('pk'), sixtyroundseatingoption= True)
venuelist = venuelist.annotate(sixtyrounds=Exists(rooms))
venuelist = venuelist.filter(Q(sixtyrounds = True) | Q(fullbuyoutsixtyroundseatingoption = True))
I've done the set objects in a serializer before
Example serializer:
class RoomAndImageSerializer(serializers.ModelSerializer):
roomimage_set = RoomImageSerializer(many=True, read_only=True)
class Meta:
model = Room
fields = ('pk','name')
any help with this query would be appreciated!
So this is what I am currently trying, I will post an answer if this works:
class VenueUserList(ListAPIView):
serializer_class = VenueUserListSerializer
queryset = VenuePermissions.objects.select_related('user').select_related('venue').filter(signupvaildatestring=None)
class VenueUserListSerializer(serializers.ModelSerializer):
user = UserSerializer()
venue = VenueSerializer()
class Meta:
model = VenuePermissions
fields = ('user', 'venue', 'isvenueviewer', 'isvenueeventplanner', 'isvenueadministrator')
Here is the answer. However I still need to group venues by user. Working on that.
class VenueUserList(ListAPIView):
serializer_class = VenueUserListSerializer
queryset = VenuePermissions.objects.select_related('user').select_related('venue').filter(signupvaildatestring=None)
class VenueUserListSerializer(serializers.ModelSerializer):
user = UserSerializer()
venue = VenueSerializer()
class Meta:
model = VenuePermissions
fields = ('user', 'venue', 'isvenueviewer', 'isvenueeventplanner', 'isvenueadministrator')

Posting in several tastypie resources simultaneously

Here's what I'm trying to do :
The user creates an Event in my application. Here's the model :
class Event(models.Model):
name = models.CharField(max_length=40)
organizer = models.ForeignKey(UserProfile)
description = models.TextField(null=True)
place = models.TextField(null=True)
confirmed = models.BigIntegerField(null=True)
organizer_part = models.BooleanField(default=True)
slug = models.SlugField()
Right after that, it posts the different people invited to this event, and the different dates that the user chose. Here are the models :
class EventDate(models.Model):
"""Correspondances date-event"""
event = models.ForeignKey(Event)
date = models.BigIntegerField()
class EventPeople(models.Model):
"""Correspondances personne-event"""
event = models.ForeignKey(Event)
phone_number = models.PositiveIntegerField()
name = models.CharField(max_length=32)
answer = models.BooleanField()
participation = models.NullBooleanField()
I'd like to fill those three models in only one request. So far I have to make three requests. I can't see how I could possibly do it.
Any idea would be highly appreciated.
Resource that should work with your models is:
class EventResource(ModelResource):
event_dates = fields.ToManyField(EventDateResource, 'event_dates')
event_peoples = field.ToManyField(EventPeopleResource, 'event_peoples')
class Meta:
queryset = Event.objects.all()
Also you have to create simple EventDateResource and EventPeopleResource.
One one more change in yout models, you need to add related_names:
class EventDate(models.Model):
"""Correspondances date-event"""
event = models.ForeignKey(Event, related_name='event_dates')
date = models.BigIntegerField()
class EventPeople(models.Model):
"""Correspondances personne-event"""
event = models.ForeignKey(Event, related_name='event_peoples')
phone_number = models.PositiveIntegerField()
name = models.CharField(max_length=32)
answer = models.BooleanField()
participation = models.NullBooleanField()