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.
Related
I want to create a seralizer with 3 models and many to many relationship:
# models.py
class Permission(models.Model):
permission_name = models.CharField(max_length=20)
class Feature(models.Model):
feature_name = models.CharField(max_length=40)
class Role(models.Model):
name = models.CharField(max_length=40)
permissions = models.ManyToManyField(Permission, through='RolePermission')
features = models.ManyToManyField(Feature, through='RolePermission')
class RolePermission(models.Model):
role = models.ForeignKey(Role, on_delete=models.CASCADE)
permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
feature = models.ForeignKey(Feature, on_delete=models.CASCADE)
Sample data:
PERMISSION:
1 - add
2 - edit
3 - remove
4 - view
FEATURE:
1 - user
2 - device
ROLE:
1 - ROLE1
2 - ROLE2
data i want to response from view:
[
{
"id": 1,
"name": "ROLE1",
"features": [
{
"id": 1,
"name": "user",
"permissions": [
{
"id": 1,
"name": "add"
},
{
"id": 2,
"name": "edit"
},
{
"id": 3,
"name": "remove"
},
{
"id": 4,
"name": "view"
}
]
},
{
"id": 2,
"name": "device",
"permissions": [
{
"id": 4,
"name": "view"
}
]
}
]
},
{
"id": 2,
"name": "ROLE2",
"features": [
{
"id": 1,
"name": "user",
"permissions": [
{
"id": 4,
"name": "view"
}
]
},
{
"id": 2,
"name": "device",
"permissions": [
{
"id": 4,
"name": "view"
}
]
}
]
}
]
But i cant write the serializer correctly?
Any help is appreciated.
I guess you should use this code, maybe there is different field_names
class PermisionSerializer(serializers.ModelSerializer):
class Meta:
model = Permission
fields = ('name', )
class FeatureSerializer(serializers.ModelSerializer):
permissions = PermisionSerializer(many=True)
class Meta:
model = Feature
fields = ('name', 'permissions', )
class RoleSerializer(serializers.ModelSerializer):
features = FeatureSerializer(many=True)
class Meta:
model = Role
fields = ('name', 'features', )
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 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
I get an error while creating merchant object and store_categories object. I get an error 'ValueError: Cannot assign "": "Store.merchant" must be a "User" instance.
' I could not resolve an issue.
My merchant object looks like this
[
"merchant": {
"id": 6,
"username": "name",
"first_name": "martin",
"last_name": "lee",
"email": "emailname#gmail.com"
},
],
My store_Categories object looks like this
"store_categories": [
{
"id": 4,
"product": {
"id": 1,
"image": {
"id": 1,
"imageName": "fishCutlet.jpg",
"image": "http://localhost:8000/api/stores/list/products/images/fishCutlet.jpg"
},
"name_of_product": "Fish Cutlet",
"description": "Steamed fish minced with spices, combined with potatoes, shaped into cutlets and fried.",
"price": "150.00",
"active": true
},
"store_category": "FOODS"
},
{
"id": 5,
"product": {
"id": 2,
"image": {
"id": 2,
"imageName": "chickenChowmein.jpg",
"image": "http://localhost:8000/api/stores/list/products/images/chickenChowmein.jpg"
},
"name_of_product": "Chicken Chowmin",
"description": "Delicious chicken chowmein with spicy flavor and herbs that makes it hygienic",
"price": "120.00",
"active": true
},
"store_category": "FOODS"
}
],
My StoreCreateSerializer code
class StoreCreateSerializer(ModelSerializer):
store_categories = StoreCategorySerializer()
merchant = UserSerializer()
class Meta:
model = Store
fields=("id",
"merchant",
"store_categories",
"name_of_legal_entity",
"pan_number",
"registered_office_address",
"name_of_store",
"store_contact_number",
"store_long",
"store_lat",
"store_start_time",
"store_end_time",
"store_off_day",
)
def create(self,validated_data):
store_categories_data = validated_data.pop('store_categories')
merchant_data = validated_data.pop('merchant')
for merchantKey, merchantVal in merchant_data.items():
try:
user = User.objects.create(username=merchantVal)
merchant,created = Merchant.objects.get_or_create(user=user)
validated_data['merchant']=merchant
store = Store.objects.create(**validated_data)
for store_categories in store_categories_data:
store_categories, created = StoreCategory.objects.get_or_create(pan_number=store_categories['pan_number'])
store_categories.product.store = store
store_categories.save()
return store
except User.DoesNotExist:
raise NotFound('not found')
I am beginner in django. I want to get all subcategories in a respective category or reversible order.
class Category(models.Model):
name_en = models.CharField(max_length=100)
name_pt = models.CharField(max_length=100)
parent = models.ForeignKey('self', null = True, blank = True, related_name = "subcategory")
status = models.CharField(max_length=1, blank=True, null=True, default='1', help_text = "1= Active, 0= Inactive")
class Meta:
db_table = 'news_category'
def __unicode__(self):
return self.id
This is serializer class in serializer.py:
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
I want serialized data as bellow:
{
"status": 200,
"data": [
{
"child": [],
"id": 1,
"name_en": "India",
"name_pt": "Índia",
"parent": null,
"status": "1"
},
{
"child": [ {
"child":[],
"id": 6,
"name_en": "XYZ",
"name_pt": "XYZ",
"parent": 2,
"status": "1"
},
{
"child": [],
"id": 7,
"name_en": "ABC",
"name_pt": "ABC",
"parent": 2,
"status": "1"
}
],
"id": 2,
"name_en": "World",
"name_pt": "mundo",
"parent": null,
"status": "1"
},
{
"child": [],
"id": 3,
"name_en": "Cali",
"name_pt": "cali",
"parent": 3,
"status": "1"
}
],
"error": 0
}
Above Json child has all data within parent data. I want this type of json Please help me.
https://gist.github.com/mhulse/1031882
Above link gives parent detail. But I also need child details or reverse order.