How to get data from multiple nested serializer? - django

serializer
class CarrGetOrderDetails(serializers.Serializer):
order = CarrGetOrderDetail(required=False)
template = CarrGetOrderDetailTemplate(required=False, many=True)
extra_fields = CarrGetOrderDetailExtraFields(required=False, many=True)
View File
class CarrierOrderDetails(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request):
order_id = request.GET['order_id']
#order_obj = Order.objects.filter(id=order_id)
obj = self.get_objects(order_id)
#print('#####',obj)
serializ = CarrGetOrderDetails(obj, many=True)
return Response(serializ.data)
def get_objects(self, order_obj):
model1 = Order.objects.filter(id=order_obj)
model2 = OrderTemplate.objects.filter(id=1)
model3 = OrderExtraField.objects.filter(id=1)
obj = {'order': model1, 'template': model2, 'extra_fields': model3}
return obj
here i'm try to hit multiple serializer objects but got null data in serializer.data
Output
[
{},
{},
{}
]

You are initializing your serializer with many=True, so it is expecting a list of objects. You should either pass in a list of objects as the first argument to the serializer class constructor or remove the many=True kwarg.
Also, since you are passing in a dictionary, I would use the data={...} kwarg instead of the first argument which is instance.
As a quick test, you can perform the following modification:
obj = self.get_objects(order_id)
serializ = CarrGetOrderDetails(obj, many = True)
obj = self.get_objects(order_id)
serializ = CarrGetOrderDetails(data=[obj], many = True)
References
DRF Serializer Documentation
serializers.py:BaseSerializer

Related

SerializerMethodField and circular import

I need help with REST Framework. I have to do my test for internship position and I have two models with circular import 'Pokemon' model and 'Team' mode. In serializer of 'Team' I have this code
class TeamDetailsSerializer(ModelSerializer):
"""Serializer for details of Team instances"""
pokemon_1 = SerializerMethodField()
pokemon_2 = SerializerMethodField()
pokemon_3 = SerializerMethodField()
pokemon_4 = SerializerMethodField()
pokemon_5 = SerializerMethodField()
trainer = UserSerializer()
class Meta:
model = Team
fields = (
"trainer",
"name",
"pokemon_1",
"pokemon_2",
"pokemon_3",
"pokemon_4",
"pokemon_5",
)
read_only_fields = ("id",)
# Methods to relate each Pokemon object
def get_pokemon_1(self, obj):
pokemon_1 = obj.pokemon_1
if not pokemon_1:
return None
serializer = pokemon.serializers.PokemonDetailsSerializer(pokemon_1)
return serializer.data
def get_pokemon_2(self, obj):
pokemon_2 = obj.pokemon_2
if not pokemon_2:
return None
serializer = pokemon.serializers.PokemonDetailsSerializer(pokemon_2)
return serializer.data
def get_pokemon_3(self, obj):
pokemon_3 = obj.pokemon_3
if not pokemon_3:
return None
serializer = pokemon.serializers.PokemonDetailsSerializer(pokemon_3)
return serializer.data
def get_pokemon_4(self, obj):
pokemon_4 = obj.pokemon_4
if not pokemon_4:
return None
serializer = pokemon.serializers.PokemonDetailsSerializer(pokemon_4)
return serializer.data
def get_pokemon_5(self, obj):
pokemon_5 = obj.pokemon_5
if not pokemon_5:
return None
serializer = pokemon.serializers.PokemonDetailsSerializer(pokemon_5)
return serializer.data
and problem that I get this kind of schema
name* [...]
trainer* User{...}
pokemon_1 integer
nullable: true
pokemon_2 [...]
pokemon_3 [...]
pokemon_4 [...]
pokemon_5 [...]
but I would like to get object type, what kind of solutions I can apply?
Thank a lot

insert nested relationships in DB django

Need help , i am trying to push nested relations inside DB don't know where I am going wrong in this, is there something wrong with validated_data , which is a list of dict here , thanks in advance
class CatalogSerializer(serializers.ModelSerializer):
catalog_products = CatalogProductsSerializer(source = 'catalogproducts_set',many=True)
class Meta:
model = Catalog
fields = ['created_by','client','catalog_products','created_datetime','is_active']
def create(self,validate_data):
client_id = validate_data.pop('id')
client = User.objects.get(id=client_id),
catalog_obj = Catalog.objects.create(
client = client,
created_by = self.context['user'],
is_active =True,
)
for pricelist_ins in validate_data:
CatalogProducts.objects.create(
catalog = catalog_obj,**pricelist_ins)
return catalog_obj
Basic Viewset
class CatalogViewset(viewsets.ModelViewSet):
queryset = Catalog.objects.all()
serializer_class = CatalogSerializer
permission_classes = []
authentication_classes = []
def create(self, request, *args, **kwargs):
if request.data:
try:
serialized_data = self.get_serializer(data = request.data)
if serialized_data.is_valid(raise_exception=True):
serialized_data.save()
return Response(serialized_data.data,status=200)
except Exception as e:
return Response({'error':str(e)},status=400)
return Response({'status':'invalid request'},status=400)
the error I am getting in Postman
{
"error": "{'catalog_products': [ErrorDetail(string='This field is required.', code='required')]}"
}
data i am posting
{
"id":"2",
"pricing_list":[
{
"from_quantity":"101",
"to_quantiy":"34",
"price":"1000"
},
{
"from_quantity":"10",
"to_quantiy":"501",
"price":"2000"
}
]
}
You have catelogue_products in the fields, it is by default required. But you are not posting any catelogue_products. You need to post data based on the fields of the serializer. validated data will not contain any other data, but valid data that was set in serializer.
To make it optional you may try to add required=False in the serialzier like this:
class CatalogSerializer(serializers.ModelSerializer):
catalog_products = CatalogProductsSerializer(source = 'catalogproducts_set',many=True, required=False)
class Meta:
model = Catalog
fields = ['created_by','client','catalog_products','created_datetime','is_active']

