Django 关于 UniqueConstraint 的更新

问题描述 投票:0回答:1

我正在尝试使用 UniqueConstraint,但在尝试按照我想要的方式更新它时遇到了一些问题。

我有以下型号

class QueryModel(models.Model):

    id = models.AutoField(_("query id"), primary_key=True)
    user = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    name = models.CharField(_("query name"), max_length=150)
    status = models.CharField(
        _("query status"),
        choices=QueryStatus.choices,
        default=QueryStatus.ACTIVE,
    )
    is_favorite = models.BooleanField(_("favorite"), default=False)
    date_created = models.DateTimeField(_("date created"), auto_now_add=True)

    class Meta(object):
        app_label = "app"
        db_table = "query"
        constraints = [
            models.UniqueConstraint(
                fields=("user",),
                condition=Q(is_favorite=True),
                name="unique_favorite_per_user",
            )
        ]
class QueryView(viewsets.ModelViewSet):
    """
    View to list all users in the system.

    * Requires token authentication.
    * Only admin users are able to access this view.
    """

    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    serializer_class = QuerySerializer
    aws_client = AWSClient()

    def get_queryset(self):
        """
        This view should return a list of all the purchases
        for the currently authenticated user.
        """
        self._paginator = None
        return QueryModel.objects.filter(user=self.request.user).order_by("id")

    def create(self, request):
        serializer = QuerySerializer(
            data={
                "user": request.user.id,
                "name": request.data["name"],
                "expiration_date": request.data["expiration_date"],
                "json": request.data["json"],
            }
        )

        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def partial_update(self, request, pk=None):
        serializer = QuerySerializer(data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)

        if "is_favorite" in serializer.validated_data.keys():
            self.get_queryset().update(
                is_favorite=ExpressionWrapper(Q(pk=pk), BooleanField())
            )

        return super().partial_update(request, pk)
router = DefaultRouter(trailing_slash=False)
router.register("auth", AuthView, basename="auth")
router.register("query", QueryView, basename="query")

version_info = json.load(open("./version.json"))


@api_view(["GET"])
def health_check(request):
    """Check if the endpoint is on. Used by container orchestration system."""
    return Response({"status": "pass", **version_info})


urlpatterns = [
    path("", health_check),
    *router.urls,
]

因此,在我的系统中,用户可以创建查询并将其设置为收藏夹,但每个用户只能有 1 个收藏夹查询,因此我创建了 UniqueConstraint 来强制执行该业务规则。

然后我会有一个端点将查询设置为最喜欢的,但是有没有办法让我更新该字段,而不必检查每个用户的所有 is_favorite 字段并手动将它们设置为 False?

我发现this 2年前的StackOverflow帖子提出了一个解决方案,但这个解决方案对我不起作用,我真的很感激一些帮助

python django django-rest-framework
1个回答
2
投票

如果您想将

QueryModel
my_pk
设置为收藏夹主键,请更新:

从 django.db.models 导入 BooleanField、ExpressionWrapper、Q

QueryModel.objects.filter(user=my_user).update(
    is_favorite=ExpressionWrapper(Q(pk=my_pk), BooleanField())
)

如果已有收藏夹,这将自动禁用收藏夹,并将其设置为以

my_pk
作为主键的收藏夹。

© www.soinside.com 2019 - 2024. All rights reserved.