Combine the results while querying in Django - django

I am struggling to querying in Django as expected.I have multiple models that are Profile, Education, Address and Social Media. Education, Address and Social Media and related with Profile by foreign key and OnoToOne relation. I want the query results that list of profiles and each profile should contain relevant
educations (as list), addresses (as list) and social media (as dictionary).
This is my models.py
from django.db import models
class ORMProfile(models.Model):
profile_photo = models.URLField(blank=True, null=True)
cover_photo = models.URLField(blank=True, null=True)
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
bio = models.TextField(blank=True, null=True)
gender = models.CharField(max_length=120, blank=True, null=True)
dob = models.DateField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
class ORMEducation(models.Model):
profile = models.ForeignKey(ORMProfile, on_delete=True)
school_name = models.CharField(max_length=255, blank=True, null=True)
school_type = models.CharField(max_length=255, blank=True, null=True)
qualification = models.CharField(max_length=255, blank=True, null=True)
description = models.TextField(blank=True, null=True)
start_date = models.DateField(blank=True, null=True)
end_date = models.DateField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
class ORMSocialMedia(models.Model):
profile = models.OneToOneField(ORMProfile, on_delete=True)
linked_in = models.URLField(blank=True, null=True)
facebook = models.URLField(blank=True, null=True)
twitter = models.URLField(blank=True, null=True)
instagram = models.URLField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
class ORMAddress(models.Model):
profile = models.ForeignKey(ORMProfile, on_delete=True)
street = models.CharField(max_length=255, blank=True, null=True)
city = models.CharField(max_length=255, blank=True, null=True)
state = models.CharField(max_length=255, blank=True, null=True)
country = models.CharField(max_length=255, blank=True, null=True)
latitude = models.DecimalField(max_digits=10, decimal_places=8, blank=True, null=True)
longitude = models.DecimalField(max_digits=11, decimal_places=8, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
I am expecting the result is list of profile that each profile includes educations, addresses and social_media. (given below)
[{
"id": 2,
"profile_photo": "google.com",
"cover_photo": "facbook.com",
"first_name": "Uzama",
"last_name": "",
"bio": "",
"gender": "",
"dob": null,
"education": [],
"address": [
{
"id": 4,
"profile_id": 2,
"street": "23",
"city": "",
"state": "",
"country": "",
"latitude": null,
"longitude": null,
"created_at": "2019-12-16T09:12:13.859562+00:00",
"modified_at": "2019-12-16T09:12:13.859615+00:00"
},
{
"id": 5,
"profile_id": 2,
"street": "23",
"city": "",
"state": "",
"country": "",
"latitude": null,
"longitude": null,
"created_at": "2019-12-16T09:12:33.485102+00:00",
"modified_at": "2019-12-16T09:12:33.485167+00:00"
},
{
"id": 6,
"profile_id": 2,
"street": "23",
"city": "",
"state": "",
"country": "",
"latitude": null,
"longitude": null,
"created_at": "2019-12-16T09:13:28.909262+00:00",
"modified_at": "2019-12-16T09:13:28.909325+00:00"
},
{
"id": 7,
"profile_id": 2,
"street": "23",
"city": "",
"state": "",
"country": "",
"latitude": null,
"longitude": null,
"created_at": "2019-12-16T09:13:40.228271+00:00",
"modified_at": "2019-12-16T09:13:40.228369+00:00"
},
{
"id": 8,
"profile_id": 2,
"street": "23",
"city": "",
"state": "",
"country": "",
"latitude": null,
"longitude": null,
"created_at": "2019-12-16T10:27:31.060495+00:00",
"modified_at": "2019-12-16T10:27:31.060565+00:00"
},
{
"id": 9,
"profile_id": 2,
"street": "23",
"city": "",
"state": "",
"country": "",
"latitude": null,
"longitude": null,
"created_at": "2019-12-16T10:27:59.089120+00:00",
"modified_at": "2019-12-16T10:27:59.089171+00:00"
},
{
"id": 10,
"profile_id": 2,
"street": "23",
"city": "",
"state": "",
"country": "",
"latitude": null,
"longitude": null,
"created_at": "2019-12-16T10:28:25.406798+00:00",
"modified_at": "2019-12-16T10:28:25.406869+00:00"
}
],
"social_media": {
"id": 3,
"profile_id": 2,
"linked_in": "linkedin.lk",
"facebook": "Hello",
"twitter": "",
"instagram": "",
"created_at": "2019-12-15T14:20:40.183078+00:00",
"modified_at": "2019-12-16T10:58:30.338692+00:00"
},
"created_at": "2019-12-15T10:36:56.538900+00:00",
"modified_at": "2019-12-18T09:28:07.087380+00:00"
}]
How can I solve this problem.

Using property you can acheive this. Here we are using reverse relationship. Many = True because you may have multiple associations.
class ORMProfile(models.Model):
profile_photo = models.URLField(blank=True, null=True)
cover_photo = models.URLField(blank=True, null=True)
first_name = models.CharField(max_length=255, blank=True, null=True)
last_name = models.CharField(max_length=255, blank=True, null=True)
bio = models.TextField(blank=True, null=True)
gender = models.CharField(max_length=120, blank=True, null=True)
dob = models.DateField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
#property #<----add this block
def education(self):
from .serializers import ORMProfileSerializer # import your relevant serializer class
return ORMProfileSerializer(self.ormeducation_set.all(), many=True).data #reverse relationship

Related

DRF How to display only not blank value of serializing nested object

I've created serializing nested be using serializers as document
models.py
class Category(models.Model):
name = models.CharField("Name", "name", max_length=255)
iconname = models.CharField("Icon Name", "iconname", max_length=255)
budgetamount = models.DecimalField(
max_digits=19, decimal_places=2, default=0)
iconcolor = models.CharField(
"Icon Color", "iconcolor", default='4294951175', max_length=255)
def __str__(self):
return self.name
class DailyExpense(models.Model):
payee_item_desc = models.CharField(
"Payee Item Description", "payee_item_desc", max_length=255)
category = models.ForeignKey(
Category, related_name='dailyexpense_category', on_delete=models.CASCADE, blank=True, null=True)
amount = models.DecimalField(max_digits=19, decimal_places=2)
remarks = models.CharField(
"Remarks", "remarks", max_length=255, blank=True, null=True)
tran_date = models.DateTimeField()
isnotclear = models.BooleanField(default=False)
def __str__(self):
return self.payee_item_desc
serializers.py
class DailyExpenseSerializer(serializers.ModelSerializer):
class Meta:
model = DailyExpense
fields = "__all__"
class CategoryWithDailyExpenseSerializer(serializers.ModelSerializer):
dailyexpense_category = DailyExpenseSerializer(
source='filtered_dailyexpense_category', many=True, read_only=True)
class Meta:
model = Category
fields = ('id', 'name', 'iconname',
'budgetamount', 'iconcolor', 'dailyexpense_category')
views.py
class CategoryWithDailyExpenseViewSet(viewsets.ModelViewSet):
def get_queryset(self):
fromDate = parse_datetime(self.request.query_params.get(
'fromDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
toDate = parse_datetime(self.request.query_params.get(
'toDate') + ' ' + '00:00:00').strftime('%Y-%m-%d %H:%M:%S')
queryset = Category.objects.prefetch_related(
Prefetch('dailyexpense_category', queryset=DailyExpense.objects.filter(
tran_date__range=[fromDate, toDate]).order_by('tran_date'), to_attr='filtered_dailyexpense_category')
)
return queryset
# queryset = Category.objects.all().order_by('name')
serializer_class = CategoryWithDailyExpenseSerializer
filter_class = CategoryFilter
And the result that I got as below
[
{
"id": 1,
"name": "Auto",
"iconname": "taxi_alert_outlined",
"budgetamount": "0.00",
"iconcolor": "4294951175",
"dailyexpense_category": []
},
{
"id": 2,
"name": "Foods:Breakfast",
"iconname": "emoji_food_beverage",
"budgetamount": "0.00",
"iconcolor": "4294951175",
"dailyexpense_category": [
{
"id": 24574,
"payee_item_desc": "เซเว่น",
"amount": "-100.00",
"remarks": "เฟิส",
"tran_date": "2022-04-01T00:00:00Z",
"isnotclear": false,
"category": 2
}
]
}
]
But I want to show only not blank nested object as below
[
{
"id": 2,
"name": "Foods:Breakfast",
"iconname": "emoji_food_beverage",
"budgetamount": "0.00",
"iconcolor": "4294951175",
"dailyexpense_category": [
{
"id": 24574,
"payee_item_desc": "เซเว่น",
"amount": "-100.00",
"remarks": "เฟิส",
"tran_date": "2022-04-01T00:00:00Z",
"isnotclear": false,
"category": 2
}
]
}
]
I've tried to create custom field such as sum nested object or count nested object
but I want something that more easier to filter only not blank objected.
I think you need to add a filter like the following.
queryset = Category.objects.prefetch_related(
Prefetch('dailyexpense_category',
queryset=DailyExpense.objects.filter(tran_date__range=[fromDate, toDate]).order_by('tran_date'))
).annotate(num_daily=Count('dailyexpense_category', filter = Q('dailyexpense_category__tran_date__range' =[fromDate, toDate]))).filter(num_daily__gt=0)

I want to build a nested serializer to display order with product and each product showing its individual value. I have my code below

I am trying to get a nested serializer with individual value displayed with particular product but i am getting all the values in a single product.
i dont kow what to do there is some mistake in my code i cant figure out where.
please help me out.
this is my code
models.py
class Order(models.Model):
user = models.ForeignKey(Account, related_name='orders',
on_delete=models.CASCADE)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
address = models.CharField(max_length=100)
zipcode = models.CharField(max_length=100)
place = models.CharField(max_length=100)
phone = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
paid_amount = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
class Meta:
ordering = ['-created_at',]
def __str__(self):
return self.first_name
def get_total_price(self):
total = sum(item.get_cost() for item in self.items.all())
class OrderItem(models.Model):
order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE, null=True,
blank=True)
glasses = models.ForeignKey(Glasses, related_name='glass', on_delete=models.CASCADE)
price = models.DecimalField(max_digits=8, decimal_places=2)
quantity = models.IntegerField(default=1)
ordered = models.BooleanField(default=False)
def get_cost(self):
return self.price * self.quantity
class Power(models.Model):
frame = models.ForeignKey(OrderItem, related_name='power', on_delete=models.CASCADE)
type = models.CharField(max_length=20, choices=[('Powered', 'Powered'), ('bifocal', 'bifocal'),
('Frame_only', 'Frame_only')])
left_eye_power = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
left_eye_cylinder = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
left_eye_bifocal = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
left_eye_axis = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
right_eye_power = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
right_eye_cylinder = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
right_eye_bifocal = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
right_eye_axis = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
serializer.py
class PowerSerializer(serializers.ModelSerializer):
class Meta:
model = Power
fields = '__all__'
class OrderItemSerializer(serializers.ModelSerializer):
#power = serializers.RelatedField(read_only=True)
power = PowerSerializer(many=True)
class Meta:
model = OrderItem
fields = (
"price",
"glasses",
"power",
"quantity",
)
class OrderSerializer(serializers.ModelSerializer):
items = OrderItemSerializer(many=True)
class Meta:
model = Order
fields = (
"id",
"first_name",
"last_name",
"email",
"address",
"zipcode",
"place",
"phone",
"items",
)
views.py
class OrderListView(ListCreateAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.AllowAny,)
output i got:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"first_name": "priyank",
"last_name": "nair",
"email": "priyankshashinair#gmail.com",
"address": "1/A 401",
"zipcode": "400102",
"place": "Mumbai",
"phone": "9833437879",
"items": [
{
"price": "234.00",
"glasses": 1,
"power": [
{
"id": 1,
"type": "Powered",
"left_eye_power": "0.16",
"left_eye_cylinder": "0.14",
"left_eye_bifocal": "0.16",
"left_eye_axis": "0.13",
"right_eye_power": "0.14",
"right_eye_cylinder": "0.15",
"right_eye_bifocal": "0.14",
"right_eye_axis": "0.19",
"frame": 1
},
{
"id": 2,
"type": "Frame_only",
"left_eye_power": null,
"left_eye_cylinder": null,
"left_eye_bifocal": null,
"left_eye_axis": null,
"right_eye_power": null,
"right_eye_cylinder": null,
"right_eye_bifocal": null,
"right_eye_axis": null,
"frame": 1
}
],
"quantity": 1
},
{
"price": "234.00",
"glasses": 2,
"power": [],
"quantity": 2
}
]
}
]
}
Output i want:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"first_name": "priyank",
"last_name": "nair",
"email": "priyankshashinair#gmail.com",
"address": "1/A 401",
"zipcode": "400102",
"place": "Mumbai",
"phone": "9833437879",
"items": [
{
"price": "234.00",
"glasses": 1,
"power": [
{
"id": 1,
"type": "Powered",
"left_eye_power": "0.16",
"left_eye_cylinder": "0.14",
"left_eye_bifocal": "0.16",
"left_eye_axis": "0.13",
"right_eye_power": "0.14",
"right_eye_cylinder": "0.15",
"right_eye_bifocal": "0.14",
"right_eye_axis": "0.19",
"frame": 1
}
],
"quantity": 1
},
{
"price": "234.00",
"glasses": 2,
"power": [
{
"id": 2,
"type": "Frame_only",
"left_eye_power": null,
"left_eye_cylinder": null,
"left_eye_bifocal": null,
"left_eye_axis": null,
"right_eye_power": null,
"right_eye_cylinder": null,
"right_eye_bifocal": null,
"right_eye_axis": null,
"frame": 1
},
],
"quantity": 2
}
]
}
]
}
Everything is correct, the problem is in your data - both Power objects clearly show "frame": 1, and your desired output is not possible without the second power having "frame": 2.

