7

I am using Django REST generic views for my API endpoint. One of the field in my serializer has ManyToMany relationship. I want to show that field into my API endpoint, But getting this error

Lists are not currently supported in HTML input.

My view is this:

class AlertCreateView(ListCreateAPIView):
    permission_classes = (IsAuthenticated,)
    pagination_class = None
    serializer_class = AlertSerializer

    def get_queryset(self):
        queues = Queue.objects.all()
        for queue in queues:
           queryset = Alert.objects.filter(
               queue=queue
           )

        return queryset

My Serializer is this:

class AlertSerializer(serializers.ModelSerializer):
     queue = QueueSerializer(many=True)

     class Meta:
         model = Alert
         fields = (
             'id', 'name', 'queue','email', 'expected_qos'
         )
Aneesh R S
  • 3,807
  • 4
  • 23
  • 35

3 Answers3

5

What can I do ?

Not much since HTML form don't support nested serializers at the moment.

You could use a non nested relational field in the serializer to work this around or just use regular JSON.

Linovia
  • 19,812
  • 4
  • 47
  • 48
  • What's really weird is that I had lists working in HTML view with a nested Serializer... rebuilt my DB and pooof... they disappeared... – ness-EE Sep 02 '17 at 08:55
4

You do not need the get_queryset method you could do something like this:

#views.py
class AlertCreateView(ListCreateAPIView):
     queryset = Alert.objects.all()
     serializer_class = AlertSerializer
     permission_classes = (IsAuthenticated,)

Name the queues field in the serializer in the same way as it is written in therelated_name of the model. And your QueueSerializer can inherit fromPrimaryKeyRelatedField to be rendered.

#models.py
class AlertModel(models.Model):
    ...
    queues = models.ManyToManyField(Queue, ... related_name='queues')     
    ...

#serializer.py
class QueueSerializer(PrimaryKeyRelatedField, serializers.ModelSerializer):
    class Meta:
       model: Queue

class AlertSerializer(serializers.ModelSerializer):
    queues = QueueSerializer(many=True, queryset=Queue.objects.all())

    class Meta:
        model = Alert
        fields = (
         'id', 'name', 'queues','email', 'expected_qos'
        )
Hugo Brilhante
  • 596
  • 4
  • 13
  • 1
    Yep. I did the same thing. Thank you! –  Mar 03 '17 at 14:28
  • 1
    Thanks, this did the trick for me! However, after adding this, I can't get a list view of queues anymore. Whenever I do a GET request to /queues I get : ```__init__() takes 1 positional argument but 2 were given``` and when I remove the PrimaryKeyrelatedField argument, I dont get this error. Any ideas? – Max Taylor Dec 18 '17 at 13:59
  • 1
    This does NOT work if you want to embed the serialized object into another serializer, it'll just make it be the PK doing this. You might as well just use the PrimaryKeyRelatedField to begin with if that's what you wanted. – liquidpele Dec 05 '18 at 14:58
0

You can write your own ListField class with text input in forms using style parameter. But you also need to convert a value from text to list if it comes from a form.

import json

class TextInputListField(serializers.ListField):

    def __init__(self, *args, **kwargs):
        style = {'base_template': 'input.html'}
        super().__init__(*args, style=style, **kwargs)

    def get_value(self, dictionary):
        value = super().get_value(dictionary)
        is_querydict = hasattr(dictionary, 'getlist')
        is_form = 'csrfmiddlewaretoken' in dictionary
        if value and is_querydict and is_form:
            try:
                value = json.loads(value[0])
            except Exception:
                pass
        return value

Then use it instead of a usual ListField.

meequz
  • 1
  • 2