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']
Related
I have modified get_queryset() method that looks like this:
def get_queryset(self):
type_of_review = self.request.data['type_of_review']
queryset = Reviews.objects.filter(type_of_review=type_of_review).order_by('-id')[:3]
return queryset
It sorts my models according to the type_of_review field, orders them and retrieves 3 last.
When I was trying to write a unit test to it, I ran into a problem that I cannot find a reliable or working way to pass filter argument into my get_queryset() method.
I tried doing it like this:
def test_list_three_review(self):
self.data = [ReviewsFactory.create() for i in range(10)]
response = self.client.get(self.url2, {"type_of_review": "Team"})
self.assertEqual(response.status_code, status.HTTP_200_OK)
But got an error: test_list_three_review - KeyError: 'type_of_review'
Can somebody explain to me what am I doing wrong?
Will gladly provide any additional information.
Thanks anyway!
OK, so self.client.get takes data which should be a dictionary. I think you want to do the following...
def test_list_three_review(self):
[ReviewsFactory.create() for i in range(10)]
data = {'type_of_review':'Team'}
response = self.client.get(self.url2, data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
Not exactly sure why you want to include a list of objects in the request since your get_queryset method overrides it anyway.
You are passing data as query string parameter. In-order to parse it in view you could use request.GET.get("type_of_review")
your get_queryset() method will become
def get_queryset(self):
type_of_review = self.request.GET.get('type_of_review')
queryset = Reviews.objects.filter(type_of_review=type_of_review).order_by('-id')[:3]
return queryset
GET request is not for passing json data, if you need to pass data as json anyway you could use POST method
then you can pass data like
def test_list_three_review(self):
self.data = [ReviewsFactory.create() for i in range(10)]
data = {"type_of_review": "Team"}
response = self.client.post(self.url2, data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
and your get_queryset method will work as it is.
I have created a test which which would sent a post request to a url and the method called against that request makes few objects, my question is how do i get these created objects ?
def test_post(self):
response = self.c.post('/url/', {'name' : 'postname', 'content' : 'abc'})
while my view logic looks something like
Class MakePost():
def makePost(self, request, data):
object = Class()
object2 = AnotherClass()
return object
def get_success_url(self, request, user):
return '/post/'
You can check your created objects in you test like:
def test_post(self):
response = self.c.post('/url/', {'name' : 'postname', 'content' : 'abc'})
# assume the above call has created an Post and a Category objects. Let's check them out.
category = Category.objects.get(name='category')
post = Post.objects.get(name='postname')
self.assertEqual(post.content, 'abc')
self.assertEqual(post.category, category)
As your database is cleaned before every test_* method and contains no objects (except fixtures if you use any), there would be only one object with that name.
I am quite new to django and recently I have a requirement of a JSON output, for which I use the following django code:
data = serializers.serialize("json", Mymodel.objects.all())
It works great, except that I get a output of:
[{"pk": 8970859016715811, "model": "myapp.mymodel", "fields": {"reviews": "3.5", "title": .....}}]
However, I would like the output to be simply either:
[{"reviews": "3.5", "title": .....}]
or,
[{"id": "8970859016715811", "reviews": "3.5", "title": .....}]
I was wondering if someone could point me to the right direction as to how to achieve this.
You can add 'fields' parameter to the serialize-function, like this:
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))
See: https://docs.djangoproject.com/en/dev/topics/serialization/
EDIT 1:
You can customize the serializer to get only the fields you specify.
From Override Django Object Serializer to get rid of specified model:
from django.core.serializers.python import Serializer
class MySerialiser(Serializer):
def end_object( self, obj ):
self._current['id'] = obj._get_pk_val()
self.objects.append( self._current )
# views.py
serializer = MySerialiser()
data = serializer.serialize(some_qs)
You'll need to write a custom Json serializer. Something like this should do the trick:
class FlatJsonSerializer(Serializer):
def get_dump_object(self, obj):
data = self._current
if not self.selected_fields or 'id' in self.selected_fields:
data['id'] = obj.id
return data
def end_object(self, obj):
if not self.first:
self.stream.write(', ')
json.dump(self.get_dump_object(obj), self.stream,
cls=DjangoJSONEncoder)
self._current = None
def start_serialization(self):
self.stream.write("[")
def end_serialization(self):
self.stream.write("]")
def getvalue(self):
return super(Serializer, self).getvalue()
The you can use it like this:
s = FlatJsonSerializer()
s.serialize(MyModel.objects.all())
Or you could register the serializer with django.core.serializers.register_serializer and then use the familiar serializers.serialize shortcut.
Take a look at the django implementation as a reference if you need further customization: https://github.com/django/django/blob/master/django/core/serializers/json.py#L21-62
I just came across this as I was having the same problem. I also solved this with a custom serializer, tried the "EDIT 1" method but it didn't work too well as it stripped away all the goodies that the django JSON encoder already did (decimal, date serialization), which you can rewrite it yourself but why bother. I think a much less intrusive way is to inherit the JSON serializer directly like this.
from django.core.serializers.json import Serializer
from django.utils.encoding import smart_text
class MyModelSerializer(Serializer):
def get_dump_object(self, obj):
self._current['id'] = smart_text(obj._get_pk_val(), strings_only=True)
return self._current
Sso the main culprit that writes the fields and model thing is at the parent level python serializer and this way, you also automatically get the fields filtering that's already built into django's JSON serializer. Call it like this
serializer = MyModelSerializer()
data = serializer.serialize(<queryset>, <optional>fields=('field1', 'field2'))
import json
_all_data = Reporter.objects. all()
json_data = json.dumps([{'name': reporter.full_name} for reporter in _all_data])
return HttpResponse(json_data, content_type='application/json')
Here Reporter is your Model
I am running into a problem trying to include tastypie resources in a larger json response in a regular django view. I would like to have the view return something like this (based on a queryset generated in the view, not from typical tastypie get params):
{
"success": bool,
"message": string,
"error": string,
"objects": [
{
"field_one": bar,
"field_two": foo
}
... more objects ...
]
}
where objects list is a list of serialized tastypie resources, and success, message and error are coming from somewhere else in the view.
Right now, I can't figure out how to avoid turing the serialized resource into strings before the larger dict gets build, so I have something like this currently:
{
"success": bool,
"message": string,
"error": string,
"objects": [
"{"field_one": bar, "field_two": foo..."}",
"{"field_one": baz, "field_two": foobar..."}",
...
]
}
The whole point of this is to keep the model json representations consistent, to minimize friction between using the tastypie api directly, and using the data returned in these views. I'm thinking the solution is to somehow use the full_dehydrate method on each resource without serializing them, and then adding them to the bigger dict, and then serializing that dict, but I'm not sure what serializer to use. Or, maybe there is a better way.
As is often the case, writing this up helped me find a temporary solution. Maybe someone will have some input on how to make this better.
I am using this to prepare a queryset for serialization:
def serialize_queryset(resource_class, queryset):
# hand me a queryset, i give you dehydrated resources
resource = resource_class()
dd = {}
# make meta
dd['meta'] = {}
dd['meta']['limit'] = 1000
dd['meta']['next'] = None
dd['meta']['offset'] = 0
dd['meta']['previous'] = None
dd['meta']['total_count'] = len(queryset)
# objects
dd['objects'] = []
for obj in queryset:
bundle = resource.build_bundle(obj=obj)
dehydrated_obj = resource.full_dehydrate(bundle)
dd['objects'].append(dehydrated_obj)
# return dict
return dd
And I use the Serializer from tastypie.serializer. and in using it in a sample view is goes something like:
from tastypie.serializer import Serializer
serializer = Serializer()
def my_view(request):
#... do some other view stuff ...
# prepare a queryset for serialization
queryset = MyModel.objects.filter(is_cool=True)
data = serialize_queryset(MyModel, queryset)
# add in custom stuff, determined earlier in the view somewhere
data['success'] = success
data['message'] = message
data['error'] = error
# serialize and return response
data = serializer.serialize(data)
return HttpResponse(data, mimetype='application/json')
This seems to work. Maybe you see something bad about this method, or a way to improve it?
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')