I'm new to the django rest framework and have two basic questions about something I don't fully understand. I have a python function which takes as an input a dictionary and would like to make it available via an API.
In [24]: def f(d):
...: pass
...:
I'm testing a post request via postman sending a json file which should be translated to my python dictionary. The input I'm sending looks like
{
"test": {
"name1": {
"list": ["a",
"b",
"c"
],
"numbers": [0.0, 0.1]
}
}
}
As you can see this is a dict currently with one key name1 which itself is a dict with two keys, list and numbers.
The view set I wrote for this example looks like this:
class TestViewSet(viewsets.ViewSet):
def create(self, request):
serializer = TestSerializer(data=request.data)
print(type(request.data.get("test")))
if serializer.is_valid():
print(serializer.validated_data.get("test"))
f(serializer.validated_data.get("test"))
and my serializer looks like this:
class TestSerializer(serializers.Serializer):
test = serializers.DictField()
If I send the json input above I get the printed the following:
<type 'dict'>
None
So I have the following two questions:
As we can see the request.data.get("test") is already the desired type (dict). Why do we want to call the serializer and doing some validation. This might cast certain inputs to not standard python types. E.g. validating a decimal via the DecimalField returns a object of type Decimal which is a Django type not a standard python type. Do I need to recast this after calling the serializer or how do I know that this won't cause any trouble with function expecting for example native python float64 type?
How can I define the serializer in the above example for the dictionary so that I get returned the correct object and not None? This dictionary consists of a dictionary consisting of two keys, where one value is a list of decimals and the other a list of strings. How can I write a validation for this within the DictField?
Related
I have a payload that is a list that will contain a variable number of dictionaries and I was hoping to be able to unpack that via a single call to a pydantic model.
Below is an example of what I am trying to accomplish, with two dictionaries:
#!/usr/bin/env python3.9
from pydantic import BaseModel
from typing import List, Dict
class RequestPayload(BaseModel):
site: str
class RequestPayload_unpack(BaseModel):
endpoints: List[Dict, RequestPayload]
payload = [
{
'site': 'nyc01',
},
{
'site': 'lax02',
},
]
request = RequestPayload_unpack(*payload)
print(request)
Running that I get the following error:
raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};"
TypeError: Too many parameters for typing.List; actual 2, expected 1
The workflow that I have working now (not using pydantic) parses/validates each dict in the list and then passes it along to the next step, which will perform additional lookups and then eventually do the work. So right now the model is that the entire RequestPayload is operated upon through the pipeline, versus each dict being treated as a distinct request.
I'm using Django Rest Framework 3.6.3. I'm trying to write nested create serializers for one optional argument and one required argument inside a child. I know that I need to override create in the base serializer to tell DRF how to create the nested children - http://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers.
However, I can't figure out how to get it to parse the object information without telling it what the nested child serializer is defined as. Doing that then causes DRF to use it to parse the children objects, which then returns a validation error that I have no control over because the child serializer doesn't call its create method.
Base
Specification(many=True)
OptionalField
RequiredField
The information I pass in is a JSON object:
{
base_id: 1,
base_info: 'blah'
specifications: [
{
specification_id: 1,
optional_info: {
optional_id: 1,
optional_stuff: 'blah'
},
required_info: {
required_id: 1,
required_stuff: 'required',
}
}
]
}
The BaseCreationSerializer calls it's create method. I know that I need to pull out the rest of the information and create it manually. However, I can't figure out how to get the BaseCreationSerializer to parse the data into validated_data without defining specification = SpecificationCreationSerializer(), which then tries to parse that and throws an error. Printing self shows the entire JSON object in data, but then validated_data only contains the subset of things that the serializer knows about. How do I parse the appropriate things from data so that I can create the objects on my own?
I am trying to serialize a list of objects.
I am making an HTTP API call. The call returns a list of objects (e.g. class A). I do not have access to the definition of class A.
I tried using dumps
print ("Result is: %s", json.dumps(result_list.__dict__))
This prints an empty result. However if I were to print the result_list I get below output
{
"ResultList": [{
"fieldA": 0,
"fieldB": 1.46903594E9,
"fieldC": "builder",
"fieldD": "StringA/StringB-Test-124.35.4.24"
}]
}
IS there a way I can convert the object with whichever field it returns to a json.
Please specify more how the class of which result_list is an instance looks like (e.g. post the class code).
json.dumps(result_list) probably works not since result_list is not a plain dictionary, but an object of a class. You need to dump the variable that holds the data structure (i.e. the same that is displayed in the print call).
I'm creating an API and I need to return data in a dictionnary format sothat it can be serialized (by the API mechanism).
The code that currently works is something as simple as:
def mymethod(self):
queryset1 = MyClass.objects.get(...) # Ccontains 1 object, easy to deal with
queryset2 = OtherClass.objects.filter(...) # Contains N objects, hard to deal with !
return {
'qs1_result': queryset1.some_attribute # This works well
}
Returning data from queryset1 is easy because there is 1 object. I just pick the attribute I need and it works. Now let's say that in addition, I want to return data from queryset2, where there are many objects, and that I don't need every attributes of the object.
How would you do that?
I repeat that I do NOT need to make the serialization myself. I just need to return structured data sothat the serialization can be made.
Thanks a lot.
From the Django docs: https://docs.djangoproject.com/en/dev/topics/serialization/#subset-of-fields
Subset of fields
If you only want a subset of fields to be serialized, you can specify a fields argument to the serializer:
from django.core import serializers
data = serializers.serialize('json', SomeModel.objects.all(), fields=('name','size'))
In this example, only the name and size attributes of each model will be serialized.
I am using ElasticSearch in my Python application and want to be able to create a reusable dictionary object that represents a query. The JSON structures are described here http://pulkitsinghal.blogspot.co.uk/2012/02/how-to-use-elasticsearch-query-dsl.html and I am using PyES to query the search server. With PyES we can pass a dict object which gets jsonified before sending to the server. I want to create a library of common queries where only the actual query term changes, so I thought I would subclass dict so I could pass in the query term via the constructor, for example, and when the dict gets jsonified I would end up with something like this:
{
"fields": [
"name",
"shortDescription",
"longDescription"
],
"query": {
"query_string": {
"fields": [
"name"
],
"query": query_term,
"use_dis_max": true
}
}
}
How would I do this? Is it true that only instance members get returned via __dict__ if so would I have to set up this data structure in the constructor? Is this the best way of doing this or should I create a class that does not extend dict and just create a to_dict() method that returns a dictionary in the correct structure?
Answer:
This seems to work fine, any suggestions for making this more 'pythonic' will be appreciated! (Yes I know there are no doc strings)
class StandardQuery(object):
search_fields = ['meta_keywords', 'meta_description', \
'fields.title.value', 'slug']
return_fields = ['slug', 'fields.title.value']
def __init__(self, query):
self.query = query
def to_dict(self):
output = dict()
output['fields'] = self.search_fields
output['query'] = {'query_string': {'fields': self.return_fields, \
'query': self.query, 'use_dis_max': True}}
return output
If you don't want all of the normal dict behaviour then you should definitely just create a separate class. You can then either give it a to_dict() method, or better since you really want to convert to json create a custom json encoder (and if required decoder) to use with the default argument of json.dumps().
In json.dump() and json.dumps() the optional argument default is a callable that should either return a serialized version of the object or raise TypeError (to get the default behaviour).