When I use like below
data , error = schema.load( json_data )
data object contains only values not keys but json_data is a valid dict.
and if I just use
MyModel = _mymodel(**json_data)
it works. But if I use below inside of my schema
#post_load
def create_model(self, data):
return MyModel(**data)
I get error
AttributeError: 'MyModel' object has no attribute 'get'
Anyone has any idea? Why "data" contains only value and does not return dictionary like the examples stated?
Thanks
According to documentation here there are two methods similar to each others.
load(data, many=None, partial=None)
Deserialize a data structure to an object defined by this Schema’s fields and make_object().
Another is
loads(json_data, many=None, *args, **kwargs)
Same as load(), except it takes a JSON string as input.
So you need to use loads() instead of load() if you have json data.
Related
I have a field on a schema that should be a specific schema based on a value in that field if it exists. To elaborate, the field should be fields.Dict() if it doesn't contain a version property. Otherwise, the schema should be retrieved from a map
def pricing_schema_serialization(base_object, parent_obj):
# Use dictionary access to support using this function to look up schema for both both serialization directions,
# and test data
if type(base_object) is not dict:
object_dict = base_object.__dict__
else:
object_dict = base_object
pricing_version = object_dict.get("version", None)
if pricing_version in version_to_schema:
return version_to_schema[pricing_version]() # Works fine
return fields.Dict(missing=dict, default=dict) # Produces error
class Product:
# pricing = fields.Dict(missing=dict, default=dict) # This worked
pricing = PolyField(
serialization_schema_selector=pricing_schema_serialization,
deserialization_schema_selector=pricing_schema_serialization,
required=False,
missing=dict,
default=dict,
)
This is the error produced:
{'pricing': ["Unable to use schema. Ensure there is a deserialization_schema_selector and that it returns a schema when the function is passed in {}. This is the class I got. Make sure it is a schema: <class 'marshmallow.fields.Dict'>"]}
I saw that marhmallow 3.x has a from_dict() method. Unfortunately, we're stuck on 2.x.
Things I tried:
The code above
Creating my own from_dict class method following the same implementation here. Same result
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']
I am creating an API using marshmallow for the data validation.
the data is given to the schema in JSON:
data = request.get_json()
schema = ItemSchema()
evaluated = schema.load(data)
if evaluated.errors:
return {'message': evaluated.errors}, 400
The schema has field validation methods which are decorated with the #validates decorator:
#validates('name')
def validate_name(self, name):
existing_item = ItemModel.name_exists(name) #returns an object of type Item if the name exists. Names are unique
if existing_item and existing_item._id != data['_id']:
raise ValidationError('Item already exists.')
As in this example i would like to access the data dictionary which is passed via the load function. How can i access the data object inside the validation method of the schema?
Thanks for your help!
To answer your question, you can use a schema validator with the #validates_schema decorator. It has a pass_original parameter.
#validates_schema(pass_original=True)
def validate_name(self, data, input_data):
existing_item = ItemModel.name_exists(data['name'])
if existing_item and existing_item._id != input_data['_id']:
raise ValidationError('Item already exists.')
But frankly, I think your use case is wrong.
If it is an item creation (POST), just check whether the name already exists.
If it is an item modification (PUT), you know the ID from the request path. And you should be able to access it from your object.
Also, if I may suggest, you could use webargs (maintained by marshmallow maintainers) to parse request with marshmallow easily.
I have the following ListView
import json
class CountryListView(ListView):
model = Country
def render_to_response(self, context, **response_kwargs):
return json.dumps(self.get_queryset().values_list('code', flat=True))
But I get following error:
[u'ae', u'ag', u'ai', u'al', u'am',
u'ao', u'ar', u'at', u'au', u'aw',
u'az', u'ba', u'bb', u'bd', u'be', u'bg',
u'bh', u'bl', u'bm', u'bn', '...(remaining elements truncated)...']
is not JSON serializable
Any ideas ?
It's worth noting that the QuerySet.values_list() method doesn't actually return a list, but an object of type django.db.models.query.ValuesListQuerySet, in order to maintain Django's goal of lazy evaluation, i.e. the DB query required to generate the 'list' isn't actually performed until the object is evaluated.
Somewhat irritatingly, though, this object has a custom __repr__ method which makes it look like a list when printed out, so it's not always obvious that the object isn't really a list.
The exception in the question is caused by the fact that custom objects cannot be serialized in JSON, so you'll have to convert it to a list first, with...
my_list = list(self.get_queryset().values_list('code', flat=True))
...then you can convert it to JSON with...
json_data = json.dumps(my_list)
You'll also have to place the resulting JSON data in an HttpResponse object, which, apparently, should have a Content-Type of application/json, with...
response = HttpResponse(json_data, content_type='application/json')
...which you can then return from your function.
class CountryListView(ListView):
model = Country
def render_to_response(self, context, **response_kwargs):
return HttpResponse(json.dumps(list(self.get_queryset().values_list('code', flat=True))),mimetype="application/json")
fixed the problem
also mimetype is important.
I'm trying to use the ValuesQuerySet feature in Django to limit the number of fields returned from query to only those I need. I would like to serialize this data set a JSON object However, Django keeps throwing an error. Below I've included my code and the error I receive:
objectList = ConventionCard.objects.values('fileName','id').filter(ownerUser = user)
data = serializers.serialize('json', objectList)
return HttpResponse(data, mimetype='application/javascript')
The Error:
Exception Type: AttributeError
Exception Value: 'dict' object has no attribute '_meta'
Exception Location: C:\Python27\lib\site-packages\django\core\serializers\base.py in serialize, line 41
Thanks !
Cast the ValuesQuerySet to a list first:
query_set = ConventionCard.objects.values('fileName','id').filter(ownerUser = user)
list(query_set)
Removing the values call as suggested by ars causes the manager to pull all columns from the table, instead of only the two you need.
Try subsetting the fields in your values list through the serialize method using a QuerySet instead:
from django.core import serializers
objectQuerySet = ConventionCard.objects.filter(ownerUser = user)
data = serializers.serialize('json', objectQuerySet, fields=('fileName','id'))
I continued to get a dict object has no attribute _meta error when using the list() method above. However I found this snippet that does the trick
def ValuesQuerySetToDict(vqs):
return [item for item in vqs]
# Usage
data = MyModel.objects.values('id','title','...','...')
data_dict = ValuesQuerySetToDict(data)
data_json = simplejson.dumps(data_dict)
Just to add a few details I've found:
When I tried #ars answer specifying the fields, like:
s_logs = serializers.serialize("json", logs, fields=('user', 'action', 'time'))
I get this:
[{"pk": 520, "model": "audit.auditlog", "fields": {"user": 3, "action": "create", "time":"2012-12-16T12:13:45.540"}}, ... ]
Which was not a simple serialization of the values as I wanted it.
So I tried the solution proposed by #Aaron, converting the valuesqueryset to a list, which didn't work the first time because the default encoder cannot deal with floats or datetime objects.
So I used #Aaron solution but using the JSON encoder that is used by django's serializer (DjangoJSONEncoder) by passing it as a kwarg to simplejson.dumps(), like this:
s_logs = list(logs.values('user', 'ip', 'object_name', 'object_type', 'action', 'time'))
return HttpResponse(simplejson.dumps( s_logs, cls=DjangoJSONEncoder ), mimetype='application/javascript')