Ошибка выбора пользовательского поля в структуре отдыха Django - PullRequest
0 голосов
/ 13 декабря 2018

В настоящее время у меня проблема с созданием поля выбора в Django Rest Framework.Сначала, ища решения в Google, я нашел лучшие практики для применения решения в моем проекте.Тем не менее, я столкнулся с проблемами в сервисе, оставшимся от приложения.Поскольку мне нужно манипулировать информацией с помощью фиксированных опций, мне пришлось следовать методологии даже создания для этого конкретного сериализатора.

Перед использованием поля ChoiceField в DRF я могу правильно выбрать опцию, но не могупродемонстрируйте значение, получив имя переменной в ответе.Мое желание, чтобы значение, а не имя переменной для отображения.Для этого я создал следующую структуру:

Мой скрипт с именем choices.py

# Model custom using ENUM concept

from enum import Enum
from rest_framework import serializers

class ChoiceEnum(Enum):
    @classmethod
    def choices(cls):
        return tuple((x.name, x.value) for x in cls)

#Serializer custom ChoicesField

class ChoicesField(serializers.Field):
   def __init__(self, choices, **kwargs):
      self._choices = choices
      super(ChoicesField, self).__init__(**kwargs)

   def to_representation(self, obj):
      return self._choices[obj]

   def to_internal_value(self, data):
      return getattr(self._choices, data)

Моя модель

class Discount(models.Model):

    class DiscountTypes(ChoiceEnum):
          VALUE = 'value_absolute'
          PERC = 'percentual'

    employee = models.ForeignKey(Employee, default=None)
    type = models.CharField(max_length=5, choices=DiscountTypes.choices(), default=DiscountTypes.PERC.value)
    value = models.IntegerField(default=0)
    inception = models.DateField(default=datetime.now)

    class Meta:
          db_table = 'discounts'
          app_label = 'db_teste'

My Viewset and Serializer

class DiscountSerializer(serializers.ModelSerializer):
      employee__id = serializers.PrimaryKeyRelatedField(
    source='employee', queryset=Employee.objects.all())
      employee__name = serializers.ReadOnlyField(source='employee.name')
      # type = serializers.ChoiceField(choices=Discount.DiscountTypes.choices())
      type = ChoicesField(choices=Discount.DiscountTypes)
      inception = serializers.ReadOnlyField()

      class Meta:
            model = Discount
            fields = ('id', 'employee__id', 'employee__name',
              'type', 'value', 'inception')


class Discounts(viewsets.ModelViewSet):
      allowed_methods = ('GET', 'PUT', 'POST', 'PATCH', 'HEAD', 'OPTIONS')
      queryset = Discount.objects.all()
      serializer_class = DiscountSerializer

Прежде, используя поле выбора DRF, я мог спокойно зарегистрироваться.Теперь с моим решением, я не могу ввести какие-либо данные, и я получаю эту ошибку ниже:

Ошибка в DRF

(1406, "Data too long for column 'type' at row 1")

Как я могу решить и улучшить свой код?

PS: В моем проекте я использую Django 1.9.4 и DRF 3.6.3

Ответы [ 3 ]

0 голосов
/ 13 декабря 2018
Make it simple with following snippet,hope it will help.

# models.py
    class User(AbstractUser):
        GENDER_CHOICES = (
            ('M', 'Male'),
            ('F', 'Female'),
                          )
        gender = models.CharField(max_length=1, choices=GENDER_CHOICES)   
# serializers.py 
    class UserSerializer(serializers.ModelSerializer):
        gender = serializers.CharField(source='get_gender_display')

        class Meta:
            model = User
        def get_gender(self,obj):
            return obj.get_gender_display()  
# views.py
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer  
0 голосов
/ 22 декабря 2018

Мне удалось найти лучшее решение, однако мне пришлось переделать структуру моего поля и скрипта функции.

Пример структуры, которую я разработал, был таким:

Мой сценарий :

# -*- coding: utf-8 -*-

# Utilizando ENUM no projeto.

from enum import Enum
from rest_framework import serializers

#So far I have not been able to make it work yet!!
class ChoiceEnum(Enum):
    @classmethod
    def choices(cls):
        return tuple((x.name, x.value) for x in cls)

#Serializer custom
class DisplayChoiceField(serializers.ChoiceField):

    def __init__(self, *args, **kwargs):
        choices = kwargs.get('choices')
        self._choices = OrderedDict(choices)
        super(DisplayChoiceField, self).__init__(*args, **kwargs)

    def to_representation(self, obj):
        """Used while retrieving value for the field."""
        return self._choices[obj]

Моя модель:

class Discount(models.Model):

#class DiscountTypes(ChoiceEnum):
#    VALUE = 'value_absolute'
#    PERC = 'percentual'

DiscountTypes = (
    ('VA', 'value_absolute'),
    ('PE', 'percentual'),
 )

employee = models.ForeignKey(Employee, default=None)
#type = models.CharField(max_length=5, choices=DiscountTypes.choices(), default=DiscountTypes.PERC.value)

type = models.CharField(max_length=20, choices=DiscountTypes)
value = models.IntegerField(default=0)
inception = models.DateField(default=datetime.now)

class Meta:
      db_table = 'discounts'
      app_label = 'db_teste'

Сериализатор и Viewset

from aldar_ws.choices import ChoicesField, DisplayChoiceField
...

class DiscountSerializer(serializers.ModelSerializer):
      employee__id = serializers.PrimaryKeyRelatedField(
    source='employee', queryset=Employee.objects.all())
      employee__name = serializers.ReadOnlyField(source='employee.name')
      # type = serializers.ChoiceField(choices=Discount.DiscountTypes.choices())
      type = DisplayChoiceField(choices=Discount.DiscountTypes)
      inception = serializers.ReadOnlyField()

      class Meta:
            model = Discount
            fields = ('id', 'employee__id', 'employee__name',
              'type', 'value', 'inception')


class Discounts(viewsets.ModelViewSet):
      allowed_methods = ('GET', 'PUT', 'POST', 'PATCH', 'HEAD', 'OPTIONS')
      queryset = Discount.objects.all()
      serializer_class = DiscountSerializer
0 голосов
/ 13 декабря 2018

Увеличение максимальной длины типа

    type = models.CharField(max_length=15, choices=DiscountTypes.choices(), default=DiscountTypes.PERC.value)
...