Django DRF序列化器或视图中的多表过滤
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django DRF序列化器或视图中的多表过滤相关的知识,希望对你有一定的参考价值。
我想要做的是检索与当前用户相关的记录。
我正在使用DRF JWT,因此user_id
与JWT sessionStorage
一起存储在token
中。据我了解,因为使用JWT,会话身份验证不是,所以像request.user
这样的东西不起作用。至少我永远不会让它工作,只是被告知将user_id
存放在sessionStorage
与JWT token
。因此,如果我想要检索与当前用户相关的记录,则需要使用sessionStorage.getItem('user_id')
将POST
传递给API。 GET
将无法工作,因为1)request.user
不起作用,2)不能发送sessionStorage.getItem('user_id')
。
所以这里是我正在使用的模型,我需要使用一些示例数据进行过滤:
-- Products table
prod_id | prod_name | active
----------------------------
3 | Widget1 | 0
10 | Widget2 | 1
11 | Widget3 | 1
-- Users table
user_id | username
------------------
10011 | joesmith
-- User_to_Products table
user_id | prod_id
-----------------
10011 | 3
10011 | 11
所以应该发生的是React FE通过sessionStorage.getItem('user_id')
将POST
发送到DRF BE,DRF视图有queryset
用于User_to_Products
,它被序列化,并且prod_id
和prod_name
被发送回客户端以便prod_name
可以呈现在React FE中。
这是大局,并且大部分都在发生。但是,如果prod_id
处于非活动状态(0
),则不应返回。目前,我可以过滤与user_id
相关的项目,但它将返回所有prod_id
。所以我需要过滤User_to_Products
和Products
。
我无法做到这一点。我尝试做类似的事情:
user_id = request.data['user_id']
queryset = UserToProducts.objects.filter(user_id=user_id).filter(products__active=1)
哪个适用于香草Django,但不适用于DRF。它认为products__
是User_to_Products
中的一个字段名称,而不是认为它是一个表。
那我该怎么做呢?
这是我的代码在当前状态,即使不活动,它返回所有prod_id
:
# ./views.py
class GetHomeAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
user_id = request.data['user_id']
serializer = GetProductsSerializer(UserToProducts.objects.filter(user_id=user_id).prefetch_related('products'), many=True)
return Response(serializer.data)
# ./serializers.py
from .models import *
class GetProductsSerializer(ModelSerializer):
prod_name = CharField()
prod_id = IntegerField()
class Meta:
model = UserToProducts
fields = [
'prod_id',
'prod_name'
]
# ./models.py
User = get_user_model()
class Products(models.Model):
prod_id = models.AutoField(primary_key=True)
prod_name = models.CharField(max_length=255, blank=True, null=True)
active = models.IntegerField(blank=False)
users = models.ManyToManyField(User, through='UserToProducts')
def __str__(self):
return self.prod_name
class Meta:
db_table = 'Products'
class UserToProducts(models.Model):
user_id = models.ForeignKey(User, related_name='user', db_column='user_id', null=True)
prod_id = models.ForeignKey(Products, related_name='products', db_column='prod_id', null=True)
def __str__(self):
return u'%s' % self.prod_id
class Meta:
db_table = 'User_to_Products'
unique_together = ('user_id', 'prod_id')
ordering = ['-prod_id']
request.user
也应该使用JWT身份验证。您必须确保在REST_FRAMEWORK配置dict中添加了其身份验证类,如下所示:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# ...
),
}
要从外键字段渲染字段,可以使用序列化字段的source
属性,如下所示:
# ./serializers.py
from rest_framework.serializers import *
from .models import *
class GetProductsSerializer(ModelSerializer):
prod_name = CharField(source='prod.name')
prod_id = IntegerField(source='prod.id')
class Meta:
model = UserToProducts
fields = [
'prod_id',
'prod_name'
]
此外,如果您使用的是模型字段而不是序列化程序字段,那么您在此处发布的序列化程序并不清楚。确保在序列化程序中使用序列化程序字段。
关于你的模型,你不应该在外键字段中附加“_id”,因为Django会为你抽象。在引擎盖下,它将创建一个名为{{the_field}} _ id的正整数字段。您可以将外键字段用作模型实例。这条路:
class UserToProducts(models.Model):
user = models.ForeignKey(User, related_name='users', db_column='user_id', null=True)
prod = models.ForeignKey(Products, related_name='products', db_column='prod_id', null=True)
def __str__(self):
return u'%s' % self.prod.id
class Meta:
db_table = 'User_to_Products'
unique_together = ('user', 'prod')
ordering = ['-prod__id']
这样,如果你有一个UserToProducts
实例user_to_products
并想要打印其产品名称,你可以做print(user_to_products.prod.name)
。 Django将自动为您检索数据库中的产品。
以上是关于Django DRF序列化器或视图中的多表过滤的主要内容,如果未能解决你的问题,请参考以下文章