Django Rest Framework serialize additional fields from intermediate model

I am developing a small application that lists the customers of a store. I'm trying to retrieve the additional fields of the intermediate model because a contact can belong to several stores but depending on the store it is premium or not and if he is happy or not.
Here's the JSON response I'd like to get for a Store like /contacts/?store=my_store
[
{
"id": "UX",
"first_name": "UX",
"last_name": "UX",
"email": null,
"mobile": null,
"happy": True,
"premium": True
},
{
"id": "AX",
"first_name": "AX",
"last_name": "AX",
"email": null,
"mobile": null,
"happy": False,
"premium": True
}
]
here are my models:
class Store(BaseModel):
id = models.CharField(primary_key=True, max_length=200)
name = models.CharField(max_length=100)
class Contact(BaseModel):
id = models.CharField(primary_key=True, max_length=200)
first_name = models.CharField(max_length=100, null=True, blank=True)
last_name = models.CharField(max_length=100, null=True, blank=True)
email = models.CharField(max_length=100, null=True, blank=True)
mobile = models.CharField(max_length=100, null=True, blank=True)
stores = models.ManyToManyField(
Store, through="MemberShip", through_fields=("contact", "store")
)
class MemberShip(BaseModel):
contact = models.ForeignKey(
Contact, on_delete=models.CASCADE, related_name="contact_to_store"
)
store = models.ForeignKey(
Store, on_delete=models.CASCADE, related_name="store_to_contact"
)
happy = models.BooleanField(default=True)
premium = models.BooleanField(default=False)
and my serializers:
class MemberShipSerializer(serializers.ModelSerializer):
class Meta:
model = MemberShip
fields = ("contact", "store", "happy", "premium")
class StoreSerializer(serializers.ModelSerializer):
class Meta:
model = Store
fields = ("id", "name")
class ContactSerializer(serializers.ModelSerializer):
infos = MemberShipSerializer(
source="contact_to_store" many=True, read_only=True
)
class Meta:
model = Contact
fields = (
"id", "first_name", "last_name", "email", "mobile", "infos"
)
As you can see, I first tried to gather all the information of the intermediate model in a field before displaying happy and premium but, strangely enough, the infos field is returned with an empty array value.
Python v 3.7
Django v 2.1
DRF v 3.9
You must provide data to MemberShipSerializer . You can use SerializerMethodField. Like that:
class ContactSerializer(serializers.ModelSerializer):
infos = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Contact
fields = (
"id", "first_name", "last_name", "email", "mobile", "infos"
)
def get_infos(self,obj:Contact):
return MemberShipSerializer(obj.contact_to_store.all(),many=True).data
I tried kamilyrb's solution here's what I changed:
class MemberShipSerializer(serializers.ModelSerializer):
class Meta:
model = MemberShip
fields = ("contact", "store", "happy", "premium")
class StoreSerializer(serializers.ModelSerializer):
class Meta:
model = Store
fields = ("id", "name")
class ContactSerializer(serializers.ModelSerializer):
happy = serializers.SerializerMethodField(read_only=True)
premium = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Contact
fields = (
"id", "first_name", "last_name", "email", "mobile", "happy", "premium"
)
def get_premium(self, obj):
return MemberShipSerializer(obj.contact_to_store.all(), many=True).data
def get_happy(self, obj):
return MemberShipSerializer(obj.contact_to_store.all(), many=True).data
This is what i have now:
[
{
"id": "UX",
"first_name": "UX",
"last_name": "UX",
"email": "0",
"mobile": null,
"happy": [
{
"store": "my-store",
"contact": "UX",
"happy": true,
"premium": false,
},
{
"store": "my-store2",
"contact": "UX",
"happy": false,
"premium": false,
}
],
"premium": [
{
"store": "my-store",
"contact": "UX",
"optin_sms": true,
"happy": false,
"premium": false
}
]
}
]
how can i get that ?
[
{
"id": "UX",
"first_name": "UX",
"last_name": "UX",
"email": null,
"mobile": null,
"happy": True,
"premium": True
},
{
"id": "AX",
"first_name": "AX",
"last_name": "AX",
"email": null,
"mobile": null,
"happy": False,
"premium": True
}
]
I also noticed that all the stores to which a contact is affiliated are shown but as I said before the url is called as follows contact/?store=my-store

