Nikko
Nikko

Reputation: 1572

DRF: values() does not return groupby object

Suppose I have:

# models.py
class Project(models.Model):
    project = models.CharField(max_length=200)
    subproject = models.CharField(max_length=200)
    physical_pct = models.FloatField()
    cost = models.FloatField()

# serializers.py
class ProjectSerializer(serializers.ModelSerializer):

    class Meta:
        model = Project
        fields = '__all__'

In my viewset, I want to display a grouped by object by name that will later be annotated. I referred to this example from values.

# views.py
class ProjectsViewSet(viewsets.ModelViewSet):
    serializer_class = ProjectSerializer

    def get_queryset(self):
        queryset = Project.objects.values('project')
        print(queryset)
        return queryset

When I print queryset it displays a list of all project without the other fields in the terminal. However it raises an error:

"Got KeyError when attempting to get a value for field `subproject` on serializer `ProjectSerializer`.\nThe serializer field might be named incorrectly and not match any attribute or key on the `dict` instance.\nOriginal exception text was: 'subproject'."

My desired output is a json grouped by the project field.

UPDATE 1:

It will not have an error if I put all fields in the values() arguments i.e.

.values('project', 'subproject', 'physical_pct', 'cost',)

Which now then destroy the purpose of values being grouped by.

Upvotes: 0

Views: 431

Answers (3)

You are querying only project field in Project model but trying to serialize all field in Project model. If you want to serialize one field, you don't need the serializer:

class ProjectsViewSet(viewsets.ModelViewSet):
    serializer_class = ProjectSerializer
    queryset = Project.objects.all()

    def list(self, request, *args, **kwargs):
        qs = self.get_queryset().values_list('project', flat=True)
        return Response(qs)

Upvotes: 0

Shakil
Shakil

Reputation: 4630

Main cause of the problem is for your serializer defination. If you only want to return back project field response make sure you are using appropriate serializer for that.

class ProjectSerializer(serializers.ModelSerializer):

    class Meta:
        model = Project
        fields = '__all__' // this means you are suppose to pass all model fields

So we need custom serializer for this purpose

class ProjectListSerializer(serializers.ModelSerializer):

    class Meta:
        model = Project
        fields = ('project',)

And also we need to update get_serializer method according to our necessary need

# views.py
class ProjectsViewSet(viewsets.ModelViewSet):


    def get_queryset(self):
        // If you are doing so you are suppose to have only one 'project' field response 
        queryset = Project.objects.values('project')

        return queryset

    def get_serializer_class(self):
        if self.action == 'list' or self.action == 'retrive':
           return ProjectListSerializer
        return  ProjectSerializer

Upvotes: 1

Jay Pratap Pandey
Jay Pratap Pandey

Reputation: 352

Try:

queryset = Project.objects.all().values('project')

Upvotes: 0

Related Questions