parsing into queryset for product media - django

I have two different models for my product. One is for product information and the other is product media.
class Products(models.Model):
id=models.AutoField(primary_key=True)
url_slug=models.CharField(max_length=255)
subcategories_id=models.ForeignKey(SubCategories,on_delete=models.CASCADE)
product_name=models.CharField(max_length=255, null=True)
brand=models.CharField(max_length=255)
max_price=models.DecimalField(max_digits=7, decimal_places=2)
discount_price=models.DecimalField(max_digits=7, decimal_places=2)
product_description=models.TextField()
product_long_description=models.TextField()
created_at=models.DateTimeField(auto_now_add=True)
in_stock_total=models.IntegerField(default=1)
is_active=models.IntegerField(default=1)
class ProductMedia(models.Model):
id=models.AutoField(primary_key=True)
product_id=models.ForeignKey(Products,on_delete=models.CASCADE)
media_type_choice=((1,"Image"),(2,"Video"))
media_type=models.CharField(max_length=255)
media_content=models.FileField(upload_to="media")
created_at=models.DateTimeField(auto_now_add=True)
is_active=models.IntegerField(default=1)
Now I have two user module one of which needs no authentication and the other is for authenticated user. For unauthenticated user I have my items dictionary as following.
items=[]
item = {
'product' :{
'id': product.id,
'media_content': media.media_content,
'product_name': product.product_name,
'discount_price': product.discount_price,
},
'quantity': cart[i]["quantity"],
'get_total': total,
}
items.append(item)
for the authenticated user my items is a query set:
if request.user.is_authenticated:
customer_user = CustomerUser.objects.get(user = request.user)
order, created = Order.objects.get_or_create(customer_user, complete=False)
items = order.orderitem_set.all()
cartItems = order.get_cart_items
Now when I want to call the media of the product in html for unauthenticated user I call
{{item.product.media_content}}
to have a visible product image in cart, it's all okay.
But this doesn't work for authenticated user. I don't want to change html command. How can I add the media content in the above items queryset?

Related

how to create a SimpleListFilter in django

I don't succeed to write a query filter.
I have 3 models: Patient, Prescription and User
I write you only what is relevant for my question
Patient:
class Patient(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Prescription:
class Prescription(models.Model):
user = models.ForeignKey(
User,
null=True,
blank=False,
on_delete=models.DO_NOTHING
)
file_extention = models.CharField(
'file extention',
max_length=8,
null=True,
blank=True,
)
So the relation between both of models (Patient and Prescription) are through User.
in the PatientAdmin, I want to filter on the file_extension according pdf or jpg of the prescription uploaded.
I created a SimpleListFilter but impossible to find the right query.
class PrescriptionFileExtensionFilter(SimpleListFilter):
"""This filter is being used in django admin panel in
patient model."""
title = 'Prescription File Ext'
parameter_name = 'file_extention'
def lookups(self, request, model_admin):
return (
('pdf', 'PDF'),
('jpg', 'JPG'),
)
def queryset(self, request, queryset):
for user in queryset:
if self.value() == 'pdf':
return queryset.filter(user=user.user).filter
(prescription__file_extention="pdf")
if self.value() == 'jpg':
return queryset.filter(user=user.user).filter
(prescription__file_extention="jpg")
That's not working...
Do I need the for user in queryset:
need What could be the query to bring me all the users with a prescription with file_extension = "pdf" (or "jpg")
You are trying to get a key from the prescription object in print(mydict['file_extention']) which I believe is causing the issue - you would instead access that property via mydict.file_extention - though I should add that mydict is not an accurate variable name for a model object as it isn't a dictionary. I don't think that for loop is actually doing anything other than printing a particular value so it can be removed altogether.
As an aside, you have two filters on your queryset, this can just be expressed as a single filter, separate by a comma, e.g.
return queryset.filter(user=user.user, prescription__file_extention="pdf")
You are also calling user.user, presumably you just want to get the user model which is kept in request.user - is that what your for loop was trying to do?
Edit
If you want to get all of the users but just filtered by JPG or PDF then you need to remove two things:
The for-loop of for user in queryset
The filter of .filter(user=user.user)
The for loop is unnecessary in the queryset function and the filter is just getting a single user, but you want to get all of them - correct?

Serializing a Profile with associated Products with Django Rest Framework

I'm building a sample iOS app where users would buy and sell products, and I'm trying to design a page where the upper section will have basic profile details and the lower section will have the products that they're currently selling, something like this:
Sample Frontend Image
So I'm trying to create a Serializer / API endpoint which would give me the Profile, with the products that they are currently selling.
My Product model has a ForeignKey relationship to User:
class Product(models.Model):
def __str__(self):
return self.name
name = models.CharField(max_length=200)
seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name="product_seller")
category = models.ForeignKey("Category", on_delete=models.CASCADE)
(...)
And I have a Profile model which has a one-to-one relationship with the default Django user. As this view will be based on Profiles, I think it would make more sense to serialize the User or the Profile model and get the products where they are the "seller".
So the JSON response that I want is something like this:
{
"id": 1,
"username": “some username”,
"profile_image": "http://192.168.1.101:8000/images/profile_pictures/732339C5-E419-4A3D-9022-A314416F5F02.png",
"description": “Some description for this particular profile.”
“products”: [
{ “id”: 1,
“image” = http://192.168.1.101:8000/images/abc.jpg,
},
{ “id”: 2,
“image” = http://192.168.1.101:8000/images/abc.jpg,
},
{ “id”: 3,
“image” = http://192.168.1.101:8000/images/abc.jpg,
}
]
}
What would be the best way to approach this using django-rest-framework?
I've tried using Nested Serializers, but my User or Profile models don't explicitly have a relationship to Product, so they haven't worked so far:
class SellerProductsSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ["id", "images"]
class SellerSerializer(serializers.ModelSerializer):
products = SellerProductsSerializer(read_only=True, many=True)
profile_image = serializers.CharField(source="profile.profile_image")
description = serializers.CharField(source="profile.description")
class Meta:
model = User
fields = ["id", "username", "profile_image", "description", "products"]
I've also tried using the SerializerMethodField, which I think would work in this case, but I haven't quite figured out how I would filter the products where the particular user is the seller. The endpoints look like this:
.../application/api/seller/1
If I could access the "1" - which is the user id, I could filter with something like:
class SellerSerializer(serializers.ModelSerializer):
products = serializers.SerializerMethodField()
profile_image = serializers.CharField(source="profile.profile_image")
description = serializers.CharField(source="profile.description")
class Meta:
model = User
fields = ["id", "username", "profile_image", "description", "products"]
def get_products(self):
# get the id from the request / or the url
# filter the Product model.
I'm used to doing filtering on the viewsets, but not on the serializer itself. I think filtering on the viewset is not possible in this case, as I'm working with two different models and the one that I'm trying to filter is not the main model for the serializer.
I feel like there has to be a simple way to do this but I have been stuck for quite some time. Any help would be greatly appreciated.
You can retrieve a user with pk in the url,and return a response with that particular user, and the result of the following query:
Product.objects.filter(seller_id=pk)
And add the results to a list,and return a response that looks like this:
Response({
"Seller":Fetched User,
"Their Products":list of products
})

