Django Update on UniqueConstraint

I'm trying to work with UniqueConstraint but I've been facing some issues trying to update it the way I want.

I have the following model

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",
            )
        ]

So in my system, users can create queries and set them as favorites, but each user can only have 1 favorite query, so I created the UniqueConstraint to enforce that business rule.

Then I would have an endpoint to set a query as favorite, but is there a way for me to update that field without having to check all is_favorite fields of each user and manually setting them to False?

I found this StackOverflow post from 2 years ago that proposes a solution, but this solution is not working for me, I would really appreciate some help

If you want to set the QueryModel with my_pk as primary key as favorite, you update with:

from django.db.models import BooleanField, ExpressionWrapper, Q

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

This will automatically disable a favorite if there is already one, and set it to the one with my_pk as primary key.

Alternatively, we can work with two updates, one to set all rows to False, and then one to set one to True:

QueryModel.objects.filter(user=my_user).update(is_favorite=False)
QueryModel.objects.filter(user=my_user, pk=my_pk).update(is_favorite=True)
Back to Top