Access Json object name - json

I want to get data with request.data.columns in frontend.I can do it with ViewSet with list method but how to do it with generics.APIView.
Below is my viewsets and generics code:
class TestList(viewsets.ViewSet):
queryset = Test.objects.all()
def list(self,request):
serializer = TestSerializer(self.queryset, many = True)
return Response({'columns': serializer.data})
class TestList(generics.RetriveAPIView):
queryset = Test.objects.all()
serializer_class = TestSerializer

class TestList(APIView):
queryset = Test.objects.all()
def list(self,request):
serializer = TestSerializer(self.queryset, many = True)
return Response({'columns': serializer.data})
change your urls.py like this.
path(r"url", TestList.as_view({"get": "list"}))

Correct code:
class TestList(APIView):
queryset = Test.objects.all()
def list(self,request):
queryset = self.get_queryset()
serializer = TestSerializer(queryset, many = True)
return Response({'columns': serializer.data})
Details about why i had to add queryset = self.get_queryset() instead of directly access self.queryset.From official drf documentation:
queryset - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the get_queryset() method. If you are overriding a view method, it is important that you call get_queryset() instead of accessing this property directly, as queryset will get evaluated once, and those results will be cached for all subsequent requests.

Related

DJANGO ListView returns HTTPResponse, but I need a json

I am having a problem around the Class Based Views in Django. I need to create JSON responses, instead of rendering to a template.
class AllItem(ListView):
model = MyModel
context_object_name = 'items'
template_name = 'mymodel/index.html'
I also have a serializer class
class SpendingConfigSerializer(serializers.ModelSerialier):
class Meta:
model = SpendingConfig
fields = ('record_date', 'amount', 'name')
Does anyone know how to connect them?
Thanks
Z.
You can make use of a ListAPIView and specify your SpendingConfigSerializer as serializer:
from rest_framework import generics
class UserList(generics.ListCreateAPIView):
queryset = SpendingConfig.objects.all()
serializer_class = SpendingConfigSerializer

Incomplete json structure - no count/next/previous/results field

like many times before, im trying to send data from my Django backend to my Ionic mobile app.
This time, however, for some reason, the .jsons im parsing are coming out incomplete.
A complete .json:
{"count":1,"next":null,"previous":null,"results":[{"codigo":"qwe","area":"ewq","especies":[],"id":1}]}
My incomplete .json:
[{"nome_ficheiro":"1520529086252.jpg","id":26,"especie":"Ameijoa Branca","zona":"L6","data":"09/06/2018"}]
IONIC is struggling with identifying what I'm parsing as a .json, which makes sense since there is no "results" field.
Here are the relevant snippets of my django code:
Views.py (both Views are doing the same thing! This is just me trying out different approaches!)
class resultUploadViewSet(viewsets.ViewSet):
def list(self, request, nome_ficheiro):
queryset = labelResult.objects.all()
nome = nome_ficheiro
answer = queryset.filter(nome_ficheiro=nome)
serializer = resultSerializer(answer, many=True)
return Response(serializer.data)
class resultUploadView(APIView):
serializer_class = resultSerializer
def get(self, request, nome_ficheiro):
queryset = labelResult.objects.all()
nome = nome_ficheiro
answer = queryset.filter(nome_ficheiro=nome)
serializer = self.serializer_class(answer, many=True)
return Response(serializer.data)
Models.py
class labelResult(models.Model):
nome_ficheiro = models.CharField(max_length=120)
especie = models.CharField(max_length=120)
zona = models.CharField(max_length=120)
data = models.CharField(max_length=120)
Urls.py
urlpatterns = [
url(r'results/(?P<nome_ficheiro>.+)/$', resultUploadViewSet.as_view({'get': 'list'})),
url(r'results1/(?P<nome_ficheiro>.+)/$', resultUploadView.as_view())]
Serializers.py
class resultSerializer(serializers.ModelSerializer):
class Meta:
model = labelResult
fields = ('nome_ficheiro','id','especie','zona', 'data')
Any idea why my .jsons are coming out incomplete?
you should use ListAPIView so the pagination is applied.
http://www.django-rest-framework.org/api-guide/generic-views/#listapiview
more on pagination you can find here:
http://www.django-rest-framework.org/api-guide/pagination/

django rest framework - request context key error

