[PYTHON] [Django] Pattern pour ajouter des enregistrements associés après avoir créé un enregistrement

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

Utiliser des signaux

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.

avantage

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.

Ajouté à la méthode de création

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()

avantage

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.

Utilisez form_valid

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())

avantage

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

Utiliser des sérialiseurs.SerializerMethodField ()

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

avantage

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.

Résumé

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

[Django] Pattern pour ajouter des enregistrements associés après avoir créé un enregistrement
Étapes de l'installation de Python 3 à la création d'une application Django
Ajouter un dictionnaire à MeCab
Création d'une application de gestion de score shogi à l'aide de Django 1-Construction de l'environnement-
Pour ajouter un module C à MicroPython ...
Étapes pour créer un projet Django
Erreur liée à memcached dans django
[Django 2.2] Ajouter un nouveau badge aux nouveaux messages avec une date à l'aide d'un filtre de modèle
Ajoutez une carte GPIO à votre ordinateur. (1)
Comment ajouter un package avec PyCharm
Commandes pour créer un nouveau projet django
Créer un écran de connexion dans Django all auth
Créer un script shell pour écrire un journal
Ajouter un environnement virtuel Python à VSCode