Editable ManyToMany field with HyperlinkedRelatedField does not deserialize into a list

24 views
Skip to first unread message

Fabian Sturm

unread,
Jun 5, 2020, 4:57:15 PM6/5/20
to Django REST framework
Hello everybody,

I am struggling getting the following to work. I have a model with a ManyToMany realationship and I want it to be updateable through the Web API of the DjangoRestFramework.

class Topping(models.Model):
    name = models.CharField(max_length=255)

class Pizza(models.Model):
    name = models.CharField(max_length=255)
    creator = models.ForeignKey(User)
    toppings = ManyToManyField(Topping, related_name='pizzas', blank=True)


My Pizza serializer looks like this:

class PizzaSerializer(ExpanderSerializerMixin, serializers.HyperlinkedModelSerializer):
    id = serializers.IntegerField(read_only=True)

    topping_queryset = models.Topping.objects.all()
    toppings = serializers.HyperlinkedRelatedField(queryset=topping_queryset, view_name='topping-detail', style={'base_template': 'input.html'}, many=True)

    """
    Create and return a new `Pizza` instance
    """
    def create(self, validated_data):
        return models.Pizza.objects.create(**validated_data, creator=self.context['request'].user)

    class Meta:
        model = models.Pizza
        fields = '__all__'
        read_only_fields = ('creator',)
        expandable_fields = {
            'creator': UserSerializer,
            'toppings': (ToppingSerializer, (), {'many': True},),
        }

Displaying the pizzas and their toppings works fine but when I e.g. want to update an existing pizza the toppings field in the browser is displayed like this:


Which in my opinion looks fine. But it ends up with the error message ""Invalid hyperlink - No URL match."" when I send a PUT request.

The reason seems to be that the input is not properly parsed into a list of two elements but it ends up being a list with a single item which is the string from above ["[\'http://localhost:8000/api/v2/toppings/3/\', \'http://localhost:8000/api/v2/toppings/2/\']"]
It seems that the request parsing happens in django/http/requests.py and it would expect multiple toppings entries instead of a single one as list.

What would I need to change so that the list is properly parsed?

The versions i am currently running are:
Django==1.11.29
djangorestframework==3.11.0
djangorestframework-expander==0.2.3

Thanks a million, I am really stuck by now.
Fabian



Yezileli Ilomo

unread,
Jun 6, 2020, 3:15:57 AM6/6/20
to django-res...@googlegroups.com
Looks like you haven't written the code to handle update on your nested field, remember DRF doesn't handle updates on nested fields automatically. If you don't want to write code for handling update on nested fields you could use a third party DRF library like https://github.com/yezyilomo/django-restql 

--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-rest-framework/eacec7a8-fd49-460c-9568-dd489431acfbo%40googlegroups.com.

Fabian Sturm

unread,
Jun 6, 2020, 10:21:38 AM6/6/20
to Django REST framework
Hell Yezileli,

thanks for the info and help! I think I now got behind the problem. What I just now found out that everything works perfectly as long as I am using json as input. So my serializer code itself seems to be ok.
What actually created the problems was setting the template to input.html. This does not seem to work with manytomany relations since it sends the input as a single string.
If I change the style to select_multiple (or omit it all together) it works!

So while my code now works it creates a different problem. I actually have thousands of toppings (as it is an example, they are not really toppings...). And even though the select_multiple widget seems to limit the toppings it renders to the first 10 it loads forever (30 seconds versus 1). I think this is actually the reason why the different template was selected in the first place. To allow changing the toppings in the html form without the load penalty. Except that it never worked of course.

Any idea how to combat this problem? If there is nothing to make it quicker I would be also happy to have it read-only for the html form but read write for json or something similar...

But at least I now have a new problem I can research on, so maybe I find something on the internet for this...

Thanks a lot,
Fabian
Reply all
Reply to author
Forward
0 new messages