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")
    # 完全定义字段,上帝字段,想返回什么就返回什么
    test_owner = serializers.SerializerMethodField() 
    device_info = serializers.SerializerMethodField() # 获取方式完全是自定义
    
    def get_test_owner (self, obj):
        try:
            aim_app = obj.device_id.all()
            if aim_app:
                app_list = DeviceaimSerializer(aim_app, many=True,  context={'request': self.context['request']})
                return app_list.data
        except Exception as e:
            appserializer_log.error(e)

    def get_device_info(self, obj):
        aim_device = DeviceController().get_aim_device(alias=obj.device_id)
        device_list = DeviceCusSerializer(aim_device, many=True, context={'request': self.context['request']})
        return device_list.data

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

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

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Django-REST-framework 中,可以通过 Serializer 来实现将两个或多个表的查询结果返回给前端。具体步骤如下: 1. 定义 Serializer 类,通过继承 serializers.Serializer 或 serializers.ModelSerializer 来定义序列化类。在序列化类中,需要定义需要返回给前端的字段,以及与其他表的关联关系。 2. 定义视图函数,通过继承 generics.ListAPIView 或 generics.RetrieveAPIView 来定义视图函数。在视图函数中,需要指定查询结果所对应的模型类,以及使用序列化类。 3. 注册 URL,将视图函数与 URL 进行绑定,以便进行访问。 例如,假设有两个模型类,分别为 Book 和 Author,它们之间存在外键关系。现在需要将 Book 和 Author 的查询结果返回给前端,可以按照以下步骤进行: 1. 定义序列化类 ```python from rest_framework import serializers from .models import Book, Author class AuthorSerializer(serializers.ModelSerializer): class Meta: model = Author fields = ('id', 'name', 'email') class BookSerializer(serializers.ModelSerializer): author = AuthorSerializer() class Meta: model = Book fields = ('id', 'title', 'author') ``` 在 BookSerializer 中,通过 author = AuthorSerializer() 来指定与 Author 模型类的关联关系。这样,在序列化 Book 查询结果时,会同时序列化对应的 Author 对象。 2. 定义视图函数 ```python from rest_framework import generics from .models import Book from .serializers import BookSerializer class BookList(generics.ListAPIView): queryset = Book.objects.all() serializer_class = BookSerializer ``` 在 BookList 视图函数中,指定查询结果对应的模型类为 Book,使用序列化类为 BookSerializer。 3. 注册 URL ```python from django.urls import path from .views import BookList urlpatterns = [ path('books/', BookList.as_view()), ] ``` 将 BookList 视图函数与 '/books/' URL 进行绑定,以便进行访问。当访问 '/books/' URL 时,将返回 Book 和 Author 的查询结果。 需要注意的是,以上代码只是示例,实际情况中可能需要根据具体需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值