Search filter not working in Rest framework

A search filter was working fine in this and there's a need to filter out the list with a user-defined distance and for that, a get function is written. Now, the filter is gone. It is appearing when I comment out the get functions.
class ServiceProviderList(generics.ListAPIView):
queryset = ProfileCompletion.objects.all()
serializer_class=ProfilecompletioneSerializer
filterset_class=SnippetFilter
filter_backends = [DjangoFilterBackend,SearchFilter]
filterset_fields = ['fullname', 'category','departments','services']
search_fields = ['fullname', 'category__name','departments__dept_name','services__service_name']
def get(self,request,*args, **kwargs):
pk=self.kwargs.get('pk')
customer = CustomerProfile.objects.get(user=pk)
Dist = request.GET.get("distance")
rad=float(Dist)
radius=rad/111
print(radius)
query = ProfileCompletion.objects.filter(location__distance_lte=(customer.location,radius))
serializer = ProfilecompletioneSerializer(query,many=True)
data = serializer.data
return Response({"message":"Listed Successfully.","data":data})
You are lossing all the functionalities because you are overriding the wrong method. Instead of get() method, you should override get_queryset method:
class ServiceProviderList(generics.ListAPIView):
queryset = ProfileCompletion.objects.all()
serializer_class=ProfilecompletioneSerializer
filterset_class=SnippetFilter
filter_backends = [DjangoFilterBackend,SearchFilter]
filterset_fields = ['fullname', 'category','departments','services']
search_fields = ['fullname', 'category__name','departments__dept_name','services__service_name']
def get_queryset(self,*args, **kwargs):
qset = super().get_queryset(*args, **kwargs)
pk=self.kwargs.get('pk')
customer = CustomerProfile.objects.get(user=pk)
dist = self.request.GET.get("distance")
rad=float(dist)
radius=rad/111
return qset.filter(location__distance_lte=(customer.location,radius))

How to return additional information outside an array, in a list serializer

I have the following serializer :
class SalesProjectListSerializer(serializers.ModelSerializer):
permissions = serializers.SerializerMethodField('get_custompermissions',read_only=True)
class Meta:
model = SalesProject
fields = ['sales_project_id', 'sales_project_name',
'sales_project_est_rev', 'project_status','permissions']
depth = 2
def get_custompermissions(self, obj):
permission_list = ['add_salesproject']
user_perms = User.get_user_permissions(self.context['request'].user)
return { permission: True if permission in user_perms else False for permission in permission_list }
This serializer is used to serialize the data thats used to render the project listing page.
The serialized data would give me something like :
projects = [{sales_project_id : 1 , sales_project_name = 'test , ... ,permissions: [...]}]
However instead what i wish to return is somthing like this :
projects = {projects:[{sales_project_id : 1 , sales_project_name = 'test , ... }]
,permissions: [...]}
You cand override the method responsible for the response depending on your View type.
I assume you are using a ListAPIView so this is how you would do it:
class YourView(ListAPIView):
model = SalesProject
serializer_class = SalesProjectListSerializer
def list(self, request, *args, **kwargs):
serializer = self.get_serializer(self.get_queryset(), many=True)
# change the data
# serializer.data is the response that your serializer generates
res = {"projects": serializer.data}
return Response(res)
It's the same for other views such as RetrieveAPIView but you should override the retrieve method instead.

Use Django Filters in ModelViewSet which return serializer data

I want to combine 2 models: City and Country in order to have a filter like this: http://localhost:8000/api/v1/geo/location-search/?name=Santa+Fe
I have a ModelViewSet which return serializer data like this:
class LocationSearchAPI(ModelViewSet):
queryset = City.objects.all().order_by('name')
permission_classes = [AllowAny]
serializer_class = CityListSerializer
filter_backends = (DjangoFilterBackend, SearchFilter)
filter_class = LocationFilter
def get_location_list(self, request):
city_qs = City.objects.all().order_by('name')
country_qs = Country.objects.all().order_by('name')
result_qs = list(chain(country_qs, city_qs))
sorted_list = sorted(result_qs, key=lambda instance: -instance.id)
results = list()
for item in sorted_list:
item_type = item.__class__.__name__.lower()
if isinstance(item, City):
serializer = CityLocaliaztionSrl(item)
if isinstance(item, Country):
serializer = CountryLocaliaztionSrl(item)
results.append({'type': item_type, 'data': serializer.data})
return Response(results, status=200)
and this Filter's not work:
class LocationFilter(FilterSet):
class Meta:
model = City
fields = ('type', 'data__name')
How can I use Django Filters in ModelViewSet which return serializer data, hope your guys help me.