django rest_framework 框架动态设置序列化返回的字段

动态修改字段可以使Django rest框架API像graphQL端点一样,只从模型中检索所需的字段。

一旦序列化器被初始化,就可以使用.fields属性访问序列化器上设置的字段字典。访问和修改此属性允许您动态修改序列化器。

显式地修改fields参数可以帮助您做一些奇怪的事情,例如在运行时修改序列化器字段参数,而不是预定义它。

django rest_framework 框架动态设置序列化返回的字段_第1张图片

  1. 创建项目
djang-admin startproject ellistest
  1. 创建app
cd ellistest
python manage.py startapp testserializer
  1. 注册app
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'testserializer.apps.TestserializerConfig',
]

  1. 创建model以及序列化器 models.py
from django.db import models

# Create your models here.
class TestModel(models.Model):
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=255)
    age = models.IntegerField()
    
    def generateTwoValue(self):
        return self.name+'11',str(self.age)+'1'
    
    
from rest_framework import serializers
class TestModelSerializer(serializers.ModelSerializer):
    name_col = serializers.SerializerMethodField()
    age_col = serializers.SerializerMethodField()
    
    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        request = kwargs.get('context', {}).get('request')
        str_fields = request.GET.get('fields', '') if request else None
        fields = str_fields.split(',') if str_fields else None
        # Instantiate the superclass normally
        super(TestModelSerializer, self).__init__(*args, **kwargs)
        if fields is not None:
            # Drop any fields that are not specified in the `fields`
            # argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)
    class Meta:
        model = TestModel
        fields = '__all__'


    def _get_two_values(self, obj):
        if not hasattr(self, '_two_values'):
            self._two_values = obj.generateTwoValue()
        return self._two_values

    def get_name_col(self,obj):
        name_col, _ = self._get_two_values(obj)
        return name_col
    
    def get_age_col(self,obj):
        _, age_col = self._get_two_values(obj)
        return age_col

  1. 数据库迁移
python manage.py makemigrations
python manage.py migrate
  1. 创建view views.py
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from rest_framework import status
from testserializer.models import TestModel,TestModelSerializer
# Create your views here.
class TestView(GenericViewSet):
    queryset = TestModel.objects.all()
    serializer_class = TestModelSerializer
    
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
  1. 创建路由 urls.py

from django.conf.urls import url, include
from rest_framework import routers
from testserializer.views import TestView

route = routers.DefaultRouter(trailing_slash=False)
route.register(r'test',TestView,'test')

urlpatterns = [
    url(r'^',include(route.urls)),
]

访问:
http://127.0.0.1:9999/api/v1/test?fields=name,age

https://stackoverflow.com/questions/40663579/call-method-once-to-set-multiple-fields-in-django-rest-framework-serializer

https://joel-hanson.medium.com/advanced-serializer-usage-dynamically-modifying-fields-e7c3bc28efa6

你可能感兴趣的:(Django,django,sqlite,数据库)