Comments on: Accepter un ID mais retourner un objet pour les liens de Django Rest Framework http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/ Du code, du cul Mon, 28 Oct 2019 11:54:55 +0000 hourly 1 https://wordpress.org/?v=4.9.7 By: Sam http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-188408 Sun, 23 Jul 2017 14:07:14 +0000 http://sametmax.com/?p=23385#comment-188408 @buffalo974 : crayon et papier d’abord :)

Après lire le code source d’un projet externe ça demande vraiment d’être expérimenté, faut pas déconner. Souvent on entend des gens dire “lisez les sources ça fait progresser”, mais y a un fossé entre pouvoir jeter un coup d’oeil à un fichier et comprendre toutes les implications dans un projet. Pour ce dernier, il faut avoir codé pas mal de projets soi-même.

Pour ce cas là ça m’a pris une bonne demi-heure à une heure. Je savais déjà ce que je voulais faire car j’avais cherché longtemps un moyen de le faire. Donc j’ai juste regardé le code source du truc qui me le permettait pas, et j’ai tenté de le modifier jusqu’à ce que ça marche dans un test unitaire à l’arrache. La tricherie c’est que DRF utilise pas mal de design patterns que je connais bien, et ça change tout car quand je le vois faire quelque chose, ça me parle. D’autant que j’avais déjà regardé le code source de DRF dans des missions précédents et ce n’était pas une base non familière.

@lollo : DRF marchera très bien pour ça, on peut tout faire sans ORM. Mais vue que tu fais un sous appel à un autre système derrière pour des raisons de perfs tu voudras peut être plutôt taper dans un framework asynchrone. Cherche un micro framework tout simple si c’est le cas. L’avantage de DRF c’est qu’il gère toute l’authentification, et c’est pas rien sur une API. Le désavantage c’est que c’est un gros morceau.

@Pyglouthon : c’est pas faux :)

]]>
By: Pyglouthon http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187710 Tue, 13 Jun 2017 06:01:18 +0000 http://sametmax.com/?p=23385#comment-187710 C’est certes pratique d’avoir ce petit helper dans le projet mais la solution de Fabs me semble simple et efficace.

Je ne fais plus trop de Django depuis un moment mais sur mes projets Flask + marshmallow je définis aussi mon schema (~serializer) avec des champs en dump_only et d’autres en read_only. T’es pas tant que ça une grosse feignasse vu comme tu te fais chier à aller fouiner le code source pour faire ta tambouille. T’es surtout un bon geek curieux, un macgyver du Python web :-)

Faut vraiment que je sois bloqué par les limites du package ou que la doc soit inexistantes pour en arriver là. Bon c’est vrai, ça arrive souvent avec les packages pour flask.

]]>
By: lollo http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187702 Mon, 12 Jun 2017 20:06:31 +0000 http://sametmax.com/?p=23385#comment-187702 Bonjour,

Trop bien cet article.

J’ai un truc a faire depuis des mois et je m’y suis pas encore attelé.. surement car j’ai pas encore la BONNE solution.

J’ai un point API json_rcp assez sale et verbeux auquel je peux pas toucher, car utilisé dans une autre condition.

Je veux donc faire un bridge API json_rpc qui expose des methodes faisant intervenir plusieurs appel json, changeant la structure et filtrant les data.

je me demande quel est le top framework REST pour faire ca.. Car les solutions que j’ai trouvé sont assez dependante de l’ORM

]]>
By: buffalo974 http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187679 Sun, 11 Jun 2017 20:57:24 +0000 http://sametmax.com/?p=23385#comment-187679 C’ est quoi ta methodologie quand tu t’attaques à un probleme costaud ?

Tu passes simplement ta paume sur la doc à la Matrix ?

Ou tu fais des dessins au crayon, ou tu utilises un UML generator pour visualiser vite fait la tuyauterie ?

quand je regardes des codes sources sur nullege, arrivé en bas du fichier, ma mémoire et déjà saturée depuis 5 minutes… Alors pour trouver un hack , jte racontes pas le fossé.

Combien de temps ça t’a pris à cogiter pour ce cas en particulier ?

]]>
By: Blob http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187677 Sun, 11 Jun 2017 16:05:28 +0000 http://sametmax.com/?p=23385#comment-187677 Oui, j’ajoute de l’information alors ;-)