Partial object returned when Serializing a model with relationship

So I have two models Foo and Bar. Foo has a one to many relationship with Bar as shown below.
app/models.py
class Foo(models.Model):
id = models.IntegerField(primary_key=True)
sourceid = models.IntegerField(blank=True, null=True)
name = models.TextField(unique=True, null=True)
url = models.TextField(unique=True, null=True)
created_at = models.DateTimeField(default=datetime.datetime.utcnow, null=True)
updated_at = models.DateTimeField(default=datetime.datetime.utcnow,null=True)
class Meta:
managed = False
db_table = 'foo'
class JSONAPIMeta:
resource_name = 'foo'
class Bar(models.Model):
id = models.IntegerField(primary_key=True)
parent_foo = models.ForeignKey(Foo, models.DO_NOTHING, db_column='parentId') # Field name made lowercase.
url = models.TextField()
extension = models.ForeignKey('self', models.DO_NOTHING, db_column='extensionId', blank=True, null=True)
created_at = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'bar'
Now the issue is that I want to create a serializer FooBarList that nests Bars into Foo.
I have managed to slightly achieve this with the following code:
app/serializers.py
class FooBarList(serializers.ModelSerializer):
class Meta:
model = Foo
fields = ('id','name','url','created_at','updated_at','bar_set')
When I call this serialise function the issue arrises... Only the 'id' parameter of the Bar object is shown in the response. This is shown below:
JSON Output
{
"data": [
{
"attributes": {
"created_at": "2017-08-23T16:07:11.384209Z",
"name": "TestFoo",
"updated_at": "2017-08-23T17:41:17.179040Z",
"url": "TestFoo.org"
},
"id": "1",
"relationships": {
"Bar": {
"data": [
{
"id": "1",
"type": "Bar"
},
{
"id": "2",
"type": "Bar"
},
],
"meta": {
"count": 2
}
}
},
"type": "Foo"
},
{
"attributes": {
"created_at": "2017-08-23T16:07:11.390343Z",
"name": "TestFoo2",
"updated_at": "2017-08-23T17:41:17.186193Z",
"url": "TestFoo2.org"
},
"id": "2",
"relationships": {
"Bar": {
"data": [
{
"id": "10",
"type": "Bar"
}
],
"meta": {
"count": 1
}
}
},
"type":"Foo"
}]}
From looking in the database I can see that the IDs are correct howver I would have thought that this should include the other attributes from the Bar object such as 'url'. Any thoughts?
Create a serializer for Bar and provide it in FooBarList serializer.
class FooBarList(serializers.ModelSerializer):
bar = BarSerializer(source='bar')
So the related Bar instance can be serialized

