Partage
  • Partager sur Facebook
  • Partager sur Twitter

Recursive many-to-many avec Django et DRF

    13 septembre 2017 à 16:45:20

    Salut !

    J'ai besoin de faire une many-to-many recursive mais je bloque :/

    Un jeu dois promouvoir plusieurs jeux et ce jeu peut être promu dans d'autres jeux. (Et aussi, chaque jeu a une liste d'assets).

    J'arrive a afficher la liste des jeux promus mais je n'arrive pas à en ajouter (ni en delete).

    J'ai pour l'instant ça:

    models.py

    class Game(models.Model):
        name = models.CharField(max_length=30, unique=True, blank=False, null=False)
        promote_games = models.ManyToManyField("self",
                                               through='GamePromoted',
                                               symmetrical=False, )
    
        class Meta:
            db_table = 'Game'
    
    
    class GamePromoted(models.Model):
        game = models.ForeignKey(Game, related_name='games_promoted')
        game_promoted = models.ForeignKey(Game, related_name='games')
    
        class Meta:
            db_table = 'Game_Promoted'
            # unique_together = ('game', 'game_promoted')


    serializers.py

    class AssetSerializer(serializers.ModelSerializer):
        class Meta:
            model = Asset
            fields = ('id', 'file_path', 'created_at', 'updated_at')
    
    
    class GamePromotedSerializer(serializers.ModelSerializer):
        id = serializers.PrimaryKeyRelatedField(source='game_promoted.id', read_only=True)
        name = serializers.CharField(source='game_promoted.name', read_only=True)
        assets = AssetSerializer(source='game_promoted.assets', many=True, read_only=True)
    
        class Meta:
            model = Game
            fields = ('id', 'name', 'assets')


    Et je voudrais un résultat de ce genre quand je fais un GET /games

    {"id":1,"name":"Game1","assets":[{...}],"games_promoted":[{"id":1,"game_id":2,"name":"Game2""assets":[{...}]},{"id":2,"game_id":3,"name":"Game3""assets":[{...}]}]}

    Et j'aimerais pouvoir ajouter un jeu à promouvoir en faisant:

    POST /games/{id}/ (promote_game={id du jeu à promouvoir}

    Si vous avez une solution, je vous remercie d'avance ! 

    -
    Edité par rafikikiki 13 septembre 2017 à 16:46:01

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      13 septembre 2017 à 17:07:16

      Je connais pas django, mais apparemment la méthode add pour ajouter, et la méthode remove pour retirer, non ?
      • Partager sur Facebook
      • Partager sur Twitter
        13 septembre 2017 à 17:31:50

        oldProgrammer a écrit:

        Je connais pas django, mais apparemment la méthode add pour ajouter, et la méthode remove pour retirer, non ?


        C'est plus compliqué que ça ^^, en faite je suis en train de faire une API RESTful et je ne vois pas comment et ou ajouter la fonction qui va ajouter la relation entre les 2 jeux.

        Et j'utilise Django Rest Framework.

        -
        Edité par rafikikiki 13 septembre 2017 à 17:34:26

        • Partager sur Facebook
        • Partager sur Twitter
          13 septembre 2017 à 17:55:02

          Oops j'avais pas vu la reponse lors de la redaction de ma reponse :)

          Dans ton cas, il faut que tu fasse une route sur cette url (dans urls.py) en récupérant l'id du jeu de base et du jeu a pourvoir. Tu peux récupérer les id en suivant cette doc

          Ensuite il faut juste faire une fonction dans ton views.py qui prend ses 2 ids et le sauvegarde avec le add dans ton modele

          _____________________

          Bonjour,

          Sauf erreur ce que tu recherches ça ressemble plus a du NoSQL. Tu peux regarder du coté de MongoDb pour stocker les n_promoted games dans la table de game. La partie serializer je n'ai pas tout compris :D

           Pour ce qui est de l'ajout, il semblerait qu'en effet add et remove soient les méthodes a utiliser (info) avec :

          main_game.promote_games.add(another_promoted_game)
          main_game.promote_games.remove(the_promoted_game)

          Tu n'as pas besoin de le faire dans les 2 sens normalement

          -
          Edité par coni63 13 septembre 2017 à 18:01:24

          • Partager sur Facebook
          • Partager sur Twitter
            13 septembre 2017 à 18:29:16

            coni63 a écrit:

            Oops j'avais pas vu la reponse lors de la redaction de ma reponse :)

            Dans ton cas, il faut que tu fasse une route sur cette url (dans urls.py) en récupérant l'id du jeu de base et du jeu a pourvoir. Tu peux récupérer les id en suivant cette doc

            Ensuite il faut juste faire une fonction dans ton views.py qui prend ses 2 ids et le sauvegarde avec le add dans ton modele

            _____________________

            Bonjour,

            Sauf erreur ce que tu recherches ça ressemble plus a du NoSQL. Tu peux regarder du coté de MongoDb pour stocker les n_promoted games dans la table de game. La partie serializer je n'ai pas tout compris :D

             Pour ce qui est de l'ajout, il semblerait qu'en effet add et remove soient les méthodes a utiliser (info) avec :

            main_game.promote_games.add(another_promoted_game)
            main_game.promote_games.remove(the_promoted_game)

            Tu n'as pas besoin de le faire dans les 2 sens normalement

            -
            Edité par coni63 il y a 11 minutes

            Merci :)

            Je viens d'override la fonction create dans mon views.py

                def create(self, request, *args, **kwargs):
                    game = Game.objects.get(id=self.kwargs['game_id'])
                    game_promoted = Game.objects.get(id=request.data['game_promoted'])
                    serializer = GameSerializer(game)
                    GamePromoted(game=game, game_promoted=game_promoted).save()
                    headers = self.get_success_headers(serializer.data)
                    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

             Mais comment je peux faire pour obliger l'user à mettre comme paramètre dans la méthode POST : game_promoted ?

            Avec ça, j'arrive à bien à save la relation dans ma DB mais c'est surtout pour la gestion d'erreur:

            - Si le le game n'existe pas ?

            - Si le game_promoted n'existe pas ?

            - Si le client ne met pas comme paramètre game_promoted ?

            Merci de ton aide ! Tu m'as bien fait avancer déjà !

            -
            Edité par rafikikiki 13 septembre 2017 à 18:32:12

            • Partager sur Facebook
            • Partager sur Twitter
              13 septembre 2017 à 18:56:20

              rafikikiki a écrit:

               Mais comment je peux faire pour obliger l'user à mettre comme paramètre dans la méthode POST : game_promoted ?

              - Si le le game n'existe pas ?

              - Si le game_promoted n'existe pas ?

              - Si le client ne met pas comme paramètre game_promoted ?

              Merci de ton aide ! Tu m'as bien fait avancer déjà !

              -
              Edité par rafikikiki il y a 16 minutes

              Alors comment obliger le user ... J'aurais tendance a dire que si tu veux qu'un user promote un jeu, tu dois lui fournir un outil simple. Un simple boutton "promote" a coté de chaque jeu ou qqch du genre. Lorsqu'il clique, le js va créer le requête et la poster (regarde du coté de $POST en JQuery c'est super simple)

              Ensuite pour les 3 "si", j'ai envie de te dire que tu n'auras pas le choix, il n'y a pas de recette magique. Premièrement il faut TOUJOURS vérifier les input des utilisateurs. Dis toi qu'il y aura toujours un petit c** qui va tester des requêtes insensé (par exemple avec greasemonkey). Du coup, tu dois vérifier que ce que tu reçois est valide (par exemple des entiers uniquement), qu'ils correspondent bien à des jeux et si oui ça ajoute l'entrée, sinon tu renvoie un code erreur que tu lui affiche en js (par exemple avec un alert). C'est sur que 99.999 % du temps, le code que tu auras codé sera valide mais s'il y a une faille, quelqu'un trouvera ce 0.0001 % (du moins pour un site public, si c'est pour un intranet, tu peux être plus tolérant).

              -
              Edité par coni63 13 septembre 2017 à 18:57:53

              • Partager sur Facebook
              • Partager sur Twitter

              Recursive many-to-many avec Django et DRF

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown