Django REST框架JSON API在使用关系时显示关系链接的空对象,

ryoqjall  于 2023-02-17  发布在  Go
关注(0)|答案(1)|浏览(92)

我正在为空间会合报告创建REST API,我希望会合成为每个报告的子级。
我的模特:

from django.db import models
from django.utils import timezone

class Report(models.Model):
  class Meta:
    managed = False
    db_table = 'report'
    ordering = ['-id']

  predict_start = models.DateTimeField(null=True)
  predict_end = models.DateTimeField(null=True)
  process_duration = models.IntegerField(default=0, null=True)
  create_conjunction_date = models.DateTimeField(null=True)
  ephe_filename = models.CharField(max_length=100, null=True)

class Conjunction(models.Model):
  class Meta:
    managed = False
    db_table = 'conjunction'
    ordering = ['-conjunction_id']

  conjunction_id = models.IntegerField(primary_key=True)
  tca = models.DateTimeField(max_length=3, null=True)
  missdt = models.FloatField(null=True)
  probability = models.FloatField(null=True)
  prob_method = models.CharField(max_length=45, null=True)
  norad = models.OneToOneField(SatelliteCategory, to_field='norad_cat_id', db_column='norad', null=True, on_delete=models.DO_NOTHING)
  doy = models.FloatField(null=True)
  ephe_id = models.IntegerField(null=True)
  pri_obj = models.IntegerField(null=True)
  sec_obj = models.IntegerField(null=True)
  report = models.ForeignKey(Report, related_name='conjunctions', null=True, on_delete=models.DO_NOTHING)
  probability_foster = models.FloatField(null=True)
  probability_patera = models.FloatField(null=True)
  probability_alfano = models.FloatField(null=True)
  probability_chan = models.FloatField(null=True)

我的序列化程序:

class ConjunctionSerializer(serializers.ModelSerializer):
  class Meta:
    model = Conjunction
    fields = '__all__'

class ReportSerializer(serializers.ModelSerializer):
  conjunctions = relations.ResourceRelatedField(many=True, read_only=True)

  class Meta:
    model = Report
    fields = '__all__'

我的观点:

from rest_framework import permissions
from rest_framework_json_api.views import viewsets
from .serializers import ReportSerializer, ConjunctionSerializer
from .models import Report, Conjunction

class ReportViewSet(viewsets.ModelViewSet):
  queryset = Report.objects.all()
  serializer_class = ReportSerializer
  permission_classes = [permissions.AllowAny]

class ConjunctionViewSet(viewsets.ModelViewSet):
  queryset = Conjunction.objects.all()
  serializer_class = ConjunctionSerializer
  permission_classes = [permissions.AllowAny]

我的网站urls.py

from django.contrib import admin
from django.urls import include, path
from rest_framework import routers
from api.views import UserViewSet, GroupViewSet
from shared.views import ReportViewSet, SatelliteCategoryViewSet, ConjunctionViewSet, ReportSentViewSet

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'groups', GroupViewSet)
router.register(r'reports', ReportViewSet)
router.register(r'report_sent', ReportSentViewSet)
router.register(r'satellite_category', SatelliteCategoryViewSet)
router.register(r'conjunctions', ConjunctionViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
  path('admin/', admin.site.urls),
  path('api/', include(router.urls)),
  path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

当我使用ResourceRelatedField时,JSON输出如下所示:

{
    "links": {
        "first": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=1",
        "last": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=84",
        "next": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=2",
        "prev": null
    },
    "data": [
        {
            "type": "Report",
            "id": "838",
            "attributes": {
                "predict_start": "2023-01-26T12:00:00Z",
                "predict_end": "2023-02-02T12:00:00Z",
                "process_duration": 752,
                "create_conjunction_date": "2023-01-26T14:52:45Z",
                "ephe_filename": "Filename.txt"
            },
            "relationships": {
                "conjunctions": {
                    "meta": {
                        "count": 107
                    },
                    "data": [
                        {
                            "type": "Conjunction",
                            "id": "78728"
                        },
                        # ... more data ...
                        {
                            "type": "Conjunction",
                            "id": "78622"
                        }
                    ]
                }
            }
        }
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pages": 84,
            "count": 838
        }
    }
}

但是当我使用HyperlinkedRelatedField时,它给出了conjunctions的空对象:

{
    "links": {
        "first": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=1",
        "last": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=84",
        "next": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=2",
        "prev": null
    },
    "data": [
        {
            "type": "Report",
            "id": "838",
            "attributes": {
                "predict_start": "2023-01-26T12:00:00Z",
                "predict_end": "2023-02-02T12:00:00Z",
                "process_duration": 752,
                "create_conjunction_date": "2023-01-26T14:52:45Z",
                "ephe_filename": "Filename.txt"
            },
            "relationships": {
                "conjunctions": {}
            }
        },
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pages": 84,
            "count": 838
        }
    }
}