Distinct field Rest Framework Django

I need to make a distinct with a field of my model and not how to make
My model is:
class CheckList(CoreModel):
date = models.DateTimeField(default=datetime.now, blank=True, null=True, verbose_name=_('Date'))
establishment = models.ForeignKey(Establishment, related_name="checklists", on_delete=models.CASCADE, null=True, verbose_name=_('Establishment'))
user = models.ForeignKey(ITManager, related_name="checklists", on_delete=models.CASCADE, null=True, verbose_name=_('User'))
class Meta:
verbose_name_plural = _("Checklist")
verbose_name = _("Checklists")
def __str__(self):
return str(self.date)
My serializer and view:
class CheckListSerializer(BulkSerializerMixin, serializers.ModelSerializer):
user = ITManagerSerializer()
class Meta:
model = CheckList
list_serializer_class = BulkListSerializer
fields = ['id', 'user', 'establishment', 'date']
class ChecklistBulkViewSet(BulkModelViewSet):
queryset = CheckList.objects.values('establishment', 'user', 'date').distinct()
model = CheckList
serializer_class = CheckListSerializer
filter_class = ChecklistFilter
The api return me:
"results": [
{
"id": 1,
"user": {
"id": 3,
"first_name": "Andres",
"last_name": "Gallardo",
"rut": "21312",
"email": null,
"user_name": "andres",
"password": null,
"user": 4,
"country": [],
"active": true
},
"establishment": 3,
"date": "2016-06-14T15:15:00Z"
},
{
"id": 2,
"user": {
"id": 2,
"first_name": "Ramiro",
"last_name": "Gutierrez",
"rut": "15616+",
"email": null,
"user_name": null,
"password": null,
"user": 2,
"country": [
{
"id": 1,
"name": "Argentina",
"code_area": null
}
],
"active": false
},
"establishment": 3,
"date": "2016-06-09T15:40:04Z"
}]
I need you just leave me an establishment with the same id
any suggestions??
Thanks !