Shoping cart M2M model with items count in Django

I'm trying to create shopping cart system for one of mine pet project.
I have Profile model that is an extension for built-in User model. My Profile model has shopping_cart field which is M2M relationship to Clothing model from another app, which represents my product. In code, Profile model looks like this:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
...
shopping_cart = models.ManyToManyField(
to=Clothing,
related_name="shopping_cart",
blank=True
)
To add new item to shopping_cart field I use request object that has user object which in turn has profile that I need:
request.user.profile.shopping_cart.add(item)
So, I want to let user add multiple instances of the same item to shoping_cart, and then just count how many and what items do user has in his shopping_cart, probably, with Counter from collections.
Then, if I added let's say, 3 items to shopping_cart, I expecting output like this (with Counter from collections):
Counter({<Clothing: 14VQv52T2409iXGC7958>: 3})
But I got this:
Counter({<Clothing: 14VQv52T2409iXGC7958>: 1})
Now, who can explain why this happens, because I thought M2M means I can add multiple instances of same item, and it will display ALL added items.
UPD 1:
Intermediate model:
class ShoppingCart(models.Model):
item = models.ForeignKey(to=Clothing, on_delete=models.CASCADE)
in_profile = models.ForeignKey(to="Profile", on_delete=models.CASCADE)
count = models.PositiveSmallIntegerField(
default=1,
blank=False,
null=False
)
def __str__(self):
return self.item.title
Part where I proceeding request:
def proceed_request(self, request):
item = Clothing.objects.get(pk=request.POST.get("id"))
related_field = request.user.profile.shopping_cart
if item and item in related_field.all():
related_field.count() += 1 # Throws 'SyntaxError: can't assign to function call' error.
related_field.save()
messages.add_message(request, messages.SUCCESS, f"{item.title} has successfully uppdated!")
return HttpResponse(status=200)
related_field.add(item)
messages.add_message(request, messages.SUCCESS, f"{item.title} has successfully added to {self.verbose_field_name}!")
return HttpResponse(status=200)
UPD 2:
Updated proceed_request function. now all works well.
def proceed_request(self, request):
item = Clothing.objects.get(pk=request.POST.get("id"))
related_model = request.user.profile.shopping_cart
if item and item in related_model.all():
cart_item = ShoppingCart.objects.get(item=item)
cart_item.count += 1
cart_item.save()
messages.add_message(request, messages.SUCCESS, f"{item.title} has successfully uppdated!")
return HttpResponse(status=200)
ShoppingCart.objects.create(item=item, in_profile=request.user.profile)
messages.add_message(request, messages.SUCCESS, f"{item.title} has successfully added to {self.verbose_model_name}!")
return HttpResponse(status=200)
With M2M you can add multiple different items of Clothing, but adding the same item multiple times will not duplicate the relation. Have a look at adding a count field to the relation by using through:
https://docs.djangoproject.com/en/3.0/topics/db/models/#extra-fields-on-many-to-many-relationships

