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效果:我的路由是使用的分發的狀態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章