Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRF choices not set in MultiChoiceField serializer field #63

Open
MattFanto opened this issue Nov 11, 2020 · 1 comment
Open

DRF choices not set in MultiChoiceField serializer field #63

MattFanto opened this issue Nov 11, 2020 · 1 comment

Comments

@MattFanto
Copy link

I'm using this library to provide metadata information for a frontend application, one of the field in my model is a simple M2M mapped to "static" table with 15 entries.

class Waste(models.Model):
    cer = models.CharField(verbose_name='Codice CER', null=True, blank=True, max_length=10, choices=CER_CODES)
    descr = models.CharField(verbose_name='Descrizione rifiuto', null=True, blank=True, max_length=300)
    unofficial_descr = models.CharField(verbose_name='Descrizione informale del rifiuto', null=True, blank=True, max_length=300)
    categ_rifiuto = models.CharField(verbose_name='Tipologia rifiuto', null=True, blank=True, max_length=20, choices=CHOICES_CATEG_RIF)
    haz = models.BooleanField(verbose_name='Pericoloso', default=False)  # MAYBE default None?
    hp = models.ManyToManyField(HP, verbose_name='Proprietà di pericolo', blank=True)

For that reason, in the related serializer I decided to use MultiChoiceField

class WasteSerializer(serializers.ModelSerializer):
    hp = serializers.MultipleChoiceField(choices=tuple(HP.objects.all().values_list('code', 'descr')), label='Proprietà di pericolo')

    def create(self, validated_data):
        # custom code to set hp appropriately

    class Meta:
        model = Waste
        fields = '__all__'

Unfortunately the available choices are not rendered in the metadata response, the reason is that drf_auto_endpoint.get_field_dict.GetFieldDict.update_choices_from_serializer only recognize ChoiceField as a field for which choices should be populated

    def update_choices_from_serializer(self, rv, field_instance, force=False):
        if field_instance.__class__.__name__ != 'ChoiceField' and force is False:
            return # --> in my case the field is of type 'MultiChoiceField'

        if not hasattr(field_instance, 'choices'):
            return

        if rv.get('related_endpoint', None) is not None and force is False:
            return

        rv['type'] = settings.WIDGET_MAPPING['choice']
        rv['choices'] = [
            {
                'label': v,
                'value': k,
            } for k, v in field_instance.choices.items()
        ]

For this field the rendered metadata is the following (which is not particularly useful for the frontend)

  {
    "key": "hp",
    "type": "manytomany-lists",
    "read_only": false,
    "ui": {
      "label": "Proprietà di pericolo"
    },
    "validation": {
      "required": true
    },
    "extra": {},
    "translated": false,
    "related_endpoint": {
      "app": "core",
      "singular": "hp",
      "plural": "hps"
    }

Thanks,
Mattia

@nanuxbe
Copy link
Contributor

nanuxbe commented Feb 22, 2023

Thanks for the report and your patience. I will look into the possible fixes for this. Using isinstance instead of relying on __class__.__name__ sounds like it should work but I will have to investigate the Django inheritance scheme for those fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants