【问题标题】:How to POST Model with Many to Many through in Django REST如何在 Django REST 中通过多对多发布模型
【发布时间】:2018-09-13 00:10:30
【问题描述】:

我有一个具有多对多连接的模型。我想让这个模型在 Django REST 中可用。默认情况下,这样的模型是只读的,但我也想写。此外,将直通连接的信息作为嵌套模型集成到 GET 中会很棒。

...
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):
    ???

我怎样才能做到这一点?我的视图和序列化程序应该是什么样的?

【问题讨论】:

  • 你想如何显示diagnoses_all_icd_10,是ids列表还是你想显示整个对象?
  • diagnoses_all_icd_10 = serializers.PrimaryKeyRelatedField( many=True, queryset= ICD10.objects.all(), write_only=True, required=False) 你可以定义类似的东西,你必须重写序列化程序创建方法并从验证数据中弹出 id,例如 icd_10 = valid_data.pop('diagnoses_all_icd_10')然后将其添加到 icd_10 中 icd 的模型实例```:instance.diagnoses_all_icd_10.add(ICD10.objects.get(pk=icd_10))```
  • 我建议在使用manytomanyfield 时使用views.py 中的类,您可以查看inlineformset_factory 中的forms.py 以及jquery-formset 中的前端。

标签: django rest django-rest-framework


【解决方案1】:

关于创建或更新嵌套对象,the documentation actually has a great example。如果可以的话,我会给你一个更好的。如果示例中有任何令人困惑的地方,很乐意在这里解释。

如果您采用这种方法,您的GET 请求将自动为您展开嵌套对象。

【讨论】:

    【解决方案2】:

    通常我通过POSTthrough 表的间接方式解决方法并实现嵌套创建()。如果我的回答不准确,请提供更多信息。

    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
    

    我的存储库:
    我与许多问题共享我的存储库。请不要介意。
    https://github.com/elcolie/tryDj2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 2014-08-27
      • 2020-11-18
      • 1970-01-01
      • 2013-07-04
      • 2018-06-11
      • 2014-05-27
      相关资源
      最近更新 更多