I have two models, Appointment and EmployeeEvent. I need to get data from these models and combine the result in to a single get api request.
urls.py
url(r'^calenderevents', calender_events)
views.py
#api_view(['GET'])
def calender_events(request):
queryset1 = Appointment.objects.all()
queryset2 = EmployeeEvent.objects.all()
return Response({'Appointments':json.loads(serializers.serialize('json', queryset1)), 'EmployeeEvents': json.loads(serializers.serialize('json', queryset2))})
When I call the API, I am getting the result, but it includes some unwanted keys like "pk", "model", "fields" etc. Also in the appoinments result, I need the full customer object instead of the customer id. Is there any way to specify the CustomerSerializer along with the query set?
Results am getting
{
"Appointments": [
{
"pk": "33a0fffb-326e-4566-bfb4-b146a87a4f3f",
"model": "appointment.appointment",
"fields": {
"customer": "25503315-8bac-4070-87c1-86bf0630c846",
"status": "Requested",
"description": "Assigned appointment",
}
},
{
"pk": "9da806f5-77f1-41e6-a745-7be3f79d6f7a",
"model": "appointment.appointment",
"fields": {
"customer": "25503315-8bac-4070-87c1-86bf0630c846",
"status": "Requested",
"description": "Assigned appointment",
}
}
],
"EmployeeEvents": [
{
"pk": "f76b5de0-1ab8-4ac3-947d-15ba8941d97d",
"model": "employee_event.employeeevent",
"fields": {
"event_name": "New Event",
"start_date": "2017-02-17",
"end_date": "2017-02-22"
}
},
{
"pk": "56f02290-370e-426c-951e-a93c57fde681",
"model": "employee_event.employeeevent",
"fields": {
"event_name": "New Event",
"start_date": "2017-02-02",
"end_date": "2017-03-22"
}
}
]
}
Expected Result
{
"Appointments": [
{
"id": "33a0fffb-326e-4566-bfb4-b146a87a4f3f",
"customer": {
"id": "25503315-8bac-4070-87c1-86bf0630c846",
"firstname": "Customre 1",
"photo_url": "imagepath",
},
"status": "Requested",
"description": "Assigned appointment"
},
{
"id": "9da806f5-77f1-41e6-a745-7be3f79d6f7a",
"customer": {
"id": "15ba8941d97d-8bac-4070-87c1-86bf0630c846",
"firstname": "Customre 2",
"photo_url": "imagepath",
},
"status": "Requested",
"description": "Assigned appointment"
},
}
],
"EmployeeEvents": [
{
"id": "f76b5de0-1ab8-4ac3-947d-15ba8941d97d",
"event_name": "New Event 1",
"start_date": "2017-02-17",
"end_date": "2017-02-22"
},
{
"id": "56f02290-370e-426c-951e-a93c57fde681",
"event_name": "New Event 2”,
"start_date": "2017-02-17",
"end_date": "2017-02-22"
}
]
}
You need to write a serializer to display the data in the desired format. Read the excellent tutorial to guide you though it properly. But if you want a quick hacky answer, then do something like this:
serializer = AppointmentSerializer(Appointment.objects.all(), many=True)
return Response(serializer.data)
Where the serializer looks something like this:
class AppointmentSerializer(serializers.ModelSerializer):
customer = CustomerSerializer(required=False, allow_null=True)
class Meta:
model = Appointment
fields = ('id', 'customer', 'status', 'etc...')
related_object = 'customer'
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = ('id', 'first_name', 'etc...')
Edit: updated to include example of a related object
Related
I have a GraphQL schema that returns orders and the products that are part of that order. I have added a filter to return only orders that contains products searched for by the user. This filter is done on a icontains.
However I have found that if a user searches for angel for example, and an order contains two or more products that contain the string angel it returns the order that many times duplicating the records returned to the frontend.
Query:
{
dateFilterList
Purchases(first: 15, after: "", username_Icontains: "", PurchaseOrdersProductsOrderId_ProductName: "angel") {
pageCursors {
previous {
cursor
}
first {
cursor
page
}
around {
cursor
isCurrent
page
}
last {
cursor
page
}
next {
cursor
}
}
edges {
node {
id
cmOrderId
username
date
articles
merchandiseValue
shippingValue
trusteeValue
totalValue
products {
edges {
node {
id
productId
productName
productNumber
}
}
}
}
}
}
}
Json Response:
{
"data": {
...
"purchases": {
...
"edges": [
{
"node": {
"id": "",
"cmOrderId": 12345,
"username": "UserA",
"date": "2022-06-29T16:38:51",
"articles": 40,
"merchandiseValue": "",
"shippingValue": "",
"trusteeValue": "",
"totalValue": "",
"products": {
"edges": [
{
"node": {
"id": "",
"productId": "",
"productName": "Angel of Grace",
"productNumber": "1"
}
},
{
"node": {
"id": "",
"productId": "",
"productName": "Angel of Sanctions",
"productNumber": "1"
}
},
...
]
}
},
"node": {
"id": "",
"cmOrderId": 12345,
"username": "UserA",
"date": "2022-06-29T16:38:51",
"articles": 40,
"merchandiseValue": "",
"shippingValue": "",
"trusteeValue": "",
"totalValue": "",
"products": {
"edges": [
{
"node": {
"id": "",
"productId": "",
"productName": "Angel of Grace",
"productNumber": "1"
}
},
{
"node": {
"id": "",
"productId": "",
"productName": "Angel of Sanctions",
"productNumber": "1"
}
},
...
]
}
},
...
Schema:
# region Integration Purchase Orders
class PurchaseOrderFilter(FilterSet):
class Meta:
model = purchase_orders
fields = {'date': ['gt', 'lt', 'isnull'], 'username': ['icontains'],}
purchase_orders_products_order_id__product_name = CharFilter(lookup_expr="icontains")
class PurchaseOrderProductFilter(FilterSet):
class Meta:
model = purchase_orders_products
fields = {"product_name": ["icontains"]}
class PurchasesProducts(DjangoObjectType):
id = graphene.ID(source='pk', required=True)
class Meta:
model = purchase_orders_products
interfaces = (graphene.relay.Node,)
filterset_class = PurchaseOrderProductFilter
class Purchases(DjangoObjectType):
id = graphene.ID(source='pk', required=True)
products = DjangoFilterConnectionField(PurchasesProducts)
class Meta:
model = purchase_orders
interfaces = (graphene.relay.Node,)
filterset_class = PurchaseOrderFilter
connection_class = ArtsyConnection
#staticmethod
def resolve_products(self, info, **kwargs):
return purchase_orders_products.objects.filter(order_id=self.id).order_by('product_name').all()
class PurchasesQuery(ObjectType):
date_filter_list = graphene.List(graphene.List(graphene.String))
purchases = ArtsyConnectionField(Purchases)
#staticmethod
def resolve_date_filter_list(self, info, **kwargs):
years = purchase_orders.objects.filter(user_id=info.context.user.id).annotate(year=ExtractYear('date'), month=ExtractMonth('date'), ).order_by().values_list('year', 'month').order_by('-year', '-month').distinct()
return years
#staticmethod
def resolve_purchases(self, info, **kwargs):
return purchase_orders.objects.filter(user_id=info.context.user.id).all().order_by("-date")
PurchasesSchema = graphene.Schema(query=PurchasesQuery)
# endregion
Problem
Your query is likely returning duplicate results. It's sometimes not enough to just call .distinct().
Solution
You must specify DISTINCT ON <field> as it seems your id field is returning an empty string. Consider a adding .distinct('cmOrderId') to your query.
I also notice that most of your purchase_order_product queries do not include distinct—consider adding the .distinct('cmOrderId') to all of these queries.
Notes
Furthermore, I notice that you call all() on your filter() queries—it has no effect on the resulting object.
References
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#filter
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#django.db.models.query.QuerySet.distinct
I am new to Django rest framework.i am trying to get child model records to the parent model as a field so that all the RefreshmentImage models records are available in games_sports list.i have posted sample code.
model.py
class Refreshment(models.Model):
title = models.CharField(max_length=200, unique=True)
type = models.CharField(max_length=200)
charges = models.DecimalField(max_digits=12, decimal_places=2, help_text="Charges per hour")
class RefreshmentImage(models.Model):
refreshment = models.ForeignKey(Refreshment, on_delete=models.CASCADE)
image = models.FileField(upload_to="refreshment_image/", null=True, blank=True)
serializers.py
class EntertainmentSerializer(serializers.ModelSerializer):
class Meta:
model = Refreshment
fields = '__all__'
class RefreshmentImageSerializer(serializers.ModelSerializer):
refreshment = EntertainmentSerializer(read_only=True, many=True)
class Meta:
model = RefreshmentImage
fields = '__all__'
views.py
def all_games_sports(request):
entertainment = Refreshment.objects.all()
serialize = EntertainmentSerializer(instance=entertainment,many=True)
serial = RefreshmentImageSerializer(instance=entertainment,many=True)
main = {'status': True, 'code': CODE_SUCCESSFUL, 'msg': SUCCESS, 'games_sports': serialize.data,'image':serial.data}
return HttpResponse(json.dumps(main), content_type='application/json')
what i got is like:
games_sports": [
{
"id": 1,
"title": "yyy",
"type": 1,
"charges": "500.00",
},
{
"id": 2,
"title": "xxxxx",
"type": "something",
"charges": "501.00",
}
*******
],
"image": [
{
"id": 1,
"image": null,
"date_created": "2019-03-03T08:16:15.538024+05:30"
},
**********
]
i want it to be:
games_sports": [
{
"id": 1,
"title": "yyy",
"type": 1,
"charges": "500.00",
"image": [
{
"id": 1,
"image": image_path,
"date_created": "2019-03-03T08:16:15.538024+05:30"
},
}
***********
],
Try this snippet
#serializers.py
"""I've re-arranged the order of 'RefreshmentImageSerializer' serializer and 'EntertainmentSerializer' serializer"""
class RefreshmentImageSerializer(serializers.ModelSerializer):
class Meta:
model = RefreshmentImage
fields = '__all__'
class EntertainmentSerializer(serializers.ModelSerializer):
image = RefreshmentImageSerializer(many=True, source='refreshmentimage_set')
class Meta:
model = Refreshment
fields = '__all__'
# views.py
"""Added DRF stuffs such as 'api_view' and 'Response'"""
from rest_framework.decorators import api_view
#api_view()
def all_games_sports(request):
entertainment = Refreshment.objects.all()
serialize = EntertainmentSerializer(instance=entertainment, many=True)
main = {'status': True, 'code': "CODE_SUCCESSFUL", 'msg': "SUCCESS", 'games_sports': serialize.data}
return Response(main)
{
"status": true,
"code": "CODE_SUCCESSFUL",
"msg": "SUCCESS",
"games_sports": [
{
"id": 1,
"image": [
{
"id": 1,
"image": null,
"refreshment": 1
},
{
"id": 3,
"image": "refreshment_image/jpg-icon.png",
"refreshment": 1
}
],
"title": "t1",
"type": "tt1",
"charges": "123.00"
},
{
"id": 2,
"image": [
{
"id": 2,
"image": "refreshment_image/asd.jpg",
"refreshment": 2
}
],
"title": "t2",
"type": "tt2",
"charges": "321.00"
},
{
"id": 3,
"image": [
{
"id": 4,
"image": "refreshment_image/Screenshot_from_2018-10-26_16-32-41.png",
"refreshment": 3
},
{
"id": 5,
"image": "refreshment_image/twitter.png",
"refreshment": 3
}
],
"title": "t3",
"type": "tt3",
"charges": "754.00"
}
]
}
What I've done here?
re-arranged the order of serializer to avoid not defined errors
added a new field in EntertainmentSerializer class to show the images associated with the Refreshment object
In views.py I've added DRF pieces of stuff, which is more suitable
References
#api_view() decorator
DRF's Response() class
DRF Nested Serializers
The source keyword argument
Hope this helps!!
I like to periodically import json data into a Django. What's the best way to import the data below to a Django model.
As far as I've seen is the best approach to use Django fixtures. Since my Model looks like this and I can't change the given JSON, what's the best way to import the data or restructure the JSON to use it as a fixture.
Django Model
class Item(models.Model):
item_name = models.CharField(max_length=250)
timestamp = models.DateTimeField()
value01 = models.DecimalField(max_digits=7, decimal_places=2)
value02 = models.DecimalField(max_digits=7, decimal_places=2)
Data I like to store:
Item1 | 2017-04-18 09:24:46 | 15.00 | 12.68
Item1 | 2017-04-18 09:25:44 | 14.92 | 12.42
Given JSON:
[
{
"id": 1,
"timestamp": "2017-04-18 09:24:46",
"details": {
"id": 843,
"color": "white"
},
"item": {
"id": 1691,
"category": "1",
"item_type": {
"id": 14,
"name": "Item1"
}
},
"itemdatavalues": [
{
"id": 227,
"value": "15.00"
},
{
"id": 228,
"value": "12.68"
}
]
},
{
"id": 2,
"timestamp": "2017-04-18 09:25:44",
"details": {
"id": 843,
"color": "white"
},
"item": {
"id": 161,
"category": "1",
"item_type": {
"id": 14,
"name": "Item1"
}
},
"itemdatavalues": [
{
"id": 283,
"value": "14.92"
},
{
"id": 284,
"value": "12.42"
}
]
}
]
I wrote a simple script to parse the input file and generate a fixture:
import json
import copy
with open('/tmp/data.json') as dataf, open('/tmp/output.json', 'w') as out:
data = json.load(dataf)
newdata = []
for i, block in enumerate(data):
new = dict(model="appname.Item", pk=block['id'])
new['fields'] = dict(item_name=block['item']['item_type']['name'],
timestamp=block['timestamp'],
value01=block['itemdatavalues'][0]['value'],
value02=block['itemdatavalues'][1]['value'])
newdata.append(copy.deepcopy(new))
json.dump(newdata, out, indent=2)
Using your input, this results in:
[
{
"pk": 1,
"model": "appname.Item",
"fields": {
"item_name": "Item1",
"timestamp": "2017-04-18 09:24:46",
"value01": "15.00",
"value02": "12.68"
}
},
{
"pk": 2,
"model": "appname.Item",
"fields": {
"item_name": "Item1",
"timestamp": "2017-04-18 09:25:44",
"value01": "14.92",
"value02": "12.42"
}
}
]
Which is suitable for use as a fixture. Obviously, you will have to fix the appname.
This might help: https://docs.djangoproject.com/en/1.11/ref/models/instances/. You should be able to create a new model object in whatever methods you are receiving that json in, then parse whatever json values you want into the object. There are some pretty easy json libraries for python. That is, unless you are wanting to handle something differently, or I am reading the documentation wrong. Have a good day!
from django.db import models
# django user
from django.contrib.auth.models import User
class Entity(models.Model):
"""
Entity of EAV
"""
entity = models.CharField(max_length=216,
null=False, default='entity_name',
name='entity', verbose_name='Entity of EAV',
db_index=True,
unique=True
)
class Asset(models.Model):
"""
Asset of EAV
"""
asset = models.CharField(max_length=216, null=False,
default='asset', name='asset',
verbose_name='Asset of EAV'
)
entity = models.ForeignKey(to=Entity)
class Meta:
unique_together = ("asset", "entity")
class Value(models.Model):
"""
Value of EAV
"""
value = models.CharField(max_length=216,
null=False, default='value',
name='value', verbose_name='Value of EAV'
)
asset = models.ForeignKey(to=Asset)
owner = models.ForeignKey(User, verbose_name='EAV Owner', related_name='eav')
class Meta:
unique_together = ('value', 'asset', 'owner')
Serializers
class EntitySerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
entity = serializers.CharField(label='Entity of EAV', max_length=216, required=False)
class AssetSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
asset = serializers.CharField(default='asset', label='Asset of EAV', max_length=216)
entity = EntitySerializer(read_only=True)
class ValueSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
value = serializers.CharField(default='value', label='Value of EAV', max_length=216)
asset = AssetSerializer(read_only=True)
owner = UserModelSerializer(read_only=True)
class EntityAssetValueSerializer(serializers.Serializer):
entity = EntitySerializer(many=True)
asset = AssetSerializer(many=True)
value = ValueSerializer(many=True)
Expected Serialization
{
"entities": [
{
"entity": "Hero",
"id": 1,
"owner": {
"name": "BatMan",
"id": "1"
},
"groups": [
{
"id": "1",
"name": "SuperHeroes Group"
}
],
"asset": [
{
"asset": "Name",
"value": "BatMan",
"asset_id": 1,
"value_id": 1
},
{
"asset": "Age",
"value": "30",
"asset_id": 1,
"value_id": 2
}
]
},
{
"entity": "Hero",
"id": 1,
"owner": {
"name": "SuperMan",
"id": "2"
},
"groups": [
{
"id": "1",
"name": "SuperHeroes Group"
}
],
"asset": [
{
"asset": "Name",
"value": "SuperMan",
"asset_id": 1,
"value_id": 3
},
{
"asset": "Age",
"value": "30",
"asset_id": 1,
"value_id": 4
}
]
},
{
"entity": "Villian",
"id": 1,
"owner": {
"name": "Joker",
"id": "3"
},
"groups": [
{
"id": "2",
"name": "SuperVillians Group"
}
],
"asset": [
{
"asset": "Name",
"value": "Joker",
"asset_id": 3,
"value_id": 4
},
{
"asset": "Age",
"value": "30",
"asset_id": 4,
"value_id": 5
}
]
},
{
"entity": "Person",
"id": 1,
"owner": {
"name": "Puny Human",
"id": "3"
},
"groups": [
{
"id": "2",
"name": "Humans Group"
}
],
"asset": [
{
"asset": "Name",
"value": "Human Being",
"asset_id": 5,
"value_id": 6
},
{
"asset": "Age",
"value": "30",
"asset_id": 6,
"value_id": 7
}
]
}
]
}
Achieved Serialization
{
"eav": [
{
"id": 1,
"value": "Human",
"asset": {
"id": 1,
"asset": "Name",
"entity": {
"id": 1,
"entity": "Human"
}
},
"owner": {
"id": 1,
"username": "PunyHuman"
}
},
{
"id": 2,
"value": "26",
"asset": {
"id": 2,
"asset": "Age",
"entity": {
"id": 1,
"entity": "Human"
}
},
"owner": {
"id": 1,
"username": "PunyHuman"
}
},
{
"id": 3,
"value": "26",
"asset": {
"id": 3,
"asset": "Age",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 2,
"username": "BatMan"
}
},
{
"id": 4,
"value": "BatMan",
"asset": {
"id": 3,
"asset": "Name",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 2,
"username": "BatMan"
}
},
{
"id": 5,
"value": "26",
"asset": {
"id": 3,
"asset": "Age",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 3,
"username": "SuperMan"
}
},
{
"id": 6,
"value": "SuperMan",
"asset": {
"id": 4,
"asset": "Name",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 3,
"username": "SuperMan"
}
}
]
}
API View
class EntityAssetValueAPIView(APIView):
queryset = Value.objects.select_related('asset', 'asset__entity', 'owner')
serializer_class = ValueSerializer
# If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
# lookup_url_kwarg = None
# The filter backend classes to use for queryset filtering
# filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
# The style to use for queryset pagination.
# pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
# def allowed_methods(self):
# http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
# return http_method_names
def get(self, request, *args, **kwargs):
eav = self.queryset.all()
serializer = self.serializer_class(eav, many=True)
return Response(serializer.data)
What I want to do is, Get all the ENTITIES Assigned to a USER ( along with the ASSET & VALUES ).
The same data is posted for a NEW ENTITY ASSIGNMENT to USER .
From What I understood from DRF, I would need an API view, API view would call serializer, so, I would have to create a custom Serializer, then to save the data I have to override create method, where in I will have these separate serializers that would validate the data and save it.
I am not able to send the desired RESPONSE or ingest the REQUEST coming in.
What should be a way forward ?
I have faced the similar problem So I'll explain a little scenario here. So you can take reference from that.
Added some related names in models :
class Asset(models.Model):
"""
Asset of EAV
"""
asset = models.CharField(max_length=216, null=False,
default='asset', name='asset',
verbose_name='Asset of EAV'
)
entity = models.ForeignKey(to=Entity, related_name='asset_entity')
class Value(models.Model):
"""
Value of EAV
"""
value = models.CharField(max_length=216,
null=False, default='value',
name='value', verbose_name='Value of EAV'
)
asset = models.ForeignKey(to=Asset, related_name='asset_value')
owner = models.ForeignKey(User, verbose_name='EAV Owner', related_name='eav')
initial queryset looks like this, the idea is to fetch all information that is required initially:
queryset = Entity.objects.filter('**condition comes here**')
.values('id', 'entity', 'asset_entity', 'asset_entity__asset', 'asset_entity__asset_value', 'asset_entity__asset_value__value',
'asset_entity__asset_value__owner_id',)
Pass this queryset when trying to make response :
serializer = serializer(queryset, many=True, context={'request': request})
Serailizers :
class Owner_Serializer(serializers.ModelSerializer)
class Meta:
model = User
exclude = ('**exclude fields you want to exclude**', )
class EntitySerializer(serializers.Serializer):
id = serializers.IntegerField(source='id')
entity = serializers.CharField(source='entity')
owner = serializers.SerializerMethodField()
groups = serializers.SerializerMethodField()
asset = serializers.SerializerMethodField()
def get_owner(self, obj):
return Owner_Serializer(obj.get('asset_entity__asset_value__owner_id'), context=self.context).data
Same process goes for groups and asset fields.
in get_owner() we have entity object and from that object we can get owner_id , as we have already fetched related data initially.
So the main idea here to fetch all data initially and then serilaize that data according to your requirement.
Existing Nested Serailization do not support the response format you required.
Note : Initial querset is vry important , you may need to use prefetch related there because we are fetching data using reverse relationship. Also I didn't test the queryset so have to make sure that correct related_names are used to fetch related data.
I want to create fixtures for auth_group_permissions table, but how named it model?
'auth.group.permissions' is not right.
[
{
"model": "auth.group",
"pk": 1,
"fields": {"name": "manager"}
},
{
"model": "auth.group",
"pk": 2,
"fields": {"name": "executive"}
},
{
"model": "auth.group",
"pk": 3,
"fields": {"name": "ordinar"}
},
{
"model": "auth.group.permissions",
"pk": 1,
"fields": {
"group_id": 1,
"permission_id": 7
}
}
]
You can define them in the group as related field
"model": "auth.group",
"fields": {
"name": "foo",
"permissions": [
...
]
There is no model named group.permissions in auth app. But class Group has many-to-many field permissions, so you should use it for your purpose.
Try this fixture:
{
"model": "auth.group",
"pk": 1,
"fields": {
"name": "manager",
"permissions" : [7]
}
}