How to retrieve a model field with query parameters in the URL with REST framework?

Question:

I have a model Account with a ForeignKey user and a method total_value() that returns a float64. I would like to GET the float value by entering the account and user primary keys as parameters in the URL.

To do that I catch parameters with request.query_params and select the desired Account object but the framework throws an error.
How can I do that ?

This is the desired URL fomat and output:

https://mysite/api/widget/total/?user=1&account=1
1.22222344

Error returned :

'Account' object is not iterable 

models.py

class Account(TimestampedModel):
    name = models.CharField(max_length=20, null=True, blank=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    def total_value(self):
        return 1.22222344

serializer.py

class TotalAssetsValueSerializer(serializers.ModelSerializer):

    class Meta:
        model = Account
        fields = ('total_value',)

view.py

class TotalAssetsValueView(viewsets.ModelViewSet):
    serializer_class = TotalAssetsValueSerializer
    http_method_names = ['get']

    def get_queryset(self):
        user = self.request.query_params.get('user')
        account = self.request.query_params.get('account')
        return Account.objects.get(pk=account, user=user)

urls.py

router = routers.DefaultRouter()
router.register("widget/total", TotalAssetsValueView, basename="account-total")

urlpatterns = [
    path('', include(router.urls)),
]

I’m sure there an account with pk=1 and user=1, so maybe my mistake is that I return an object not a queryset. Unfortunnatly when I filter instead of get it return [].

Asked By: Florent

||

Answers:

Here you are returning a single Account object, but get_queryset method should return QuerySet of objects. That’s why it throws error that a single object is not iterable.

def get_queryset(self):
    user = self.request.query_params.get('user')
    account = self.request.query_params.get('account')
    return Account.objects.get(pk=account, user=user)

Depending on what you want to go for, you can change it to single object QuerySet:

...
return Account.objects.filter(pk=account, user=user)

Or completely change whole view approach, but there are many ways to do that.

Answered By: NixonSparrow