Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-2.2

Django Change all other Boolean fields except one


I have a model which has a boolean field:

class Library(SocialLinksModelMixin):
    """
    Represents book shelves and places where people have / leave books.
    """
    user = models.ForeignKey(...)
    is_main = models.BooleanField(default=False)

User can have multiple Libraries and I would like to allow setting the main one to ease the flow in the app.

What is the easiest way for switching only one Library is_main to True and all others to False (There is always only 1 Library for a user that is main)

I'm thinking about querying for all libraries and updating each and every one. Maybe there is another way to do that functionality?


Solution

  • If you have the primary key of the Library to set the is_main to True, you can work with:

    from django.db.models import Q
    
    Library.objects.filter(user=my_user).update(
        is_main=Q(pk=my_pk)
    )

    You might also want to enforce at database level that there can only be one Library with is_main=True per user:

    from django.conf import settings
    from django.db.models import Q
    
    class Library(SocialLinksModelMixin):
        """
        Represents book shelves and places where people have / leave books.
        """
        user = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.CASCADE
        )
        is_main = models.BooleanField(default=False)
        
        class Meta:
            constraints = [
                models.UniqueConstraint(fields=('user',), condition=Q(is_main=True), name='one_main_per_user')
            ]