I have two models (Like and News). I am using django-rest-framework to make a web api out of it.
class Like(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
class News(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=150)
...
likes = GenericRelation(Like)
A Like object has its own user field to store who liked the News object. Now to check if a specific user exists in any of the likes of a News object, I am getting request.user from a SerializerMethodField.
class NewsSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
likes_count = serializers.IntegerField(source='likes.count', read_only=True)
user_in_likes = serializers.SerializerMethodField()
class Meta:
model = News
fields = ('user', 'title', 'body', 'article_image', 'pub_date', 'likes_count', 'user_in_likes')
def get_user_in_likes(self, obj):
user = self.context['request'].user
what = obj.likes.filter(user=user).exists()
return what
When I go the /news/ url, I get the json objects including the user_in_likes to true/false for each news object.
However, I have another serialzer for different model which imports NewsSerializer class and other similar serializers:
class ActivityObjectRelatedField(serializers.RelatedField):
def to_representation(self, value):
if isinstance(value, User):
serializer = UserSerializer(value)
elif isinstance(value, Job):
serializer = JobSerializer(value)
elif isinstance(value, News):
serializer = NewsSerializer(value)
elif isinstance(value, Tender):
serializer = TenderSerializer(value)
else:
raise Exception('Unexpected type of tagged object')
return serializer.data
class ActivitySerializer(serializers.HyperlinkedModelSerializer):
actor = ActivityObjectRelatedField(read_only=True)
target = ActivityObjectRelatedField(read_only=True)
class Meta:
model = Activity
fields = ('url', 'actor', 'verb', 'target', 'pub_date')
Now if I visit /activities/, to get the activities objects I am getting an error:
KeyError at /activities/
'request'
And it points to the line of SerializerMethod of NewsSerialize class where self.context['request'].user is used.
Exception Location: /vagrant/myproject/news/serializers.py in get_user_in_likes, line 25
Again if I visit /news/ url, everything is fine and I get news objects. What am I missing here? Why is request not being recognized in the ActivitiesSerializer class? Please help me solve this problem. Thank you.
You are getting this error because you are not passing request in the context when instantiating the NewsSerializer class or other similar serializers in the to_representation() method.
You are manually instantiating the particular serializer class in to_representation() method. So, after instantiation, that particular serializer does not have access to ActivitySerializer's context thereby leading to the error.
You can pass the ActivitySerializer's context during instantiation of the relevant serializer in the to_representation() method.
class ActivityObjectRelatedField(serializers.RelatedField):
def to_representation(self, value):
if isinstance(value, User):
serializer = UserSerializer(value, context=self.context) # pass context
elif isinstance(value, Job):
serializer = JobSerializer(value, context=self.context) # pass context
elif isinstance(value, News):
serializer = NewsSerializer(value, context=self.context) # pass context
elif isinstance(value, Tender):
serializer = TenderSerializer(value, context=self.context) # pass context
else:
raise Exception('Unexpected type of tagged object')
return serializer.data
It seems like you don't populate the context dictionary of NewsSerializer with your request in the /activities/ view.
You probably use a class based view provided by Django REST Framework which populates this dictionary for you (see the get_serializer_context() method) and passes it to the Serializer instance. That's why it's automatically available to your serializer in your /news/ view.
In your /activities/ view, though, the context is passed to ActivitySerializer and isn't (automatically) propagated further from there. That's why there's no request key in your context dictionary of NewsSerializer. You would need to pass your request object to the NewsSerializer instance. To pass extra context to a Serializer you can add a context parameter containing a dictionary when instantiating (see the DRF documentation).

Using Django Rest Framework > 2.4 to get children of parent with #detail_route

I had this working great less than DRF 2.4, but the change to 2.4+ uses #detail_route.
When I do a GET to /api/parent/7/children I expect to get all the children that belong to Parent 7.
But I'm getting an empty array.
Here's my code:
class ParentViewSet(viewsets.ModelViewSet):
serializer_class = ParentSerializer
model = models.Parent
#detail_route()
def children(self, request, pk):
parent = self.get_object()
children = parent.children.all()
serializer = ChildrenSerializer(children)
return Response(serializer.data)
def get_queryset(self):
if self.request.user.is_superuser:
return models.Parent.objects.all()
else:
return models.Parent.objects.filter(user=self.request.user)
def pre_save(self, obj):
obj.user = self.request.user
When I go to the endpoint /api/parent/7/children in the API viewer the response I get is:
{
"detail": "Not found"
}
Any suggestions?
I like this better in principle, you can be much more declarative about what is happening. I know I can set methods on children so I don't have to do a #link and #action for the same resource. Just need to get past this hurdle.
Thanks!
I don't know if this is your issue or not, but you have a typo in the example as presented...
children = parent.children.all()
serializer = ChildrenSerializer(Children)
Should be:
children = parent.children.all()
serializer = ChildrenSerializer(children)
You're passing the Children class to be serialized, not the children instance.

Django REST: ContentNotRenderedError when checking JSON object before rendering

I have a Django model, Note, which has a class-based view. It is supposed to return a JSON object upon the appropriate query.
Before returning the object, however, I would like to check that the user field in the note object matches the user currently logged in. (Users should not be able to access Note objects that are not their own.) To do this, I tried rewriting the get() method, calling on self.retrieve() to inspect the object before returning it:
class NoteDetail(generics.RetrieveUpdateDestroyAPIView):
model = Note
serializer_class = NoteSerializer
permission_classes = (permissions.IsAuthenticated,)
renderer_classes = (JSONRenderer,)
def get(self, request, *args, **kwargs):
current_user = User.objects.get(pk=self.request.user.id)
note = self.retrieve(request, *args, **kwargs)
if note.author is current_user:
return note
else:
raise PermissionDenied('Note does not belong to authenticated user.')(author=current_user)
However, this returns a ContentNotRenderedError when run: The response content must be rendered before it can be accessed.
Is there a way for me to check the object before returning it? Must I find a workaround?
One potential workaround is to redefine get_queryset(), rather than get() or get_object(). get_queryset() is the function that returns all objects of the relevant model; get_object() narrows down among these given the argument pk.
By overriding get_queryset(), you restrict the potential objects that get_object() can pick. Thus the set is already filtered at the time get() is called.
def get_queryset(self):
current_user = User.objects.get(pk=self.request.user.id)
# Must filter by author to prevent making everyone's notes public
queryset = Note.objects.filter(author=current_user)
return queryset