DRF get 2 row with bigger count than other ones - python

i have some row in table i want to get only 2 record that have bigger count value that others . for now according the my picture count 50 and 80 shoud be return.
i should have a list of product_ids (only 2 record)
that have count more that others.. so i should try values_list
i know this is wrong how can i fix it?
prod_ids = ProductViewCount.objects.all().aggregate(Max('count')).values_list('product', flat=True)
this is my full code :
class ViewTopLiked(APIView):
def get(self, request):
prod_ids = ProductViewCount.objects.all().aggregate(Max('count')).values_list('product', flat=True)
obj = Product.objects.filter(product_id__in=prod_ids).order_by('-created_date')
serializer = ProductSerializer(instance=obj, many=True, context={'request': request})
return Response(serializer.data)
productViewcount model:
model:
class ProductViewCount(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, to_field='product_id',
related_name='count')
count = models.IntegerField(null=True, blank=True, default=0)
product model:
class Product(models.Model):
PRO = 'P'
INTER = 'I'
BEGINER = 'B'
ALL = 'A'
TYPE_CHOICE = ((PRO, 'P'), (INTER, 'I'), (BEGINER, 'B'), (ALL, 'A'))
product_id = models.AutoField(primary_key=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True)
title = models.CharField(max_length=200)
video_length = models.IntegerField(null=True, blank=True)
mini_description = models.CharField(max_length=1000, null=True, blank=True)
full_description = models.TextField(null=True, blank=True)
price = models.IntegerField(null=True, blank=True)
free = models.BooleanField(default=False)
video_level = models.CharField(max_length=20, choices=TYPE_CHOICE, default=ALL)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
publish = models.BooleanField(default=False)
draft = models.BooleanField(default=False)
slug = models.SlugField(allow_unicode=True, null=True, blank=True)
image = models.FileField(upload_to=upload_to_custom_p, null=True, blank=True)
lecture = models.IntegerField(null=True, blank=True)
def __str__(self):
return self.title
#property
def owner(self):
return self.author

For ordering you can use count related_name in product queryset, to get only first two elements use slicing [:2]:
obj = Product.objects.order_by('-count__count')[:2]
serializer = ProductSerializer(instance=obj, many=True, context={'request': request})
return Response(serializer.data)

Related

Cannot assign "OrderItem.product" must be a "Product" instance

