skip to Main Content

I am wondering how to pass some context data to response in Django.

I have this endpoint:

/api/facebook/user/

which returns data like this:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "facebook_account_id": "176890406129409",
        "first_name": "Ivan",
        "last_name": "K",
        "token_status": "active",
        "facebook_access_token": 1
    },
    {
        "facebook_account_id": "123123123",
        "first_name": "Ivan",
        "last_name": "FFFF",
        "token_status": null,
        "facebook_access_token": null
    },
    {
        "facebook_account_id": "123123",
        "first_name": "Test",
        "last_name": "test",
        "token_status": null,
        "facebook_access_token": null
    }
]

Here is my list serializer:

class FacebookUserListSerializer(ModelSerializer):
    token_status = SerializerMethodField()

    class Meta:
        model = FacebookUser
        fields = ["facebook_account_id", "first_name", "last_name", "token_status", "facebook_access_token"]

    def get_token_status(self, obj):
        try:
            facebook_token = obj.facebook_access_token
            if facebook_token:
                return "active" if facebook_token.is_active else "inactive"
        except FacebookToken.DoesNotExist:
            return None

Here is my list view:

def list(self, request, *args, **kwargs):
    response = super().list(request, *args, **kwargs)
    data = response.data
    inactive_accounts = sum(1 for account in data if account.get("token_status") == "inactive")
    accounts_without_token = sum(1 for account in data if account.get("token_status") is None)
    context = {"inactive_accounts": inactive_accounts, "accounts_without_token": accounts_without_token} # Is this the correct way of passing context data to a response?
    response.context_data = context
    return response

In list view, in the "context" variable, I am attempting to pass data to the frontend, but I am sure that I am doing this incorrectly, I must first convert it to JSON, or make this somewhere else.

So the question is – where (serializer, list method, or somewhere else?) and how should I put this context data according to REST conventions, so that data can be accessed in frontend without iterating over list items?

2

Answers


  1. you can do something like this:

    context = {
                "inactive_accounts": inactive_accounts,
                "accounts_without_token": accounts_without_token
            }
    
    response.data['context'] = context
    

    but in the front end you will have to fetch this values using chained key like
    data.context.inactive_accounts

    or you can simply add key directly to response without defining separate context.

    response.data['inactive_accounts']= inactive_accounts
    response.data['accounts_without_token']= accounts_without_token
    
    

    then at frontend you can directly fetch with related keys
    data.inactive_accounts

    Login or Signup to reply.
  2. Do not loop through serialized data to find the information you want, use the view queryset instead. Also, there is no need to convert your response, DRF Response handles it automatically, given the correct content-type.

    Since the extra information is not directly related to your object, doing it inside the list method is just fine. Else, you would use get_serializer_context method.

    Here is a more "advanced" way on how to extract this information, using aggregation:

    views.py

    class FacebookUserList(ListAPIView):
        queryset = FacebookUser.objects.all()
        serializer_class = FacebookUserListSerializer
    
        def list(self, request):
            queryset = self.get_queryset()
    
            accounts_without_token = Q(facebook_access_token__isnull=True)
            inactive_accounts = (
                Q(facebook_access_token__is_active=False) | 
                Q(facebook_access_token__isnull=True)
            )
    
            metadata = queryset.aggregate(
                accounts_without_token=Count("pk", filter=accounts_without_token),
                inactive_accounts=Count("pk", filter=inactive_accounts),
            )
    
            serializer = self.get_serializer(
                queryset,
                many=True,
            )
    
            context = {
                "metadata": metadata,
                "users": serializer.data,
            }
            return Response(context)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search