在 Django Rest Framework 中转储自定义过滤字段作为响应
Dump A Custom Filtered Field as Response in Django Rest Framework
blog/models.py
class Tag(models.Model):
label = models.SlugField(null=False, blank=False, unique=True)
# (iii) or here?
# ...
class Entry(models.Model):
title = models.CharField(null=False, blank=False, max_length=128)
content = models.TextField(null=False, blank=False)
slug = models.SlugField(unique=True)
tags = models.ManyToManyField(Tag, null=False, blank=False)
dtime_created = models.DateTimeField(null=False, blank=False, auto_now_add=True)
api/serializers.py
from blog.models import *
from rest_framework import serializers
class EntrySerializer(serializers.ModelSerializer):
class Meta:
model = Entry
fields = ("title", "content")
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ("label")
# (ii) here?
api/views.py
class TagList(APIView):
def search_by_query(self, query):
try:
return Tag.objects.filter(label__icontains=re.escape(query))
# (i) do something here?
except Tag.DoesNotExist:
raise Http404
def get(self, request, format=None):
q = None
try:
q = request.POST["q"]
except KeyError:
return Response(status=status.HTTP_400_BAD_REQUEST)
tags = self.search_by_query(query)
serializer = TagSerializer(tags, many=True)
return Response(serializer.data)
def post(self, request, format=None):
if not request.user.is_authenticated():
return Response(status=status.HTTP_403_FORBIDDEN)
serializer = TagSerializer(request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
我的问题有点复杂。现在,我有一个被 Entry
模型使用的 Tag
模型。然后,我创建了一个名为 TagList
的 APIView
,它会转储包含标签的字符串。但是,问题是,我还想转储标签在 Entry
个实例中使用了多少次,如下所示:
# This is similiar to how it dumps
[
{
"label": "a-label-here"
},
{
"label": "another-label-here"
}
]
# This is what I want
[
{
"label": "a-label-here",
"length": 5
},
{
"label": "another-label-here",
"length": 15
}
]
怎么做?
环境
- python 3.5.1
- django 1.9.5
- djangorestframework 3.3.3
非常简单 - 使用 DRF 的 source
核心参数。
第 1 步
在您的 Tag
模型上定义一个计算任何标签出现次数的方法:
class Tag(models.Model):
label = models.SlugField(null=False, blank=False, unique=True)
def nr_of_entries(self):
return self.entry_set.count()
第 2 步
然后在您的 TagSerializer
上添加一个自定义字段,该字段将从您在上面定义的方法中获取数据:
class TagSerializer(serializers.ModelSerializer):
length = serializers.IntegerField(source="nr_of_entries", read_only=True)
class Meta:
model = Tag
fields = ("label", "length")
现在,当 tag
的一个实例将被序列化时,它将包含一个 length
属性,它将从 运行 的结果中获取它的值该 tag
实例上的 nr_of_entries
方法。
blog/models.py
class Tag(models.Model):
label = models.SlugField(null=False, blank=False, unique=True)
# (iii) or here?
# ...
class Entry(models.Model):
title = models.CharField(null=False, blank=False, max_length=128)
content = models.TextField(null=False, blank=False)
slug = models.SlugField(unique=True)
tags = models.ManyToManyField(Tag, null=False, blank=False)
dtime_created = models.DateTimeField(null=False, blank=False, auto_now_add=True)
api/serializers.py
from blog.models import *
from rest_framework import serializers
class EntrySerializer(serializers.ModelSerializer):
class Meta:
model = Entry
fields = ("title", "content")
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ("label")
# (ii) here?
api/views.py
class TagList(APIView):
def search_by_query(self, query):
try:
return Tag.objects.filter(label__icontains=re.escape(query))
# (i) do something here?
except Tag.DoesNotExist:
raise Http404
def get(self, request, format=None):
q = None
try:
q = request.POST["q"]
except KeyError:
return Response(status=status.HTTP_400_BAD_REQUEST)
tags = self.search_by_query(query)
serializer = TagSerializer(tags, many=True)
return Response(serializer.data)
def post(self, request, format=None):
if not request.user.is_authenticated():
return Response(status=status.HTTP_403_FORBIDDEN)
serializer = TagSerializer(request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
我的问题有点复杂。现在,我有一个被 Entry
模型使用的 Tag
模型。然后,我创建了一个名为 TagList
的 APIView
,它会转储包含标签的字符串。但是,问题是,我还想转储标签在 Entry
个实例中使用了多少次,如下所示:
# This is similiar to how it dumps
[
{
"label": "a-label-here"
},
{
"label": "another-label-here"
}
]
# This is what I want
[
{
"label": "a-label-here",
"length": 5
},
{
"label": "another-label-here",
"length": 15
}
]
怎么做?
环境
- python 3.5.1
- django 1.9.5
- djangorestframework 3.3.3
非常简单 - 使用 DRF 的 source
核心参数。
第 1 步
在您的 Tag
模型上定义一个计算任何标签出现次数的方法:
class Tag(models.Model):
label = models.SlugField(null=False, blank=False, unique=True)
def nr_of_entries(self):
return self.entry_set.count()
第 2 步
然后在您的 TagSerializer
上添加一个自定义字段,该字段将从您在上面定义的方法中获取数据:
class TagSerializer(serializers.ModelSerializer):
length = serializers.IntegerField(source="nr_of_entries", read_only=True)
class Meta:
model = Tag
fields = ("label", "length")
现在,当 tag
的一个实例将被序列化时,它将包含一个 length
属性,它将从 运行 的结果中获取它的值该 tag
实例上的 nr_of_entries
方法。