I'm newbie in Python and building API in Django using rest framework and using mysql for database.
I'm using filter query to get user info object but its returning array.
In Login API my code is:
is_valid_user = users.objects.filter(email=req_email, password=req_password)
serializer = usersSerializer(is_valid_user,many=True)
if is_valid_user:
response = {
'message': 'success',
'code': 1,
'data':serializer.data
else:
response = {
'message': 'User not found',
'code': 0,
}
return Response(response)
My usersSerializer Class :
class usersSerializer(serializers.ModelSerializer):
class Meta:
model = users
fields = ('uid', 'first_name', 'last_name', 'email', 'gender')
For this code response is :
{
"message": "success",
"code": 1,
"data": [
{
"uid": 6,
"first_name": "anuj",
"last_name": "sharma",
"email": "anujs1991#gmail.com",
"gender": "0"
}
]
}
But for this I don't want array of data .
Expected result should be :
{
"message": "success",
"code": 1,
"data": {
"uid": 6,
"first_name": "anuj",
"last_name": "sharma",
"email": "anujs1991#gmail.com",
"gender": "0"
}
}
Kindly help me for this.
The comments under your questions should point you to another solution. Here I'd like to give an explanation, why you're getting an array, and not an object.
In this line:
isValidUser = users.objects.filter(email=req_email, password=req_password)
you use the filter method, which may return more than 1 result (or none). You'll always get an array (a list in python), regardless of the number of results. The filter() method returns a new QuerySet.
If you want to retrieve a single result explicitly, and you have a unique field in your model class, then you should use the method get(), which doesn't return a QuerySet, but an object.
So if, let's say the field email is set to be unique, you could do this:
isValidUser = users.objects.get(email=req_email)
That will return an object, if there is an entry that can be matched.
Also, it is a good practice to follow the naming conventions for Python and name the variables with snake case:
is_valid_user
instead of
isValidUser
Related
I am returning some data but instead of dict I am getting list in return
my serializer.py file
class CommitteeDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = Committee
fields = ['id','com_name', 'com_members_limit', 'com_amount_per_month',
'com_starting_date', 'com_join_id', 'com_status']
my views.py
serializer = CommitteeDetailsSerializer(get_committee, many=True)
I am getting this data list
{
"status": "success",
"msg": "Done.",
"data": [
{
"id": 19,
"com_name": "My second Committee",
"com_members_limit": 4,
"com_amount_per_month": 1000,
"com_starting_date": "2022-05-04",
"com_join_id": "GR9PKKOX65",
"com_status": "pending"
}
]
}
what I want is dict here in data {}
In your views.py in the serializer you passed many=True, hence its returning a list. Remove that and you should get one single object serialized instead of a list.
I would like to map object from another API and send in GET response. I'm going to change only id of received object. Let's assume I get data from another API in such format:
{
"id": "31242",
"name": "sth1",
"price": "44",
"data": "2017-06-07",
}
In my database I have table object1 with values:
{
"id": "123",
"name": "sth1",
},
{
"id": "124",
"name": "sth2",
},
{
"id": "125",
"name": "sth3",
}
Field name is unique both in data from API and in data from database. I receive an object named sth1. So now I would like to find it in my database and get his id, replace with id from API and send GET response. In this case my response would look in this way:
{
"id": "123",
"name": "sth1",
"price": "44",
"data": "2017-06-07",
}
At this moment this is my URL - url(r'^data/(?P<name>\w+)$', views.DataList),
but I would like to have such URL - localhost:8000/data?name=sth
Myview.py:
#api_view(['GET'])
def DataList(request, name=None):
if request.method == 'GET':
quote = getDataFromAPI().get(name)
return Response(quote)
serializers.py:
class Object1Serializer(serializers.ModelSerializer):
class Meta:
model = Object1
depth = 1
fields = '__all__'
models.py:
class Object1(models.Model):
name = models.CharField(max_length=200)
I have done it in this way:
#api_view(['GET'])
def DataList(request):
t = request.GET.get("t","")
quote = getDataFromAPI().get(t)
id = Object1.objects.get(t=t)
quote["id"] = id
return Response(quote)
But I get error:
TypeError: Object of type 'Object1' is not JSON serializable
I suppose, your view should look somewhat like this,
#api_view(['GET'])
def DataList(request):
t = request.GET.get("t","")
quote = getDataFromAPI().get(t)
id = Object1.objects.get(t=t).id #put the id of the object in the variable.
#not the object itself.
quote["id"] = id
return Response(quote)
If you want to change the url from
url(r'^data/(?P<name>\w+)$', views.DataList) to localhost:8000/data?name=sth you'd need to change your api endpoint from
#api_view(['GET'])
def DataList(request, name=None):
to
#api_view(['GET'])
def DataList(request):
name = request.GET.get("name","")
and then take the id of object from your database by querying
id = Object1.objects.get(name=name)
and then updating id in response to be sent
quote["id"] = id
I have the following two classes in my app.models and i'm using the wagtail APIs to get the data as json
class AuthorMeta(Page):
author=models.OneToOneField(User)
city = models.ForeignKey('Cities', related_name='related_author')
class Cities(Page):
name = models.CharField(max_length=30)
So, when I try /api/v1/pages/?type=dashboard.AuthorMeta&fields=title,city, it returns the following data:
{
"meta": {
"total_count": 1
},
"pages": [
{
"id": 11,
"meta": {
"type": "dashboard.AuthorMeta",
"detail_url": "http://localhost:8000/api/v1/pages/11/"
},
"title": "Suneet Choudhary",
"city": {
"id": 10,
"meta": {
"type": "dashboard.Cities",
"detail_url": "http://localhost:8000/api/v1/pages/10/"
}
}
}
]
}
In the city field, it returns the id and meta of the city. How can I get the name of the city in the response here, without making an extra query? :/
I couldn't find any solution in the Documentation. Am I missing something?
Use Django model property to return through the ForeignKey:
class AuthorMeta(Page):
author=models.OneToOneField(User)
city = models.ForeignKey('Cities', related_name='related_author')
city_name = property(get_city_name)
def get_city_name(self):
return self.city.name
Check Term Property to better understand the concept
In case you have the foreign key in a Streamfield, e.g. a PageChooserBlock, you can customize the api response by overwriting the get_api_representation of a block, as described in the example as provided here:
class CustomPageChooserBlock(blocks.PageChooserBlock):
""" Customize the api response. """
def get_api_representation(self, value, context=None):
""" Return the url path instead of the id. """
return value.url_path
In How to add django-reversion to an app developed using django and django-rest framework I have added the below function to get history of objects
from django.http import HttpResponse
from reversion.models import Version
import json
def history_list(request):
history_list = Version.objects.all().order_by('-revision__date_created')
data = []
for i in history_list:
data.append({
'date_time': str(i.revision.date_created),
'user': str(i.revision.user),
'object': i.object_repr,
'type': i.content_type.name,
'comment': i.revision.comment
})
data_ser = json.dumps(data)
return HttpResponse(data_ser, content_type="application/json")
In the urls.py of How to add django-reversion to an app developed using django and django-rest framework I have added a route to history.
When I visit 127.0.0.1:8000/history I get the json data as
[{"object": "someobject", "user": "someuseruser", "type": "sometype", "comment": "Changed name.", "date_time": "2015-03-02 18:04:58.368650+00:00"}]
execution flow: When I visit 127.0.0.1:8000/admin and change the value of above object to "otherobject". when I refresh 127.0.0.1:8000/history. I get one more json field
[{"object": "otherobject", "user": "someuseruser", "type": "sometype", "comment": "Changed name.", "date_time": "2015-03-02 18:04:58.368650+00:00"}]
below is the area I got stuck to add one more additional field to history function:
I would like to include one more field to above iteration in history function. like previous_object: " " to get the object name before its changed even after changing name.
for instance:-
from 127.0.0.1:8000/admin
I changed object name from "apple" to "orange".
When I visit the history route 127.0.0.1:8000/history
[{"object": "apple", "object_before_changed": ""null": "someuseruser", "type": "sometype", "comment": "Changed name.", "date_time": "2015-03-02 18:00:58.368650+00:00"}]
I should be able to see as below
[{"object": "orange", "object before_changed": ""apple": "someuseruser", "type": "sometype", "comment": "Changed name.", "date_time": "2015-03-02 18:04:58.368650+00:00"}]
You just need to setup a variable to hold to previous item and insert it into the dictionary as required. note that this uses getattr as a way to get the object_repr of previous_object and safely provide a default if there is none (as would be the case for the first iteration).
data = []
previous_object = None
for i in history_list:
data.append({
'date_time': str(i.revision.date_created),
'user': str(i.revision.user),
'object': i.object_repr,
'previous_object': getattr(previous_object,'object_repr',None),
'type': i.content_type.name,
'comment': i.revision.comment
})
previous_object = i
I want to grab some information from Foursquare , add some fields and return it via django-tastypie.
UPDATE:
def obj_get_list(self, request=None, **kwargs):
near = ''
if 'near' in request.GET and request.GET['near']:
near = request.GET['near']
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
client = foursquare.Foursquare(client_id=settings.FSQ_CLIENT_ID, client_secret=settings.FSQ_CLIENT_SECRET)
a = client.venues.search(params={'query': q, 'near' : near, 'categoryId' : '4d4b7105d754a06374d81259' })
objects = []
for venue in a['venues']:
bundle = self.build_bundle(obj=venue, request=request)
bundle = self.full_dehydrate(bundle)
objects.append(bundle)
return objects
Now I am getting:
{
"meta": {
"limit": 20,
"next": "/api/v1/venue/?q=Borek&near=Kadikoy",
"offset": 0,
"previous": null,
"total_count": 30
},
"objects": [
{
"resource_uri": ""
},
{
"resource_uri": ""
}]
}
There are 2 empty objects. What should I do in order to fill this resource?
ModelResource is only suitable when you have ORM Model behind the resource. In other cases you should use Resource.
This subject is discussed in ModelResource description, mentioning when it is suitable and when it is not: http://django-tastypie.readthedocs.org/en/latest/resources.html#why-resource-vs-modelresource
Also there is a whole chapter in the documentation, aimed at providing the details on how to implement non-ORM data sources (in this case: external API): http://django-tastypie.readthedocs.org/en/latest/non_orm_data_sources.html