I am trying to create a "create order" endpoint, i keep getting
Cannot assign "<django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x7f50dad00f70>": "OrderItem.product" must be a "Product" instance.
heres my models
def product_images(instance, filename):
return f"product/{instance.product_name}/{filename}"
class Product(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=200, null=True, blank=True)
description = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
image = models.ImageField(
storage=MediaRootS3BotoStorage(),
upload_to="product_images",
null=True,
blank=True,
)
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.name
def save(self, *args, **kw):
self.slug = slugify(f"{self.name}")
super(Product, self).save(*args, **kw)
# Ecommerce Models Store and Product
def store_images(instance, filename):
return f"{instance.store_name}/{filename}"
class Store(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=200, null=True, blank=True)
description = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
image = models.ImageField(upload_to="store_images", null=True, blank=True)
delivery_fee = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
address = models.CharField(max_length=100, null=True, blank=True)
phone_number = models.CharField(max_length=100, null=True, blank=True)
products = models.ManyToManyField("Product", through="StoresProduct")
def __str__(self):
return self.name
def save(self, *args, **kw):
self.slug = slugify(f"{self.name}")
super(Store, self).save(*args, **kw)
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ManyToManyField("Product", through="StoresProduct")
quantity = models.IntegerField(default=1)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user.email
def get_total(self):
return self.product.price * self.quantity
class StoresProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
seller = models.ForeignKey(Store, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
quantity = models.IntegerField(blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
is_active = models.BooleanField(default=True)
cart = models.ForeignKey(
Cart,
on_delete=models.CASCADE,
related_name="products",
default=None,
null=True,
blank=True,
)
product = models.ForeignKey(
Product,
on_delete=models.CASCADE,
related_name="+",
default=None,
null=True,
blank=True,
)
def __str__(self):
return f"{self.product.name} - {self.seller.name}"
class Meta:
unique_together = ["product", "seller"]
OrderStatus = (
("Pending", "Pending"),
("Delivered", "Delivered"),
("Cancelled", "Cancelled"),
("Processing", "Processing"),
)
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=100, choices=OrderStatus, default="Pending")
delivery_fee = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
total = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
order_id = models.CharField(max_length=100, null=True, blank=True)
order_items = models.ManyToManyField("Product", through="OrderItem")
store = models.ForeignKey(Store, on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return self.user.email + " - " + self.order_id
def get_random_order_id(self):
order_id = str(uuid.uuid4()).replace("-", "").upper()[:10]
return order_id
# create order id with random string
def save(self, *args, **kwargs):
if not self.order_id:
self.order_id = self.get_random_order_id()
super(Order, self).save(*args, **kwargs)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
order = models.ForeignKey(Order, on_delete=models.CASCADE)
store = models.ForeignKey(Store, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.product.name
and my views.py
#create order with orderitems
#swagger_auto_schema(method="post", request_body=OrderSerializer)
#api_view(["POST"])
#permission_classes((permissions.AllowAny,))
#authentication_classes([TokenAuthentication])
def create_order(request):
"""
Creates an order then creates an orderitem
"""
user = request.user
serializer = OrderSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=user)
order_id = serializer.data["id"]
order = Order.objects.get(pk=order_id)
cart = user.cart_set.all()
for item in cart:
OrderItem.objects.create(
order=order,
product=item.product,
quantity=item.quantity,
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#swagger_auto_schema(method="post", request_body=AddToCartSerializer)
#api_view(["POST"])
#permission_classes((permissions.AllowAny,))
#authentication_classes([TokenAuthentication])
def add_to_cart(request):
"""
Adds a product to cart
"""
user = request.user
serializer = AddToCartSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Basically, users should be able to add products from various stores to their cart and when they are done they should be able to order.
I can't seem to figure out what i am doing wrongly, if there's a better way to do this do tell.I'm guessing my approach is problematic

Cannot assign "'Sample Category'": "Product.category" must be a "Category" instance

While creating new products I'm getting such kind of error. Can someone help me?
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name_geo = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True, default='/placeholder.png')
brand = models.CharField(max_length=200, null=True, blank=True)
category = models.ForeignKey(Category, null=False, default=0, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
def __str__(self):
return self.name_geo
class Category(models.Model):
_id = models.AutoField(primary_key=True, editable=False)
name = models.CharField(max_length=200, null=True, blank=True)
createdAt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
#api_view(['POST'])
def createProduct(request):
user = request.user
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category="Sample Category",
price=0,
brand='Sample Brand',
countInStock=0,
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
Without separating category class in models.py everything works fine. I mean If i didn't use ForeignKey in Products class for category
It just has to be a Category Instance/Object
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category=Category.objects.get_or_create(name="Sample Category"),
price=0,
brand='Sample Brand',
countInStock=0,
)
Notes:
You could just do a .get() or a .filter().first() if you don't want to create
If you use a form, you can get away with just the Category's PK/_id in the POST
this type of thing: f = form(request.POST) f.is_valid() f.save()
At the end that field will hold the PK/_id/Row# of the Category Obj

Single object from queryset

I need help with a little issue I am having with my project. I have a model where I have a foreign key with many entries and I would like to take just one item of these entries.
In fact, my problem is something like that:
I need to obtain the single mission id, in order to have other functions.
The code is working fine, my problem is that I don't know the righe order to obtain the mission item from this queryset:
models.py
from django.db import models
from flight.models import LogEntry
from user.models import Instructor, Student
# Create your models here.
TRAINING_COURSE_CHOICES = (
('PPL', 'PPL'),
('CPL', 'CPL'),
('IR', 'IR'),
('ATPL', 'ATPL'),
)
class TrainingCourse(models.Model):
name = models.CharField(max_length=20, choices=TRAINING_COURSE_CHOICES)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class StudentTrainingCourse(models.Model):
training_course = models.ForeignKey(
TrainingCourse, on_delete=models.PROTECT)
student = models.ForeignKey(Student, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.student.first_name + ' ' + self.student.last_name + ' ' + self.training_course.name
class Mission(models.Model):
name = models.CharField(max_length=200)
training_course = models.ForeignKey(
TrainingCourse, on_delete=models.CASCADE)
note = models.TextField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.training_course.name + ' ' + self.name
class StudentMission(models.Model):
mission = models.ForeignKey(Mission, on_delete=models.PROTECT)
student_training_course = models.ForeignKey(
StudentTrainingCourse, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['mission__name']
def __str__(self):
return self.mission.name
class LearningObjective(models.Model):
name = models.CharField(max_length=300)
mission = models.ForeignKey(Mission, on_delete=models.DO_NOTHING)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
GRADING_VALUE = (
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5'),
)
class MissionEntry(models.Model):
student = models.ForeignKey(
Student, on_delete=models.DO_NOTHING, blank=True, null=True)
mission = models.ForeignKey(
Mission, on_delete=models.DO_NOTHING, null=True, blank=True)
log_entry = models.ForeignKey(
LogEntry, on_delete=models.DO_NOTHING, blank=True, null=True)
learning_objective = models.ForeignKey(
LearningObjective, on_delete=models.DO_NOTHING, blank=True, null=True)
grade = models.CharField(
max_length=10, choices=GRADING_VALUE, blank=True, null=True)
note = models.TextField(blank=True, null=True)
debriefing = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.mission) + ' ' + str(self.log_entry)
class Meta:
verbose_name_plural = 'Mission Entries'
class MissionEntryStatus(models.Model):
student_mission = models.ForeignKey(
StudentMission, on_delete=models.PROTECT, null=True, blank=True)
mission = models.ForeignKey(
Mission, on_delete=models.PROTECT, null=True, blank=True)
student = models.ForeignKey(Student, on_delete=models.PROTECT)
is_completed = models.BooleanField(default=False)
is_failed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
views.py
def student_mission_list(request, pk):
student = Student.objects.get(id=pk)
student_training_course = StudentTrainingCourse.objects.get(
student_id=student)
missions = StudentMission.objects.filter(
student_training_course_id=student_training_course)
context = {
'student': student,
'missions': missions,
}
return render(request, 'mission/student_mission_list.html', context)
In fact, in student_mission_list I need to retrieve the mission_id!!! The problem is that, if I try to retrieve that from StudentTraining or MissionEntryStatus model, I have multiple missions; but i'd like to have just the corresponding mission_id, but I am not able to find a way.
Is there any suggestion? Probably I have to modify the database, but I don't know where.
Thank you very much to all of you for your help
The way you have it set up now, a StudentTrainingCourse can have only ONE student but, because a ForeignKey is a ManyToOne relationship, MANY students can have that same StudentTrainingCourse. What I think you want is for a Student to have ONE StudentTrainingCourse, but a StudentTrainingCourse to have MANY Students. My guess is what you need is:
class Student(models.Model):
...
training_course = models.ForeignKey(StudentTrainingCourse, on_delete=models.CASCADE)
...
Then you can get the particular mission id like:
def student_mission_list(request, pk):
student = Student.objects.get(id=pk)
training_course = student.training_course
mission = Mission.objects.get(training_course=training_course)
# If you just want the mission ID:
mission_id = mission.pk
missions = StudentMission.objects.filter(
student_training_course_id=student_training_course)
context = {
'student': student,
'missions': missions,
}
return render(request, 'mission/student_mission_list.html', context)

How to fetch data from other table django rest framework

I have a cartmodel, cartitem and offlinecheckout model. I want to display cartitem instead of cartmodel id, I want to display all the cartitem data which have cart_id = offlinecheckout cart_id. But I got this response.
I tried a lot but didn't get. Anybody will please help me.
views.py
class GetAPI(APIView):
def get(self, request, *args, **kwargs):
serializer = OfflineSerializer()
return Response(serializer.data)
models.py
class OfflineCheckOut(models.Model):
billing_name = models.CharField(max_length=254)
billing_phone_no = models.CharField(max_length=15)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
cart = models.ForeignKey('cart.CartModel', on_delete=models.CASCADE)
cartitem = models.ManyToManyField(CartItem, blank=True)
# time_slot = models.ForeignKey('category.TimeSlot', on_delete=models.CASCADE)
address = models.ForeignKey('cart.CustomerAddress', on_delete=models.CASCADE)
status_choice = [
('0', 'Offline'),
('1', 'Online')
]
status = models.CharField(max_length=3, choices=status_choice, default=0)
# date = models.DateField()
date = models.DateField()
time_slot = models.ForeignKey('category.TimeSlot', on_delete=models.SET_NULL, null=True, blank=True)
order_id = models.CharField(max_length=254, blank=True)
# date = models.DateField()
razorpay_payment_id =models.CharField(max_length=254, blank=True)
razorpay_signature = models.CharField(max_length=254, blank=True)
paid = models.BooleanField(default=False)
service = models.ForeignKey('service.ServiceProvider', on_delete=models.SET_NULL, null=True, blank=True)
class CartModel(models.Model):
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
status_choice = [
('1', 'open'),
('2', 'closed')
]
status = models.CharField(max_length=2, choices=status_choice, default=1)
validated = models.BooleanField(default=False)
def __str__(self):
return self.user.username
#property
def total_price(self):
return self.cartitem_set.aggregate(
total_price=Sum(F('quantity') * F('price'))
)['total_price'] or Decimal('0')
class CartItem(models.Model):
cart = models.ForeignKey('CartModel', on_delete=models.CASCADE)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
service = models.ForeignKey('accounts.SubCategory', on_delete=models.CASCADE)
defects = models.ForeignKey('category.Defects', on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
price = models.IntegerField()
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now_add=True)
order_placed = models.BooleanField(default=False)
serializers.py
class OfflineSerializer(serializers.ModelSerializer):
def total(self, obj):
return obj.total
total = serializers.IntegerField(read_only=True)
cartitems = CartItemSerializer( read_only=True, many=True)
class Meta:
model = OfflineCheckOut
fields = ['user', 'billing_name','billing_phone_no','cartitem', 'cartitems','cart', 'date', 'time_slot', 'address', 'total']
extra_fields = ['total', 'cartitems']
You have to put them in a serializer for CartModel. Then OfflineSerializer will use that for cart field.
class CartModelSerializer(serializers.ModelSerializer):
cartitem_set = CartItemSerializer(read_only=True, many=True)
class Meta:
model = CartModel
fields = [
"cartitems_set",
# other fields here
]
class OfflineSerializer(serializers.ModelSerializer):
def total(self, obj):
return obj.total
total = serializers.IntegerField(read_only=True)
cart = CartModelSerializer(read_only=True)
class Meta:
model = OfflineCheckOut
fields = ['user', 'billing_name','billing_phone_no','cartitem', 'cartitems','cart', 'date', 'time_slot', 'address', 'total']
extra_fields = ['total', 'cartitems']
EDIT: Changed the related name serializer from cartlineitems_set to cartlineitem_set

Django: get the max count of a foreign key based on other foreign key

I have this Model:
class Complaint(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
name = models.CharField(max_length=255, unique=True)
definition = models.TextField(blank=False, default="")
is_violent = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Meta:
ordering = ['name']
def get_absolute_url(self):
return reverse('complaint-details', kwargs={'pk': self.pk})
class Service(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
name = models.CharField(max_length=255, unique=True)
definition = models.TextField(blank=True, default="")
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('service-details', kwargs={'pk': self.pk})
class Location(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
location_name = models.CharField(max_length=255, unique=True)
loc_lat = models.DecimalField(max_digits=9, decimal_places=6)
loc_long = models.DecimalField(max_digits=9, decimal_places=6)
pop = models.PositiveIntegerField(default=500)
is_AOR = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.location_name
class Blotter(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)#default=timezone.now().date()
date = models.DateField(blank=True)
time = models.TimeField(blank=True)
entry_number = models.CharField(max_length=255, unique=True,validators=[RegexValidator(r'^\d{1,255}$')])
complaints = models.ForeignKey(Complaint, on_delete=models.CASCADE, null=True, blank=True)
service = models.ForeignKey(Service, on_delete=models.CASCADE, null=True, blank=True)
information = models.TextField(blank=False, default="")
location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True)
is_active = models.BooleanField(default=True)
class Meta:
ordering = ("date_created",)
def __str__(self):
return (self.entry_number)
def get_absolute_url(self):
return reverse('details-blotter', kwargs={'pk': self.pk})
And I have this serializer:
class APILocationListSerializer(serializers.Serializer):
address = serializers.CharField()
latitude = serializers.DecimalField(max_digits=9, decimal_places=5)
longitude = serializers.DecimalField(max_digits=9, decimal_places=5)
population= serializers.IntegerField()
crime_count=serializers.IntegerField()
crime_rate=serializers.DecimalField(max_digits=4, decimal_places=3)
is_aor = serializers.BooleanField()
class Meta:
model = Blotter
fields= [
'address',
'latitude',
'longitude',
'population',
'crime_count',
'crime_rate'
'is_aor',
]
def to_representation(self, value):
context = {
value['address']:
{
'coordinates':[value['latitude'],value['longitude']],
'Population': value['population'],
'Crime-Count': value['crime_count'],
'Crime-Rate': value['crime_rate'],
'Area-Of-Responsibility': value['is_aor'],
}
}
return context
And ListApiView:
class APILocationList(generics.ListAPIView):
serializer_class = APILocationListSerializer
def get_queryset(self):
q=Blotter.objects.values('location__location_name').annotate(
address=F('location__location_name'),
latitude=F('location__loc_lat'),
longitude=F('location__loc_long'),
population=F('location__pop'),
crime_count=Count('complaints', filter=Q(complaints__is_active=True) and Q(complaints__isnull=False)),
crime_rate=(Cast(F('crime_count'), FloatField())/Cast(F('population'), FloatField()))*100000,
is_aor=F('location__is_AOR')
)
q1 = q.filter(location__is_AOR=True).order_by('address')
query_search = self.request.GET.get("q")
if query_search:
q1 = q.filter(Q(location__is_AOR=True) and Q(location__location_name__icontains=query_search)).order_by('address')
return q1
I'm new to django and DRF. I want to achieve a result like this in my API Not Achieved
but this is the result that i've achieved so far Achieved
As you can see in the picture, I want to count the crime trend (highest count of a crime and the crime itself) in every location.
My questions are:
Is this even achievable/possible to get these results using just one query?
If yes, how?
If no, is there any other way to achieve these kind of results?
Thank you in advance!

Categories