我将此表存储在Postgres数据库中
用户
| id | email | password | gender |
| 01 | user1@email.com | pass1 | male |
| 02 | user2@email.com | pass3 | female |
| 03 | user3@email.com | pass2 | male |
标记
| id | school_mark | subject | user_id | status |
| 01 | 9 | history | 01 | True |
| 02 | 8 | english | 02 | True |
| 03 | 7 | math | 01 | True |
| 02 | 7 | english | 01 | False |
| 03 | 6 | math | 03 | False |
...
# api/models.py
from django.db import models
class User(models.Model):
email = models.EmailField()
password = models.CharField(max_length=100)
gender = models.CharField(max_length=100)
class Mark(models.Model):
school_mark = models.IntegerField()
subject = models.CharField(max_length=100)
user_id = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.BooleanField(default=False)
我希望我的最终结果像这样 / api / marks / male
[
{"id" : 01,
"marks": [
{"id": 01,
"subject": "history",
"school_mark": 9},
{"id": 03,
"subject": "history",
"school_mark": 7}]}
{"id" : 03,
"marks": []}
]
首先仅选择“男性”形式的 user ,然后搜索选定用户的标记,但在响应中仅返回status = TRUE的标记
我开始认为serializers.py是这样的:
# api/serializers.py
from rest_framework import serializers
from .models import User, Mark
class MarkSerializer(serializers.ModelSerializer):
class Meta:
model = Mark
exclude = ('status', 'user_id')
class UserSerializer(serializers.ModelSerializer):
marks = MarkSerializer(many=True, read_only=True)
class Meta:
model = User
fields = ('id', 'marks')
但是后来我陷入了views.py
# api/views.py
from rest_framework import generics
from .models import User, Mark
from .serializers import UserSerializer
class MarkList(generics.ListAPIView):
serializer_class = UserSerializer
def get_queryset(self):
# "/api/marks/<str:gender>/"
gender = kwargs['gender']
???
有什么想法吗?
答案 0 :(得分:2)
您是否设置了url /响应结构?我意识到这并不是您所要的,但是为了给出最佳答案,我可能会对您的设置进行一些结构上的更改:
通常对于RESTful API, / api / marks / 会返回序列化的Mark
对象的列表,而不是您显示的列表,该列表是{ {1}},其中每个都有序列化的Users
的列表。由于您只需要用户ID,因此DRF提供了一种简单的非嵌套机制,可以以另一种方式(使用PrimaryKeyRelatedField
)来进行序列化。
接下来,我可能会使用查询参数( / api / marks?gender = male ),而不是 / api / marks / male 。这是个人偏爱的一点,但是在REST最佳实践中有一定基础(请参阅this SO answer for a nice description)
最后,Marks
上的ForeignKey
字段应命名为Mark
,而不是user
。在存储外键字段时,Django会自动将user_id
附加到数据库列名称中,因此您编写的模型将产生一个名为_id
的数据库列。
进行了这些修改后,以下代码将为您提供所请求的过滤功能(尽管如上所述,序列化响应与初始请求有所不同)
user_id_id
我尚未对此进行测试,但是除非您有任何错别字,否则从上面的示例中请求 / api / marks?gender = male 都应返回以下内容:
# api/serializers.py
from rest_framework import serializers
from .models import Mark
class MarkSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Mark
exclude = ('status')
# api/views.py
from rest_framework import generics
from .models import Mark
from .serializers import MarkSerializer
class MarkList(generics.ListAPIView):
serializer_class = MarkSerializer
def get_queryset(self):
queryset = Mark.objects.filter(status=True)
gender = self.request.query_params.get('gender')
if gender is not None:
queryset = queryset.filter(user__gender=gender)
return queryset
答案 1 :(得分:0)
这不是 RESTful API的最佳实践。因此,我建议您执行以下操作
将您的$(".feel").click(function() {
alert("s");
$(this).next(".hide").show();
});
更改为有意义的
view.py
class MarkList(generics.ListAPIView):
serializer_class = MarkSerializer
queryset = Mark.objects.all()
class UserList(generics.ListAPIView):
serializer_class = UserSerializer
queryset = User.objects.all()
为
urls.py
现在,您必须 API端点,它们是urlpatterns = [
url(r'user/', UserList.as_view()),
url(r'mark/', MarkList.as_view())
]
和/path/user/
。
如果您在视图上需要过滤器,请使用一些第三方过滤器,例如django-filter(它也有很好的文档说明)或覆盖/path/mark
方法 。请参见下面的示例
get_queryset()
要使用这些过滤器,您必须将API用作
class MarkList(generics.ListAPIView):
serializer_class = MarkSerializer
queryset = Mark.objects.all()
def get_queryset(self):
queryset = Mark.objects.all()
if self.request.GET.get('gender'):
queryset = queryset.filter(user_id__gender=self.request.GET.get('gender'))
# if you need to add more filter like "subject" or "status", implement here
if self.request.GET.get('subject'): # subject filter
queryset = queryset.filter(subject=self.request.GET.get('subject'))
if self.request.GET.get('status'): # status filter
queryset = queryset.filter(subject=self.request.GET.get('status'))
return queryset
/path/mark/?gender=male&status=True&subject=some_subject
/path/mark/?subject=some_subject