django-rest-framework序列化外键操作序列化

项目是有django django-rest-framework django-filter 组合。其中django-rest-framwork的几个组合包一定要记得下载,否则会导致部分功能不能用。
这是依赖包,都得装上。

  • coreapi(1.32.0+) - 文档生成支持。在django-filter的参数添加后可以直接在这里显示
  • Markdown(2.1.0+) - Markdown对可浏览API的支持。(这个对于调试api特别方便)
  • django-filter(1.0.1+) - 过滤支持。
  • django-crispy-forms - 改进的HTML显示以进行过滤。
  • django-guardian(1.1.1+) - 对象级权限支持。

model.py:

class ClusterDevice(models.Model):
    cluster = models.CharField(max_length=255, null=True, blank=True, verbose_name="集群名称")
    comment = models.CharField(max_length=255, null=True, blank=True, verbose_name="详情")
    createtime = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        managed = False
        db_table = 'cluster_device'
        verbose_name = "设备集群"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.cluster


class Owner(models.Model):
    owner_name = models.CharField(max_length=255, verbose_name="名称")
    mobile = models.IntegerField(verbose_name="手机号码")
    email = models.EmailField(max_length=255, blank=True, null=True, verbose_name="邮箱")

    class Meta:
        managed = False
        db_table = "owner"
        verbose_name = "联系人"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.owner_name

class Device(models.Model):
    CHOICE = (
        (0, "失效"),
        (1, "有效")
    )
    name = models.CharField(max_length=255, blank=True, null=True, verbose_name="设备名称", unique=True)
    status = models.IntegerField(choices=CHOICE, default=1, verbose_name="状态")
    type = models.ForeignKey(to=DeviceTag, related_name='tag_result', verbose_name="类型")
    #注意此处的两个外键
    owner = models.ForeignKey(to=Owner, related_name='result', verbose_name="所有者")
    password = models.CharField(max_length=255, blank=True, null=True, verbose_name="密码")

    class Meta:
        managed = False
        db_table = 'device'
        verbose_name = "设备信息"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.alias

序列化器:


class DeviceTagSerializer(serializers.ModelSerializer):
    class Meta:
        model = DeviceTag
        fields = "__all__"


class ClusterDeviceSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClusterDevice
        fields = "__all__"


class OwnerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Owner
        fields = "__all__"


class DeviceSerializer(serializers.ModelSerializer):
    # 此处的模式是:
     # Device_model的字段=serializer.CharField(source='Device_model的字段.外键模型自定字段')
    type = serializers.CharField(source='type.tag_name')
    cluster_device = serializers.CharField(source='cluster_device.cluster')
    owner = serializers.CharField(source='owner.owner_name')

    class Meta:
        model = Device
        fields = "__all__"

假如不做自定义的序列化,那么取到的数据将会是id,显示很不友好。假如下面使用这样的外键序列化

type = DeviceTagSerializer(many=True)

这样返回的将会是外键的所有信息,那个外键表的所有字段,所有信息(或者是自定义的几个字段)

而我们显示要是外键的某个字段:那就必须序列化外键表的某个字段

type = serializers.CharField(source='type.tag_name')

序列化外键的使用方式就是上面那样,自定义序列化一下,就好了。
注意 自定义的序列化的格式,前面变量最好是model里面的外键字段(此处也可以是type_name,但是这样显示的时候会多一个自断,并且显示还是id),后面的source中也必须是model中的字段,否则会报错。不可迭代类型啊,xxmodel没有xx属性。

views:

class Pagination(PageNumberPagination):
    '''
    翻页器
    '''
    page_size = 10
    page_size_query_param = 'page_size'
    #此处的也会自动在路由那也就是core的文档中生成
    page_query_param = "page"
    max_page_size = 100


class DeviceListViews(mixins.ListModelMixin, viewsets.GenericViewSet):
    '''
    设备表
    '''
    queryset = DeviceController().get_all_device()
    serializer_class = DeviceSerializer
    pagination_class = Pagination
    filter_backends = (DjangoFilterBackend,filters.SearchFilter)
    filter_class = DeviceFilter
    # print(queryset)
    search_fields = ('id', 'alias', 'inner_ip', 'outer_ip', 'owner')

 

url:没有使用register进行注册的方式。

urlpatterns = [
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^docs/', include_docs_urls(title="基础服务文档"))
    url(r'^DeviceList', DeviceListViews.as_view({'get': 'list'}), name='device'),
    url(r'^OwnerList', OwnerListViews.as_view({'get': 'list'}), name='owner'),
    # 这样的url后会直接生成 /device/DeviceList?fields=xx使用
    # drf+django-filter 的好处,就省下来好多的路由麻烦


]

filter文件:


class DeviceFilter(django_filters.rest_framework.FilterSet):
    alias = django_filters.CharFilter(help_text="别名")
    # 后面的help文字会在core文档里面生成
    inner_ip = django_filters.CharFilter(help_text="内网ip")
    outer_ip = django_filters.CharFilter(help_text="外网ip")
    owner = django_filters.NumberFilter(help_text="所属者的id")

    class Meta:
        model = Device
        fields = ['id', 'alias', 'inner_ip', 'outer_ip', 'owner']

上面的djagno-filter+core+markdown效果:我的路由是使用的分发的状态

django-rest-framework序列化外键操作序列化_第1张图片

你可能感兴趣的:(后端)