How I can get the queryset created and passed by a view in the serializer - django-rest-framework

I have a review model which has a large data so, first I do some filtration based on the date range and other things, I did it like this:
class ProgressView(generics.ListAPIView):
"""
Return a list of all Feedback reviews for progress.
"""
serializer_class = ReviewProgressSerializer
filterset_class = ProgressFilter
pagination_class = UnlimitedPagination
def get_queryset(self):
return Review.objects.filter(division__pk=self.kwargs['division_pk'])
Now, I want to do some calculations based on this filtered queryset in the serializer and return this info along with the serialized data, the problem is, I don't know how to get this queryset in the serializer or should I do it in view.
Please note that I need to do both things, serialize the review data and return the calculations too in the same response.
So, my question is how to access the queryset created by view in serializer or should I do that in another place or what.
Thank you

I figured it out, you can access your current queryset that being serialized from your serializer by self.instance

Related

many to many field in django view

I try to write a view user create paper trading,I have some assets in my site,now when user create paper trading have to choose from that assets,but cant create and have an error
# -------------------- Create Paper_Trading View --------------------
class CreatePaperTradingApiView(viewsets.GenericViewSet):
permission_classes = (IsAuthenticated,)
"""
create a paper_trading for request.user
"""
serializer_class = PaperTradingSerializer
#action(methods=['POST'], detail=True, url_name='paper', url_path='paper')
def create_paper_trading(self, request, pk=None):
data = request.data
symbol = Assets.objects.get(id=pk).core_key
user_id = request.user.pk
if not PaperTrading.objects.filter(user=user_id, status='OPENED').filter(assets__core_key=symbol).exists():
queryset = PaperTrading.objects.create(
user_id=user_id,
average_price=data['average_price'],
quantity=data['quantity'],
status='OPENED',
side=data['side']).assets.set(Assets.objects.filter(core_key=symbol))
queryset = PaperTrading.objects.filter(user=user_id, status='OPENED').filter(assets__core_key=symbol)
serializer = PaperTradingSerializer(queryset, many=True)
return Response(serializer.data)
return Response(data={'result': 'This symbol opened.'})
I took assets from list of asset that is many to many field
The error is
"<PaperTrading: PaperTrading object (None)>" needs to have a value for field "id" before this many-to-many relationship can be used.
I will assume the Many to many relationship is Assets to PaperTrading (it would be good to see your models otherwise. Try:
new_instance = PaperTrading.objects.create(
user_id=user_id,
average_price=data['average_price'],
quantity=data['quantity'],
status='OPENED',
side=data['side'],
)
new_instance.assets.set(Assets.objects.filter(core_key=symbol))
...
My thought is that you firstly need to create the object before you assign its' M2M.

How to serialize multiple query set to json Response in django rest frame work

I am getting a list of committees by user using a get method in which I am sending a user id but I am getting an error Committee object is not serialize I have serializer created but I dont't know how to serializer the queryset of that particular user id result.
below is my views.py file
def get(self, request, user_id):
get_committees = Committee.objects.filter(user=Profile.objects.get(id=user_id))
data = {
"status": "success",
"data":get_committees
}
res = Response(serializer.data, status=status.HTTP_200_OK)
below is my serializer.py
class MyCommitteesSerializer(serializers.ModelSerializer):
def get_queryset(self, user_id):
my_committees =
Committee.objects.filter(user=Profile.objects.get(id=user_id))
return my_committees
from your code in get method
"data":get_committees
this get_committees is a list and you are trying to return a list but you can only return json, and so you are getting the message.
You can do this in a better way
define your serializer as -
class MyCommitteesSerializer(serializers.ModelSerializer):
class Meta:
model = Committee
fields = ""_all__"
and define your views as -
class MyCommitteesView(generics.ListAPIView):
serializer_class = MyCommitteesSerializer
def get_queryset(self):
queryset = Committee.objects.filter(user=Profile.objects.get(id=self.request.user_id))
return queryset
the serializer will take care of serialization and you can customize this according to your needs.
or else you will have to manually convert your get_committes into json format before returning.

how to get validated data from serializers to views in django rest framework

I am returning some data from def create method in seriaizers.py file I want to acccess that data in views.py I dont know how to get it.
serilizers.py
def create(self, validated_data):
//returning something
return validated_data
views.py
if serializer.is_valid():
serializer.save()
//I want to return that validated_data here so how to get it here here
Response(validated_data)
To get the validated data, use serializer.validated_data. See the Deserializing Objects section of the manual.
Also, I want to point out a potential footgun here: you're supposed to return a model instance, from the create() method, rather than the validated data.

Accessing ViewSet object list to provide extra context to serializer

I am attempting to add context to a serializer within a ModelViewSet which is dependent on the current paged object list in context. I'll explain with an example.
I am building a viewsets.ModelViewSet that lists Users and a list of favorite_foods. However- the list of user's favorite foods in some external microservice accessible via API. Building a ViewSet to collect objects and performing HTTP requests on each is trivial, we can do something like this:
class UserViewSet(viewsets.ViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserSerializer(serializers.ModelSerializer):
favorite_foods = serializers.SerializerMethodField()
def get_favorite_foods(self, instance):
# performs an HTTP call and returns a list[] of foods.
return evil_coupled_microservice_client.get_user_food_list(instance)
class Meta:
model = User
fields = ('id', 'name', 'favorite_foods')
The issue is (aside from some ugly infrastructure coupling) this is going to make an HTTP request count equivalent to the page size. Instead- it would be great if I could prefetch the favorite food lists for all users on the page in a single HTTP call, and just add them into context, like this:
class UserViewSet(viewsets.ViewSet):
def get_serializer_context(self):
context = super().get_serializer_context()
users = <-- This is where I want to know what users are in the current filtered, paginated response.
users_food_dict = evil_coupled_microservice_client.get_many_users_food_list(users)
context.update({'usesr_foods': users_food_dict})
return context
However- it doesn't appear there is any way to fetch the object list that's going to be serialized. Although (I'm fairly sure) get_serializer_context is called after the queryset is filtered and paginated, I'm not sure how to access it without doing some really hacking re-compiling of the queryset based on the query_params and other pieces attached to the class.
I'll post my current solution. It's not terrible, but I'm still hoping for a cleaner built-in.
class UserViewSet(viewsets.ViewSet):
...
def list(self, request, *args, **kwargs):
# Overrwite `ListModelMixin` and store current set
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
self.current_queryset = page
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
self.current_queryset = queryset
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
This is untested so far (not sure about functionality on Detail endpoints for instance) allows for the current_queryset to be fetched within the serializer context.

How to programmatically provide `queryset` to PrimaryKeyRelatedField in DRF 3

In order to have a non-readonly PrimaryKeyRelatedField, you are required to provide a queryset that contains valid options.
How can I properly populate that queryset based on the current request (user)?
The key is to subclass PrimaryKeyRelatedField and overload the get_queryset method, using the user information from the request context:
class UserFilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
request = self.context.get('request', None)
queryset = super(UserFilteredPrimaryKeyRelatedField, self).get_queryset()
if not request or not queryset:
return None
return queryset.filter(user=request.user)
You can then use this new serializer just like the (unfiltered) original:
class MySerializer(serializers.ModelSerializer):
related = UserFilteredPrimaryKeyRelatedField(queryset=MyModel.objects)
Whenever the serializer accesses the queryset, it will be filtered such that only objects owned by the current user are returned.
View has a
self.request.user
attribute which you can then use to fetch user related queryset
eg
queryset = Products.objects.get(customer=self.request.user)

Resources