Il existe de nombreux cas où vous souhaitez créer un enregistrement lié lors de l'enregistrement d'un enregistrement sur le site ou de l'ajout d'un enregistrement à l'aide de l'API. Cette fois j'ai essayé de résumer le code qui le réalise avec différents patterns de Django. Veuillez noter que les exemples donnés ici ne sont que ceux que vous avez implémentés, vous pouvez donc les implémenter de bien d'autres manières.
Il existe également une implémentation dans django-rest-framework (DRF).
Django
Le modèle le plus simple et le plus polyvalent consiste à utiliser des signaux. Dans Django, lorsqu'une action spécifique se produit, un signal est envoyé en conséquence et un processus spécifique peut être exécuté.
from django.contrib.auth.models import AbstractBaseUser
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.crypto import get_random_string
class User(AbstractBaseUser):
pass
class Token(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='token')
token = models.CharField("jeton", max_length=40)
@receiver(post_save, sender=User)
def create_token(sender, **kwargs):
"""Générer un jeton lors de la création d'un utilisateur"""
if kwargs['created']:
#Get au lieu de hash car c'est un exemple_random_string
Token.objects.create(user=kwargs['instance'],
token=get_random_string(length=40))
Puisqu'il s'agit d'un signal lorsque l'enregistrement est sauvegardé, il reçoit le signal «post_save».
Pour la fonction qui reçoit le signal, utilisez le décorateur @ receiver
.
Une fois créé, kwargs ['created'] = True
.
L'instance créée est stockée dans kwargs ['instance']
, qui peut être utilisée pour créer des enregistrements associés.
L'avantage de l'utilisation des signaux est que vous pouvez également générer des enregistrements associés en ajoutant des enregistrements à partir du site de gestion. Comme il est exécuté par n'importe quelle méthode de création telle que site de gestion, shell, formulaire, API, il peut être utilisé dans divers modèles. Inversement, cela signifie également que les enregistrements seront créés dans n'importe quelle situation.
La conception de Django recommande de travailler avec Model Manager pour travailler avec des enregistrements. Créez une méthode pour créer des enregistrements dans ModelManager et créez des objets associés dans cette méthode.
from django.contrib.auth.models import BaseUserManager
class UserManager(BaseUserManager):
use_in_migrations = True
def create_user_and_token(self, email, password, **extra_fields):
if not email:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
#Création d'objets associés
Token.objects.create(user=user,
token=get_random_string(length=40))
return user
class User(AbstractBaseUser):
objects = UserManager()
Si vous lui donnez un nom descriptif comme create_user_and_token
,
La bonne chose est que vous pouvez reconnaître qu'il s'agit d'une méthode qui crée également des objets associés.
Vous pouvez également passer des arguments, même si la structure de l'objet associé change Il est facile à entretenir car il vous suffit de changer cette méthode.
Avec generic.CreateView
, cela peut être réalisé en écrivant un petit form_valid.
from django.views.generic import CreateView
from django.contrib import messages
class View(CreateView):
form_class = UserModelFormClass # modelForm
def form_valid(self, form):
self.object = form.save()
#Création d'objets associés
token = Token.objects.create(user=self.object,
token=get_random_string(length=40))
messages.success(self.request, f"J'ai également créé un jeton: {token.token}")
return HttpResponseRedirect(self.get_success_url())
L'avantage est qu'il nécessite une quantité de description relativement faible. CreateView est souvent utilisé pour créer des enregistrements, c'est donc l'une des options. De plus, si vous souhaitez afficher un message à l'aide de l'objet créé, il semble bon de le décrire ici.
Django REST Framework
Dans DRF, vous pouvez définir un champ appelé «SerializerMethodField» dans le sérialiseur.
La valeur définie dans ce champ renvoie la valeur de retour de la méthode get_ <field_name>
.
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
token = serializers.SerializerMethodField()
class Meta:
model = User
fields = (
'pk',
'email',
'name',
'password',
'profile',
'token',
)
def get_token(self, instance):
#instance contient l'instance créée
return APIToken.object.create(instance).token
C'est un bon point de pouvoir écrire simplement lors du renvoi des valeurs associées créées en même temps lors de la création de données avec l'API. Le remplacement de la «création» du «ViewSet» tend à allonger la vue.
Pour être honnête, je pense qu'il est préférable d'utiliser des signaux ou d'implémenter des méthodes de création pour la plupart des cas d'utilisation, mais on m'a dit qu'il y a des endroits où je peux écrire clairement.
Recommended Posts