94 votes

Vérifier si OneToOneField est None dans Django

Je possède deux modèles de ce type :

class Type1Profile(models.Model):
    user = models.OneToOneField(User, unique=True)
    ...

class Type2Profile(models.Model):
    user = models.OneToOneField(User, unique=True)
    ...

J'ai besoin de faire quelque chose si l'utilisateur a le profil Type1 ou Type2 :

if request.user.type1profile != None:
    # do something
elif request.user.type2profile != None:
    # do something else
else:
    # do something else

Mais, pour les utilisateurs qui n'ont pas de profil de type 1 ou de type 2, l'exécution d'un tel code produit l'erreur suivante :

Type1Profile matching query does not exist.

Comment puis-je vérifier le type de profil d'un utilisateur ?

Merci

2voto

pymen Points 49

Au cas où vous auriez le modèle

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)

Et vous avez juste besoin de savoir, pour chaque utilisateur, si UserProfile existe ou non. le moyen le plus efficace du point de vue de la base de données, d'utiliser existe requête .

La requête Exists ne renverra qu'un booléen, au lieu de accès inversé aux attributs comme hasattr(request.user, 'type1profile') - qui générera obtenir une requête et retourner la représentation complète de l'objet

Pour le faire - vous devez ajouter une propriété au modèle User

class User(AbstractBaseUser)

@property
def has_profile():
    return UserProfile.objects.filter(user=self.pk).exists()

0voto

FreeWorlder Points 146

J'utilise une combinaison de has_attr et is None :

class DriverLocation(models.Model):
    driver = models.OneToOneField(Driver, related_name='location', on_delete=models.CASCADE)

class Driver(models.Model):
    pass

    @property
    def has_location(self):
        return not hasattr(self, "location") or self.location is None

0voto

pymen Points 49

L'un des approches intelligentes sera d'ajouter personnalisé champ OneToOneOrNoneField et utiliser il [fonctionne pour Django >=1.9]

from django.db.models.fields.related_descriptors import ReverseOneToOneDescriptor
from django.core.exceptions import ObjectDoesNotExist
from django.db import models

class SingleRelatedObjectDescriptorReturnsNone(ReverseOneToOneDescriptor):
    def __get__(self, *args, **kwargs):
        try:
            return super().__get__(*args, **kwargs)
        except ObjectDoesNotExist:
            return None

class OneToOneOrNoneField(models.OneToOneField):
    """A OneToOneField that returns None if the related object doesn't exist"""
    related_accessor_class = SingleRelatedObjectDescriptorReturnsNone

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('null', True)
        kwargs.setdefault('blank', True)
        super().__init__(*args, **kwargs)

Mise en œuvre

class Restaurant(models.Model):  # The class where the one-to-one originates
    place = OneToOneOrNoneField(Place)
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

Utilisation

r = Restaurant(serves_hot_dogs=True, serves_pizza=False)
r.place  # will return None

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X