gpt4 book ai didi

python - Django 休息框架 : advanced queryset filtering based on another model

转载 作者:太空宇宙 更新时间:2023-11-04 00:25:50 24 4
gpt4 key购买 nike

我正在使用 Django Rest Framework 作为应用程序的后端。

我有一个用户,它有一个钱包。然后我有 Item。如果 User 想要一个 Item,它会在他/她的 Wallet 中创建一个名为 WalletItem 的实例。一切正常。

现在我想使用属性 limit_usage 限制 User 的项目数。

首先,我在添加新实例的 post 方法中添加了一个检查,用于检查 UserWallet 中项目实例的数量。因此,如果此 Itemlimit_usage == 2,则用户在尝试添加第三个 WalletItem 时会收到 403。

我想覆盖 list()/retrieve() 中的 get_queryset() 方法或 queryset > 方法,这样如果匿名用户调用 /items/ 就会有未过滤的项目作为响应。但是,如果用户经过身份验证,我只想过滤那些他/她被允许放入钱包的项目,即那些没有超过当前用户 limit_usage 的项目。

class Wallet(models.Model):
user = models.OneToOneField('auth.User', related_name='wallet')

class Item(models.Model):
valid_from = models.DateTimeField()
valid_to = models.DateTimeField()
limit_usage = models.PositiveSmallIntegerField(default=0)

class WalletItem(models.Model):
wallet = models.ForeignKey('Wallet', related_name='%(class)ss')
offer = models.ForeignKey('Item', related_name='offer')

class ItemViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Item.objects.all().order_by('-created_at')
serializer_class = ItemSerializer

def list(self, request, *args, **kwargs):
time_now = now()
self.queryset = self.queryset.filter(
valid_from__lte=time_now,
valid_to__gte=time_now,
)
serializer = self.get_serializer(self.queryset, many=True)
return Response(serializer.data)

我创建了一个 Item 类的方法,它应该对我有帮助,但我意识到我不能在查询集中使用它:

def is_visible_for_user(self, user=None):
if not self.limit_usage or not user:
return True
ct = WalletItem.objects.filter(item=self, wallet=user.wallet).count()
return self.limit_usage > ct

所以我可以遍历查询集以查看用户是否可以看到每个项目,但是我无法从这个过滤列表中构建查询集。我在 SO 上发现了类似的东西:Django REST Framework : filtering with another table但回应对我没有帮助。

最佳答案

您首先需要检查用户是否通过身份验证,如果没有,然后返回每个 Item。如果相应的WalletItem对象超过了限制,则过滤掉Item对象。

from django.db.models import Count, F, Sum

...

class ItemViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
queryset = super().get_queryset()
user = self.request.user
if user.is_anonymous:
return queryset

queryset = queryset.annotate(user_wallet_items=Sum(
Case(
When(walletitem__wallet_id=user.wallet_id, then=1),
default=0, output_field=IntegerField()
)) \
.filter(user_wallet_items__lte=F('limit_usage'))
return queryset

我建议您将基于当前时间的过滤移动到相同的 get_queryset() 方法,因为它属于那里。

注意:我没有测试过这种方法。

关于python - Django 休息框架 : advanced queryset filtering based on another model,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47500345/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com