Django - Make a related queryset for a set of foreignkeys

Hi I am trying to write a view, so that I can display all Items related to a Bill. How do I have to write my query? The query bills returns a QuerySet[bill1, bill2]. Thought I can get a related queryset, so I can access every item of a bill.
If I do a for-loop now in my HTML I have all items listed for both bills no the one they relate to.
The models.py looks like this:
class Bill(models.Model):
event = models.ForeignKey(Event)
customer = models.ForeignKey(Team)
date = models.DateField()
class Item(models.Model):
bill = models.ForeignKey(Bill)
registration = models.OneToOneField(Registration, unique=True)
I wrote a view:
def payments(request):
customer = Team.objects.get(owner=request.user) # Gets the right user
bills = customer.bill_set.all() # Query all bills of the user
items = bills.item_set.all() # Tried but doesnt work
context = {'bills': bills,
'items': items,
'customer': customer,}
return render(request, 'payment/payments.html', context)
You could use the in field lookup. The code would be this simple:
items = Item.objects.filter(bill__in=bills)
Where bills is your Bill queryset.

Create Django Table displaying information about users

I am currently using django 1.8 and I'd like to create a more intelligent way to display information about users. Say I have something like this:
class User(models.Model):
name = models.CharField()
class Invitation(models.Model):
inviter = models.ForeignKey(User)
invitee = models.ForeignKey(User)
I want to create a field that is the unique number of user's an inviter has invited. I could see how this could be done with something like set("SELECT invitee FROM INVITATIONS WHERE inviter = 'my-user';"), but if I want this displayed in the admin panel, is there a simple way to present this?
Also, I would want this done for every user, so it feels like there is a simple way to make a field generated for every user in the table.
First, let's setup proper related_name- it'll help reduce a lot of confusion in the code.
class Invitation(models.Model):
inviter = models.ForeignKey(User, related_name="invitation_sent")
invitee = models.ForeignKey(User, related_name="invitation_recv")
With the related_name setup, we can do queries such as
user = User.objects.get(pk=1)
# retrieve all invitation objects sent by this user
user.invitation_sent.all()
# retrieve all invitation objects received by this user
user.invitation_recv.all()
Now we can actually count the number of unique invitations a user has sent out quite easily:
# count number of distinct invitee for user
user.invitation_sent.all().values('invitee').distinct().count()
Next, we can actually count the number of unique users a user has invited in a single database query for all users:
user_list = User.objects.all().annotate(
uniq_inv=Count('invitation_sent__invitee', distinct=True)
)
Each user object returned will have an additional property called uniq_inv which contains the count of unique users the user has invited
for user in user_list:
print(user.name + ' invited ' + user.uniq_inv + ' unique users')
To apply this to the admin interface, you'll need to override get_queryset method:
class MyAdmin(admin.ModelAdmin):
...
list_display = [..., 'uniq_inv']
def uniq_inv(self, obj):
return obj.uniq_inv
uniq_inv.short_description = 'Unique Invitees'
def get_queryset(self, request):
qs = super(MyAdmin, self).get_queryset(request)
qs = qs.annotate(uniq_inv=Count('invitation_sent__invitee', distinct=True))
return qs
You can use annotate, which allows to add calculated fields to a queryset.
Models:
class User(models.Model):
name = models.CharField()
class Invitation(models.Model):
inviter = models.ForeignKey(User,related_name="inviter_user")
invitee = models.ForeignKey(User,related_name="invited_user")
Queryset:
from django.db.models import Count
q = Invitation.objects.annotate(count_invitee=Count('invitee')).all()
Now "count_invitee" field has the number for each invitation object.
If you want to filter invitee from the user side.
For a single user:
User.objects.get(pk=1).invited_user.all.count()
For all users queryset:
User.objects.annotate((count_invitee=Count('invited_user')).all()