这就是我所期待的:

{
    "links": {
        "first": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=1",
        "last": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=84",
        "next": "http://127.0.0.1:8000/api/reports/?page%5Bnumber%5D=2",
        "prev": null
    },
    "data": [
        {
            "type": "Report",
            "id": "838",
            "attributes": {
                "predict_start": "2023-01-26T12:00:00Z",
                "predict_end": "2023-02-02T12:00:00Z",
                "process_duration": 752,
                "create_conjunction_date": "2023-01-26T14:52:45Z",
                "ephe_filename": "Filename.txt"
            },
            "relationships": {
                "conjunctions": {
                    # Any links or something.
                    "data": [{
                        "type": "Conjunction",
                        "id": "1",
                    },{
                        "type": "Conjunction",
                        "id": "2",
                    }],
                    "links": {
                        "self": "http://localhost:8000/api/reports/838/relationships/conjunctions/",
                        "related": "http://localhost:8000/api/reports/838/conjunctions/"
                    }
                }
            }
        },
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pages": 84,
            "count": 838
        }
    }
}
vyswwuz2

vyswwuz21#

我现在就能解决这个问题。
从现在开始,我将使用drf-nested-routers来解析与报表链接相关的合取。
您可以通过以下方式安装

pip install drf-nested-routers

不需要在Django项目的www.example.com文件中添加这个库,因为它不包含任何应用、信号或模型。settings.py file, as it does not contain any app, signal or model.
在www.example.com中,添加以下路由器urls.py, add the following routers

from django.urls import path, include
from rest_framework_nested import routers
from api.views import UserViewSet, GroupViewSet
from shared.views import ReportViewSet, SatelliteCategoryViewSet, ConjunctionViewSet, ReportSentViewSet, SatelliteViewSet, DiscosObjectViewSet, CoordinateViewSet, ReportRelationshipView

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'groups', GroupViewSet)
router.register(r'reports', ReportViewSet)
router.register(r'report_sent', ReportSentViewSet)
router.register(r'satellite_categories', SatelliteCategoryViewSet)
router.register(r'conjunctions', ConjunctionViewSet)
router.register(r'satellites', SatelliteViewSet)
router.register(r'discos_objects', DiscosObjectViewSet)
router.register(r'coordinates', CoordinateViewSet)

reports_router = routers.NestedSimpleRouter(router, 'reports', lookup='report')
reports_router.register(r'conjunctions', ConjunctionViewSet, basename='report-conjunctions')

urlpatterns = [
  path('admin/', admin.site.urls),
  path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
] + [
  path('api/', include(router.urls)) for router in [router, reports_router]
]

在www.example.com中,将HyperlinkedRelatedField添加到ReportSerializer类中。serializers.py, add HyperlinkedRelatedField into ReportSerializer class.

class ReportSerializer(serializers.HyperlinkedModelSerializer):

  conjunctions = relations.HyperlinkedRelatedField(
    many=True, read_only=True, 
    related_link_view_name='report-conjunctions-list',
    related_link_url_kwarg='report_pk'
  )

  class Meta:
    model = Report
    fields = '__all__'

在www.example.com中,从ConjunctionViewSet类覆盖get_queryset方法以过滤与报告相关的任何合取。views.py, from ConjunctionViewSet class, override get_queryset method to filter any conjunctions that are related with report.

class ConjunctionViewSet(viewsets.ModelViewSet):
  queryset = Conjunction.objects.all()
  serializer_class = ConjunctionSerializer
  permission_classes = [permissions.AllowAny]

  # Add code below
  # | | | | | | |
  # v v v v v v v

  def get_queryset(self):
    queryset = super().get_queryset()
    report_pk = self.kwargs.get('report_pk')
    if report_pk is not None:
      queryset = queryset.filter(report__pk=report_pk)

    return queryset

给定的JSON输出结果

{
    "data": {
        "type": "Report",
        "id": "838",
        "attributes": {
            "predict_start": "2023-01-26T12:00:00Z",
            "predict_end": "2023-02-02T12:00:00Z",
            "process_duration": 752,
            "create_conjunction_date": "2023-01-26T14:52:45Z",
            "ephe_filename": "Filename.txt"
        },
        "relationships": {
            "conjunctions": {
                "links": {
                    "related": "http://127.0.0.1:8000/api/reports/838/conjunctions/"
                }
            }
        },
        "links": {
            "self": "http://127.0.0.1:8000/api/reports/838/"
        }
    }
}

相关问题