How to select specify field only in Viewset Django

2019-07-25 04:31发布

问题:

I would like to select the distinct field and some field only from Django ViewSet.

My method

@action(methods=['get'], detail=False)
    def shiftsum(self, request):        
        query = (
                    Shift.objects.values('shiftid', 'dayname')
                        .annotate(shiftdesc=Max('shiftdesc'))
                        .annotate(ct=Count('*'))  # get count of rows in group
                        .order_by('shiftid', 'dayname')
                        .distinct()
                )
        serializer = self.get_serializer_class()(query,many=True)
        return Response(serializer.data)

My Model

class Shift(models.Model):
    shiftid = models.CharField(max_length=15)
    shiftdesc = models.CharField(blank = False, null= False, max_length=20)
    dayname = models.CharField(blank = False, null= False, max_length=20)
    dayno = models.IntegerField(blank = False, null= False)
    offin_f = models.IntegerField(blank = False, null= False)
    .
    .
    .

My serializer

class ShiftSerializer(serializers.ModelSerializer):
    class Meta:        
        model=Shift
        fields = "__all__"

    def create(self,validated_data):      
        validated_data['Created_Usr']="Admin"             
        validated_data['Created_DT']=datetime.datetime.now()      
        validated_data['LastModified_Usr']=''            
        validated_data['LastModified_DT']=None            
        return Shift.objects.create(**validated_data)

    def update(self,instance,validated_data):       
        instance.shiftdesc = validated_data.get('shiftdesc',instance.shiftdesc) 
        instance.dayname = validated_data.get('dayname',instance.dayname) 
        instance.dayno = validated_data.get('dayno',instance.dayno) 
        instance.offin_f = validated_data.get('offin_f',instance.offin_f) 
        instance.offout_f = validated_data.get('offout_f',instance.offout_f) 

When I select like that, Error message show

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

I would like to select the shiftid , shiftdesc and dayname only, How to select these three field only and am I need to create new serializer?

回答1:

Your ShiftSerializer uses __all__, which means it is going to try to serialize all the fields in your model.

Since the queryset you have specified doesn't include all your fields (and it is a sum/distinct, so it should not), then this is guaranteed to fail.

There are 2 options

1) Create a new serializer for only the fields you want, manually specifying them

class ShiftSum(Serializer):  # NOT model serializer
    shiftid = CharField()
    ... add other fields

return Response(ShiftSum(query, many=True).data)

2) Convert the queryset to a list, and just return it directly

data = list(query) # turns your queryset into [{"shiftid":"n", ...}, ]
return Response(data=data)

This last way works if the data coming out of your query is already the format you want, and already the correct type for simple JSON serialization (no datetimes, no Decimal, etc). Try it and see if it works.