Confused about editing many to many field with Editor

Confused about editing many to many field with Editor

ruzqatruzqat Posts: 4Questions: 1Answers: 0

Hi, I'm pretty confused about my many-to-many field editing. I've tried about 10 different approaches with different errors every time.

Currently I'm getting: {"type":["This field is required."],"companyname":["This field is required."]}

I have two simple Models:

class Companiestypechoice(models.Model):
    business_type = models.CharField(max_length=50)

class Companies(models.Model):
    companyname = models.CharField(max_length=100)
    type = models.ManyToManyField(Companiestypechoice)

Two serializers:

class TypeSerializer(serializers.ModelSerializer):

    class Meta:
        model = Companiestypechoice
        fields = ('__all__')

class CompanySerializer(serializers.ModelSerializer):
    type = TypeSerializer(many=True)

    class Meta:
        model = Companies
        fields = ('__all__')

A viewset:

class CompanyViewSet(viewsets.ModelViewSet):
    queryset = Companies.objects.all().order_by('companyname')
    serializer_class = CompanySerializer

My JSON looks like this:

[
{ "id":  1, "type":  [
{ "id":  1,"business_type":  "Customer" }  ],
"companyname" :  "AB flight"  },

{ "id":  2, "type":  [
{ "id":  1,"business_type":  "Customer"  },
{ "id":  2,"business_type":  "Supplier"  } ],
"companyname":  "Alitalia"  },

{ "id":  3, "type":  [
{ "id":  1,"business_type":  "Customer"  }  
] etc...

As per the manual I'm using column.data option to display business type/s in cells.
columns: [ { data: "type.[, ].business_type" ... } ]

Which works great.

When but when I try to edit or create the fields it gives me
BAD REQUEST 400: "type":["This field is required."],"companyname":["This field is required."]

My HTML:

$(document).ready(function() {
    editor = new $.fn.dataTable.Editor( {
        ajax: {
        url: "api/companies.json",
        headers: {'X-CSRFToken': '{{ csrf_token }}'}
        },
        table: "#table_id",
        idSrc:  'id',
        fields: [
            {
                label: "Company name:",
                name: "companyname"
            },
            {
                label: "Type:",
                name: "type.[, ].business_type",
             },
                   ]
    } );


    oTable = $('#table_id').DataTable( {
        dom: "Blrtip",
        ajax: {
            url: "api/companies.json",
            dataSrc: ''
        },

        columns: [
        {   data: "id",
            visible: false,
            searchable: false
        },
        {   data: "companyname",
             title: "Comany Name"
        },

        {    data: "type.[, ].business_type",
              title: "Business type"
        }

                          ],

        select: true,
        buttons: [
            { extend: "create", editor: editor },
            { extend: "edit",   editor: editor },
        ]
    } );
} );

I've tried django-datatables-editor library, but still cannot make it work. I've tried setting up create fuctions in ViewSet, but to no avail. In case of many-to-many relations how does DRF know which table does it need to enter data into? Do I need to explicitly specify, or does it go to model reference first and follows the M2M from there. Sorry I'm really new to DRF.

Thank you in advance!

Answers

  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin

    Hi,

    I'm afraid I can't help you with the Django part of it as that isn't written by me and I have no knowledge of Django in general - but I can hopefully help with the client-side part and what the client sends to the server and expects back in turn.

    The first part is to check if the api/companies.json route expects POST parameters as described here? This might be one that you need to ask the django-datatables-editor library author I'm afraid.

    Allan

  • ruzqatruzqat Posts: 4Questions: 1Answers: 0

    Hi!

    Thank you for your quick response!

    I guess that is a django related question.

    My API says this route accepts POST request and I've also checked with api/companies/ but the result is the same

    I've dug a little deeper, and the error is not related to many-to-many field (sorry). I've removed it and error presist.

    Apparently, "This field is required" is a django 'empty' validator error. It thinks that I'm trying to submit an empty field. It also checks for default values and as soon as I set the default value for the field It accepted my entry with no error, but set default value. I will look further, I'm not yet sure why it thinks the field is empty. The payload seems to say otherwise.

    data[0][companyname]: Ryanair
    action: create
    
    data[4][companyname]: Montenegro Airlines
    action: edit
    
  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin

    I'd be interesting to know what you find out please :). Equally, if you have any questions about what the client-side is doing, just shoot them through.

    Allan

  • ruzqatruzqat Posts: 4Questions: 1Answers: 0
    edited October 2022

    Hey!

    So I think the issue as you've pointed out was with the POST method. I didn't get to figure out a way with my the outlined setup so I simply went back to using the django-datatalbes-editor library and as soon as I've switched from ModelViewSet to DatatablesEditorModelViewSet it started accepting my create and edit entries for normal fields.

    I'm still unable to figure out a Many-to-Many field create and edit though.
    I've tried several approaches, but they throw various errors.
    Datatalbes are rendering fine, I'm able to view the nested data, but Editor is a bit of a difficulty.

    With my initial setup it gave me this error:

    "Expected a list of items but got type "str"."

    I tried to play around with the field.name option, but couldnt figure out a way. It is either that or for example with:
    {...
    type: "select",
    multiple: true
    ...}

    I was hoping it would send it as a list but it changed to:
    "Expected a list of items but got type "dict"."

    I've tried switching from having serializer within a serializer and going with a "depth=1" method in Meta options in a single serializer, as per the Django Rest Framework manual and with that my JSON structure did not change, but submitting then throws:
    "The following fields are present in the request, but they are not writable: type"
    I've tried many other options again with field.name, but no bueno.

    Sorry if this are really basic questions:
    Is there a way to pass a list of items on submit? Or do I need to find a different way to structure my JSON for example nesting objects instead of arrays like in your example: https://editor.datatables.net/examples/advanced/deepObjects.html

  • ruzqatruzqat Posts: 4Questions: 1Answers: 0

    With a few tweaks, I was able to change my JSON to another format.

    { "data":[
    { "id":1,"name" : "AB fligh", "type" : "Customer"},
    { "id":2,"name" : "Antalia" , "type" : "Customer, Supplier"},
    { "id":3,"name" : "KLMss" , "type" : "Supplier"}...]
    

    In case anybody will follow my steps I changed my serializer to:

    type = serializers.SerializerMethodField()
    def get_type(self, Companies):
            return ', '.join([str(type) for type in Companies.type.all()])
    

    This changed my JSON format, but gave the same error as depth = 1 option: fields not writable.

    Then I also tried serialize "type = serializers.PrimaryKeyRelatedField" with a separate create method

        def create(self, validated_data):
            source_companies = validated_data.pop('source_companies', [])
            company = Companies.objects.create(**validated_data)
            for source in source_companies:
                company.source_products.add(source)
            return company
    

    But with the same result.

    Finally I went back to my original setup and tried to play with select field options (https://editor.datatables.net/reference/field/select), but couldn't figure out a way to pass a list. At the moment I'm stuck with
    {type: {non_field_errors: ["Expected a list of items but got type "str"."]}.

    I'm sure this is something trivial, but I really can't think of any other way to advance.

  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin

    Hi,

    What do you need to pass to the server in order to have it create a list (rather than a dictionary or a string)?

    Allan

Sign In or Register to comment.