DRF полиморфный многие ко многим с дополнительными полями - PullRequest
0 голосов
/ 11 января 2019

Я работаю с Django Rest Framework, чтобы создать API, который может обрабатывать спецификации материалов (BoM) электронных компонентов.

Я использую django-polymorphic и django-rest-polymorphic, поэтому я могу использовать полиморфные модели для компонентов (они имеют общие атрибуты, но я все еще хочу обрабатывать их во многом таким же образом. Полиморфные модели отлично подходят для с этой целью).

Все хорошо, пока я не ввожу отношения «многие ко многим» с атрибутом «сквозной». То, что я хотел бы, это BoM, который имеет несколько различных компонентов, каждый с количеством, например. BoM1 имеет резистор 2х470 кОм и конденсатор 3х100 мкФ.

models.py: (немного подрезано, чтобы этот пост не был эпическим романом)

class BoM(models.Model):
    """Bill of Materials: a list of all parts and their quantities for a given pedal"""
    pedal = models.ForeignKey(Pedal, on_delete=models.CASCADE)
    variant = models.CharField(max_length=100, blank=True)
    electronic_components = models.ManyToManyField(
        'ElectronicComponent', through='ElectronicComponentQty', blank=True)

    class Meta:
        verbose_name = 'Bill of materials'
        verbose_name_plural = 'Bills of materials'

    def __str__(self):
        return str(self.pedal)


class ElectronicComponent(PolymorphicModel):
    """Shared data model for electronic components"""
    value = models.CharField(max_length=20)
    datasheet = models.FileField(upload_to='uploads/components', blank=True)

    def __str__(self):
        return self.value


class ElectronicComponentQty(models.Model):
    """Combination of resistor and quantity"""
    bom = models.ForeignKey(BoM, on_delete=models.CASCADE)
    component = models.ForeignKey(
        ElectronicComponent, on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField(default=1)

    class Meta:
        verbose_name = 'Elecronic component quantity'
        verbose_name_plural = 'Electronic component quantities'


class Resistor(ElectronicComponent):
    """Resistor data model"""
    WATTAGES = [('1/4w', '1/4w'), ('1/8w', '1/8w')]

    wattage = models.CharField(max_length=4, choices=WATTAGES, default='1/4w')



class Capacitor(ElectronicComponent):
    """Capacitors (all kinds)"""
    VOLTAGE_RATINGS = [
        ('16V', '16V'),
        ('35V/50V', '35V/50V'),
    ]

    CAP_TYPES = [
        ('ceramic disk', 'ceramic disk'),
        ('film', 'film'),
        ('electrolytic', 'electrolytic'),
        ('tantalum', 'tantalum'),
        ('other', 'other'),
    ]

    capacitor_type = models.CharField(
        max_length=20, choices=CAP_TYPES, default='film')
    voltage_rating = models.CharField(
        max_length=10, choices=VOLTAGE_RATINGS, blank=True)

serializers.py:

class ElectronicComponentSerializer(serializers.ModelSerializer):
    class Meta:
        model = ElectronicComponent
        fields = '__all__'


class ElectronicComponentQtySerializer(serializers.ModelSerializer):
    class Meta:
        model = ElectronicComponentQty
        fields = '__all__'


class BoMSerializer(serializers.ModelSerializer):
    electronic_components = ElectronicComponentQtySerializer(
        many=True, read_only=True)

    class Meta:
        model = BoM
        fields = '__all__'

class ResistorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Resistor
        fields = '__all__'


class CapacitorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Capacitor
        fields = '__all__'


class ElectronicComponentPolySerializer(PolymorphicSerializer):
    model_serializer_mapping = {
        Resistor: ResistorSerializer,
        Capacitor: CapacitorSerializer,
    }

С помощью этого кода я могу создавать объекты EletronicComponentQty без проблем. Однако, когда я пытаюсь перечислить BoM (через сериализатор), я получаю: AttributeError в / pedalparts / boms / Получил AttributeError при попытке получить значение для поля bom в сериализатор ElectronicComponentQtySerializer. Поле сериализатора может быть названо неправильно и не совпадать ни с одним атрибут или ключ в экземпляре Capacitor. Исходный текст исключения был: объект «Конденсатор» не имеет атрибута 'Бом'.

Кто-нибудь знает, как я могу решить это? Я открыт для любых изменений, которые делают эту работу.

1 Ответ

0 голосов
/ 11 января 2019

Поскольку electronic_components в модели BoM относится к модели ElectronicComponent, она не должна использовать ElectronicComponentQtySerializer, а модель, которая может сериализовать нужные экземпляры, скорее всего, ElectronicComponentSerializer или ElectronicComponentPolySerializer.

...