Récemment, lorsque j'ai à nouveau créé un modèle pour la fonction de suivi avec Django, j'ai essayé d'utiliser l'argument through
et j'ai trouvé un modèle facile à écrire, donc je l'ai écrit sous forme d'article.
Je ne l'ai pas écrit de manière particulièrement avancée, mais lorsque j'ai recherché la fonction de suivi, je n'ai pas trouvé de modèle comme celui-ci, donc j'espère que cela sera utile pour ceux qui créent des fonctions similaires.
Dans Django, il existe trois manières principales d'écrire un modèle qui représente plusieurs-à-plusieurs.
ManyToManyField
ManyToManyField
created_at
).through
de ManyToManyField
#suiveur de user1/Obtenez tous les abonnés
user1.followers.all()
user1.followees.all()
#Liste d'éléments des utilisateurs suivis par user1(Chronologie sur Twitter)Avoir
Item.objects.filter(user__followers=user1)
#user1 suit user2
user1.followee_friendships.create(followee=user2)
Vous pourrez écrire comme ça.
class FriendShip(models.Model):
follower = models.ForeignKey('User', on_delete=models.CASCADE, related_name='followee_friendships')
followee = models.ForeignKey('User', on_delete=models.CASCADE, related_name='follower_friendships')
class Meta:
unique_together = ('follower', 'followee')
Un modèle intermédiaire qui représente les relations de suivi. La «clé étrangère» est dirigée vers chacun en tant que suiveur et suiveur du modèle User.
L'argument ʻon_deleteest
models.CASCADEcar ces relations doivent également être supprimées lorsque l'utilisateur est supprimé. Si cela supprime les données cibles de
Foreignkey`, ces données seront également supprimées automatiquement.
related_name
Si vous utilisez plusieurs Foreignkey
s pour la même classe, vous devez définir related_name
ou vous obtiendrez une erreur au moment de la commande manage.py make migrations
. En définissant cela, il est possible de faire référence à ce modèle dans le sens opposé à la destination de connexion de la clé externe.
Ici, follower_friendships
se comporte comme des objets
. Par exemple, les deux lignes suivantes ont la même signification.
Friendship.objects.create(follower=user1, followee=user2)
user1.followee_friendships.create(followee=user2)
Celles-ci représentent les suivis de «utilisateur1» à «utilisateur2».
unique_together Il s'agit de définir une contrainte que la combinaison est unique.
Il y a toujours une combinaison d'abonnés pour les abonnés, et la création de plusieurs abonnés est un comportement anormal, alors définissez ceci.
De plus, il semble qu'il n'y ait pas d'erreur même s'il y a un suivi et un suivi inversés (soi-disant suivi mutuel).
class User(AbstractUser):
followees = models.ManyToManyField(
'User', verbose_name='Utilisateurs suivant', through='FriendShip',
related_name='+', through_fields=('follower', 'followee')
)
followers = models.ManyToManyField(
'User', verbose_name='Utilisateurs suivis', through='FriendShip',
related_name='+', through_fields=('followee', 'follower')
)
AbstractUser
ʻAbstractUser est pour étendre l'utilisateur par défaut. ʻUtilisé lors de l'écrasement ou de l'ajout d'un nouveau champ que l'utilisateur
a déjà.
Cela a déjà de meilleures informations, alors consultez le commentaire ou la documentation officielle pour plus de détails.
ManyToManyField
Le modèle FriendShip
est spécifié dans l'argument through
. Vous pouvez maintenant obtenir les données via le modèle intermédiaire en appelant simplement suivis
, suiveurs
.
related_name Spécifier «+» indique que la référence arrière n'est pas requise. La documentation dit:
If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'. For example, this will ensure that the User model won’t have a backwards relation to this model:
https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ForeignKey.related_name
through_fields
Lorsque vous ciblez une donnée et une autre donnée associée dans ManyToManyField
comme source et cible, passez (source, cible) ʻ dans l'argument
through_fields`.
ʻUser.followee veut obtenir le suiveur d'un utilisateur, alors spécifiez
('suiveur', 'followee') , et ʻuser.follower
spécifie le contraire.
Si vous spécifiez une référence arrière avec related_name
, vous n'avez besoin que d'unManyToManyField
.
class User(AbstractUser):
followers = models.ManyToManyField(
'User', verbose_name='Utilisateurs suivis', through='FriendShip',
related_name='followees', through_fields=('followee', 'follower')
)
Cependant, il semble que ce ne sera pas pratique de spécifier verbose_name
, il vaut donc mieux en déclarer deux.
Recommended Posts