Les corrections sont au niveau de la méthode from_serializer et de l’appel dans le serializer.

Dans la méthode from_serializer, pour respecter la méthode type, il faut que le 2ème argument soit un tuple: [cls] -> (cls,)

Comme on passe une classe et non une instance, on ne peut pas faire serializer.class.name mais plutôt serializer.__name__

Enfin au niveau du serializer, on utilise la méthode de classe from_serializer à laquelle on passe la classe du serializer à utiliser, ce qui nous donne une nouvelle classe de laquelle on appelle le constructeur:

bar = AsymetricRelatedField.from_serializer(BarSerializer)()

En tout cas, ce que je n’avais pas mis dans mon premier post, l’idée est vraiment très bonne ! En plus elle tombe à pic et solutionne un problème que j’avais la veille.

Dommage que la proposition ne soit pas passée et même si je comprend les raisons, on fait bien ce qu’on veut avec nos APIS !

Encore un bon article donc :-)

]]>
By: Sam http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187665 Sat, 10 Jun 2017 15:47:57 +0000 http://sametmax.com/?p=23385#comment-187665 Il faut que tu précise ce qui ne marchait pas et ce que tu as corrigé.

]]>
By: Blob http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187647 Fri, 09 Jun 2017 13:53:27 +0000 http://sametmax.com/?p=23385#comment-187647 Bon comme ça ne marchait pas directement chez moi, je poste la version “corrigée”:

D’un côté dans un helpers.py:

from collections import OrderedDict

from rest_framework import serializers

class AsymetricRelatedField(serializers.PrimaryKeyRelatedField):

# en lecture, je veux l'objet complet, pas juste l'id
def to_representation(self, value):
    return self.serializer_class(value).data

# petite astuce perso et pas obligatoire pour permettre de taper moins
# de code: lui faire prendre le queryset du model du serializer
# automatiquement. Je suis lazy
def get_queryset(self):
    if self.queryset:
        return self.queryset
    return self.serializer_class.Meta.model.objects.all()

# Get choices est utilisé par l'autodoc DRF et s'attend à ce que
# to_representation() retourne un ID ce qui fait tout planter. On
# réécrit le truc pour utiliser item.pk au lieu de to_representation()
def get_choices(self, cutoff=None):
    queryset = self.get_queryset()
    if queryset is None:
        return {}

    if cutoff is not None:
        queryset = queryset[:cutoff]

    return OrderedDict([
        (
            item.pk,
            self.display_value(item)
        )
        for item in queryset
    ])

# DRF saute certaines validations quand il n'y a que l'id, et comme ce
# n'est pas le cas ici, tout plante. On désactive ça.
def use_pk_only_optimization(self):
    return False

# Un petit constructeur pour générer le field depuis un serializer. lazy,
# lazy, lazy...
@classmethod
def from_serializer(cls, serializer, name=None, args=(), kwargs={}):
    if name is None:
        name = f"{serializer.__name__}AsymetricAutoField"

    return type(name, (cls,), {"serializer_class": serializer})

Et dans serializers.py:

class FooSerializer(serializers.ModelSerializer):

bar = AsymetricRelatedField.from_serializer(BarSerializer)()

class Meta:
    model = Foo
    field=('bar', 'name')

]]>
By: Fabs http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187644 Fri, 09 Jun 2017 12:55:52 +0000 http://sametmax.com/?p=23385#comment-187644 Pour info, comme soumis dans le ticket, nous utilisons cette solution :

class FooSerializer(serilizers.ModelSerializer):
    
    bar = BarSerializer(read_only=True)
    bar_id = serializers.PrimaryKeyRelatedField(source='bar',  queryset=Bar.objects.all(), )

    class Meta:

        model = Foo
        fields = ('bar', 'bar_id', )

]]>
By: Mask http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187632 Thu, 08 Jun 2017 12:46:31 +0000 http://sametmax.com/?p=23385#comment-187632 Ha bah.. Il tombe à pic cet article..

Je m’embête depuis ce matin à trouver un truc propre, j’étais parti sur la solution 1, mais effectivement, refaire l’écriture à la main, c’est pas la joie.

Merci pour l’astuce.

]]>
By: Sam http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/#comment-187630 Thu, 08 Jun 2017 10:37:13 +0000 http://sametmax.com/?p=23385#comment-187630 Glop

]]>