How to deserialize base64-encoded data and use it with DRF - python

My goal is to come up with an endpoint that gets a base64-decoded string.
This is based described by an example
My input JSON looks like this:
{
"encoded_data": "a2F0aWUsIGpvaG5zLCBrYXRpZUBnbWFpbC5jb20KdG9tbXksbGVlLHRvbW15QGdtYWlsLmNvbQ=="
}
I have tried to implement it the following way, but I end up with the following error message:
JSON parse error - Expecting value: line 1 column 1 (char 0)
Looks like I've messed up the concepts. Really need help on this:
class UsersFileUpload(APIView):
#parser_classes = (MultiPartParser,)
def post(self, request):
stream = base64.b64decode(request.data['encoded_data'])
stream = io.BytesIO(stream)
data = JSONParser().parse(stream)
serializer = UsersSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

I don't think you're decoding your text correctly, you shouldn't need to use BytesIO.
You should decode the byte string returned from b64decode and then pass it to the JSONParser.
b64decoded_data = base64.b64decode(request.data['encoded_data']).decode('UTF-8')
data = JSONParser().parse(b64decoded_data)

Related

Django Rest Framework parser does not accept string as valid JSON

I'm sending some data to Django Rest Framework backend with Content-Type set as application/json.
If I try to send any JSON that is shaped like a typical nested key-value object, everything works fine.
But if I want to send a simple string like test, I get a 400 Bad request due to malformed JSON : JSON parse error - Expecting value: line 1 column 1 (char 0).
But aren't strings valid JSON values according to RFC 8259 ?
I don't understand from the official DRF documentation if this is a normal feature for Django JSON Parser or if I'm doing something wrong somewhere ?
The class-based view that I'm using is ListCreateAPIView:
class ObjectList(ListCreateAPIView):
"""
View dedicated to GET a list of instances or POST a new one
"""
serializer_class = MySerializer
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get_queryset(self):
# Filter objects based on user identity (token based)
queryset = MyObject.objects.filter(user=self.request.user)
return queryset
def post(self, request, format=None):
transect_data = request.data # Returns 400 Bad request
The piece of code that send data to the server (JS using Axios)
…
return axios
.post(API_URL + 'create/',
"test",
{
headers: headers,
}
)
.then(response => {
return response.data;
})
.catch((error) => {
console.log(error);
});
You can pass any JSON value [json.org], so that includes a string, but a string is put between double quotes ("…") and some characters should be escaped, so you send "test", not test.
test itself is not a valid JSON value. Indeed, you can check for example with the Online JSON valiator [jsonlint.com] if a JSON blob is valid JSON.
A string literal is, just like for example in Python and JavaScript thus put in an "envelope" of double quotes, and escapes certain characters such that if the string itself contains a double quote, that character is escaped properly.

Django: custom Action with date parameter not working

I have the following code in Python Django:
#action(detail=True, methods=['get'], url_path=r'by_date')
def get_meal_by_date(self, request, meal_date=date.today):
print(meal_date)
meals_by_date = Meal.objects.filter(
owner=self.request.user,
mealTimestamp__day=meal_date.day,
mealTimestamp__month=meal_date.month,
mealTimestamp__year=meal_date.year
)
serializer = self.get_serializer(meals_by_date, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
That Code works on call it like this:
http://localhost:8000/meals/by_date/
My problem is how can I enrich the method to gets data back with date parameter.
For example with this call:
http://localhost:8000/meals/by_date/2022-03-16T21:30:45.290Z/
What is your problem exactly, are you passing in the date in the url? That should work.
path('adress/date:date/', something like this. In your view get the date.

problem with 'QueryDict' object is not callable

class PreUpdateDeleteAPIView(APIView):
serializer_class = PreEditSerializer
queryset = Reserve.objects.all()
def post(self, request):
code = request.data()
"""''.join(code)"""
data = {
reverse('update-delete', args = [code] ,request=request)
}
return Response(data)
hello. i have an problem for converting querydict to string. what should i do now?
i have tried json.dump and several answers in SOF. but i didnt get my answer yet!
request.data is a property that returns a QueryDict, so you work with:
code = request.data
It however makes no sense to specify args=[code], since code is a dictionary-like structure.
Likely you need some value that corresponds to some key from the request.data, so something like:
code = request.data['code']

Python convert python-amazon-simple-product-api results to json using Django

I am writing an API in Python Django and rest framework. I am using a python packaged called python-amazon-simple-product-api to access amazon advertising API. I am trying to feed the results into the rest framework and return the results as JSON Here is my code so far.
class AmazonProductsViewSet(viewsets.ViewSet):
def list(self, request, format=None):
products = amazon.search(Brand="Microsoft", SearchIndex="Software",
ResponseGroup="Images,ItemAttributes,Accessories,Reviews,VariationSummary,Variations")
products = list(products)
With this code I get the following error;
TypeError: Object of type 'AmazonProduct' is not JSON serializable
So I am trying to find a way of making the AmazonProduct object serializable or a better solution.
Not JSON serializable means that your response is an object not a primitive data that can be sent over a network.
You need to write a serializer for that model. Something like this:
class AmazonProductSerializer(serializers.Serializer):
color = serializers.CharField()
title = serializers.CharField()
and use it like this:
products = amazon.search(Brand="Microsoft", SearchIndex="Software", ResponseGroup="Images,ItemAttributes,Accessories,Reviews,VariationSummary,Variations")
data = AmazonProductSerializer(products, many=True).data
return Response(data, status=status.HTTP_200_OK)
Hope it helps!
Probably the best approach is to use the bottlenose [ https://github.com/lionheart/bottlenose ] instead if you just want to get the amazon results as they're and convert to JSON. Here is how I have done it;
amazon = bottlenose.Amazon(access_key_id, secret_key, associate_tag)
class AmazonProductsViewSet(viewsets.ViewSet):
def list(self, request, format=None):
response = amazon.ItemSearch(Keywords="Kindle 3G", SearchIndex="All")
return Response(xmltodict.parse(response)) #json.dumps(xmltodict.parse(response))
Now I get the entire XML document as JSON.

Serialization is returning each character as object

I have a simple view, in which I need to return JSON data but when using django serialize and JsonResponse it returns each character as an object. Here is the snippet:
def query(request):
data = serializers.serialize('json', Post.objects.all())
response = JsonResponse(data, safe=False)
return response
The problem is that if I want to print response.content[0] it returns some random number as it's the first character of the response.
Is there any way I can make the response to be accessed like a simple dictionary (JSON)?
Once you have a JSON, it's basically a string - so you can not access it like a dictionary/list or any Python type.
If you need to access it like a dictionary or a list, you should operate on the non serialized data:
def query(request):
posts = Post.objects.all()
print(posts[0]) # You can now use it as a list of objects
data = serializers.serialize('json', posts)
response = JsonResponse(data, safe=False)
return response

Categories

Resources