Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to POST Model with Many to Many through in Django REST

I have a model with a many to many connection. I would like to make this model available in Django REST. By default such a model is read only, but I would also like to write. Furthermore, it would be great to get the information of the through connection integrated into the GET as a nested model.

...
class KeyDateCase(models.Model):
    ...
    diagnoses_all_icd_10 = models.ManyToManyField(
        'ICD10', through='CaseICD10Connection')
...

class CaseICD10Connection(models.Model):
    case = models.ForeignKey('KeyDateCase', on_delete=models.CASCADE)
    icd_10 = models.ForeignKey('ICD10', on_delete=models.CASCADE)
    is_primary = models.BooleanField(default = False)
    certainty = models.CharField(
        max_length=1,
        choices=CERTAINTY_CHOICES,
        default='G',
    )

class ICD10(models.Model):

    primary_key_number = models.CharField(max_length=10, primary_key=True)

    star_key_number = models.CharField(max_length=10, blank=True, null=True)

    additional_key_number = models.CharField(
        max_length=10, blank=True, null=True)

    preferred_short_description = models.CharField(max_length=128, )
...

class KeyDateCaseViewSet(viewsets.ModelViewSet):
    ???

class KeyDateCaseSerializer(serializers.ModelSerializer):
    ???

How can I achieve this? What should my view and serializer look like?

like image 329
Gurkenkönig Avatar asked Apr 03 '18 15:04

Gurkenkönig


People also ask

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.


1 Answers

Normally I workaround by indirect way by POST to through table and implement nested-create(). Please provide me more information if my answer is inaccurate.

models.py

from django.db import models


class ICD10(models.Model):
    primary_key_number = models.CharField(max_length=10, primary_key=True)
    star_key_number = models.CharField(max_length=10, blank=True, null=True)
    additional_key_number = models.CharField(max_length=10, blank=True, null=True)
    preferred_short_description = models.CharField(max_length=128, )

    def __str__(self):
        return f'{self.primary_key_number} {self.star_key_number}'


class CaseICD10Connection(models.Model):
    case = models.ForeignKey('KeyDateCase', related_name='connections', related_query_name='key_date_cases', on_delete=models.CASCADE)
    icd_10 = models.ForeignKey('ICD10', related_name='connections', related_query_name='icd_10s', on_delete=models.CASCADE)
    is_primary = models.BooleanField(default=False)
    certainty = models.CharField(max_length=1, default='G', )


class KeyDateCase(models.Model):
    name = models.CharField(max_length=20)
    diagnose_all_icd_10 = models.ManyToManyField(ICD10, related_name='icd10s', related_query_name='icd10s',
                                                 through=CaseICD10Connection)

serializers.py

from rest_framework import serializers

from keydatecases.models import KeyDateCase, ICD10, CaseICD10Connection


class KeyDateCaseSerializer(serializers.ModelSerializer):
    class Meta:
        model = KeyDateCase
        fields = [
            'id',
            'name',
            'diagnose_all_icd_10',
        ]
        read_only_fields = ['id', 'diagnose_all_icd_10']


class ICD10Serializer(serializers.ModelSerializer):
    class Meta:
        model = ICD10
        fields = [
            'primary_key_number',
            'star_key_number',
            'additional_key_number',
            'preferred_short_description',
        ]


class CaseICD10ConnectionSerializer(serializers.ModelSerializer):
    case = KeyDateCaseSerializer()
    icd_10 = ICD10Serializer()

    class Meta:
        model = CaseICD10Connection
        fields = [
            'case',
            'icd_10',
            'is_primary',
            'certainty',
        ]

    def create(self, validated_data) -> CaseICD10Connection:
        # import ipdb;
        # ipdb.set_trace()
        # create key_date_case
        key_date_case = KeyDateCase.objects.create(**validated_data.get('case'))

        # create icd10
        icd10 = ICD10.objects.create(**validated_data.get('icd_10'))

        # create connection
        conn = CaseICD10Connection.objects.create(
            case=key_date_case, icd_10=icd10, is_primary=validated_data.get('is_primary'),
            certainty=validated_data.get('certainty')
        )
        return conn

viewsets.py

from rest_framework import viewsets

from keydatecases.api.serializers import CaseICD10ConnectionSerializer
from keydatecases.models import CaseICD10Connection


class CaseICD10ConnectionViewSet(viewsets.ModelViewSet):
    permission_classes = ()
    queryset = CaseICD10Connection.objects.all()
    serializer_class = CaseICD10ConnectionSerializer

My Repository:
I share my repository with many questions. Please do not mind it.
https://github.com/elcolie/tryDj2

like image 181
joe Avatar answered Nov 15 '22 22:11

joe