Antti Isomursu
Antti Isomursu

Reputation: 68

Return QuerySet as JSON. Using values() function leads to missing values

I want to fetch data from the model shown below. class ModelItem should return all the 4 values in the return statement.

class ModelItem(models.Model):
    """Stores item names for user"""
    item_owner = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
    item_name = models.TextField(max_length=100, null=True)

    def __unicode__(self):
        return "{0}, {1}, {2}, {3}".format(
                                        self.pk,
                                        self.item_owner.pk,
                                        self.item_owner.username,
                                        self.item_name,
                                      )

At views.py the code below works.I get all the values that class 'ModelItem' is returning

user_id = 2
get_data = ModelItem.objects.filter(item_owner=user_id)
context = {'user_items': get_data}
return render(request, 'itemrequests.html', context)

Results this(pk of item, pk of item_owner, username of item_owner, item_name):

<QuerySet [<ModelItem: 1, 2, app_user, 2h-Axe>, <ModelItem: 2, 2, app_user, Ball of fire>]>

But if trying to return data in JSON (and therefore having to use .values() )

user_id = 2
get_data = ModelItem.objects.filter(item_owner=user_id).values()
return JsonResponse({'results': list(get_data)})

Results(username is missing):

{"results": [{"item_name": "2h-Axe", "item_owner_id": 2, "id": 1}, {"item_name": "Ball of fire", "item_owner_id": 2, "id": 2}]}

I can't find out what is causing this. Is it the way I am returning data from the model or something else?

SOLVED

Ok So in order to return customized data from model I switched from using Djangos default User-model to a custom User-model by adding this class to models.py:

class SiteUser(AbstractUser):

    def natural_key(self):
        return (self.username, self.pk)

For django to start using my new custom User-model I also added following into settings.py:

AUTH_USER_MODEL = 'homepage.SiteUser'

This way I am still using the default User-model as a base and just adding things to it. In this class I added the natural_key() -method which returns the username and primary key of an user.

In other models where I point Foreign Keys to User I made following change:

models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)

In my views.py I used then following:

user_id = 1
get_data = ModelItem.objects.select_related('item_owner').filter(item_owner=user_id)
ser_data = serializers.serialize("json", get_data, use_natural_foreign_keys=True)
return HttpResponse(ser_data, content_type="application/json")

Result:

[{"model": "homepage.modelitem", "pk": 1, "fields": {"item_owner": ["Murzum", 1], "item_name": "2h-Axe"}}, {"model": "homepage.modelitem", "pk": 2, "fields": {"item_owner": ["Murzum", 1], "item_name": "Ball Of fire"}}]

Now I have both username and pk values for the item_owner. Also learning now about django Manager interface

Upvotes: 0

Views: 78

Answers (1)

Andruten
Andruten

Reputation: 261

Methods __unicode__ or __str__ are only for representation when you print an object, it doesn't means that if you return an instance will work in that way. You have to return the information you need serializing the data.

EDIT: Also you can use select_related method in order to avoid extra queries.

ModelItem.objects.select_related('item_owner').filter(item_owner=user_id)

Upvotes: 1

Related Questions