как создать простые отношения «многие ко многим» с django rest

#python #django #django-rest-framework #relationship

Вопрос:

я новичок в django и перешел с symfony. я хочу попробовать создать простую связь между 2 моделями в django-rest-фреймворке и получить для них apiview. но я не могу понять, почему сериализаторы не обрабатывают отношения между этими 2 моделями.

мои модели в models.py

 from django.contrib.gis.db import models
from django.contrib.gis.geos import Point
import uuid

class RequestLocation(models.Model):
    gpslocation = models.PointField(srid=4326, geography=True, default=Point(0.0, 0.0))
    gpslocationradius = models.IntegerField(default=5)
    description = models.TextField(default='#')
    created = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['created']

    def __str__(self):
        return self.id

class Shops(models.Model):
    gpslocation = models.PointField(srid=4326, geography=True, default=Point(0.0, 0.0))
    created = models.DateTimeField(auto_now_add=True)
    requestlocations = models.ManyToManyField(RequestLocation, null=True, blank=True)

    class Meta:
        ordering = ['created']

    def __str__(self):
        return self.id


 

и мои сериализаторы в serializers.py:

 from rest_framework_gis.serializers import GeoFeatureModelSerializer
from .models import RequestLocation, Shops

class RequestLocationSerializer(GeoFeatureModelSerializer):
    class Meta:
        model = RequestLocation
        geo_field = 'gpslocation'
        auto_bbox = True
        id_field = 'id'
        fields = ['id', 'gpslocation', 'gpslocationradius', 'description']
    
class ShopsSerializer(GeoFeatureModelSerializer):
    requestlocations = RequestLocationSerializer(read_only=True)

    class Meta:
        model = Shops
        geo_field = 'gpslocation'
        auto_bbox = True
        id_field = 'id'
        fields = ['id', 'gpslocation', 'requestlocations']

 

и views.py:

 # RequestLocation view
@api_view(['GET', 'POST'])
def rl_list(request, format=None):
    if request.method == 'GET':
        rl = RequestLocation.objects.all()
        serializer = RequestLocationSerializer(rl, many=True)
        distance_filter_field = 'geometry'
        filter_backends = (DistanceToPointFilter)
        bbox_filter_include_overlapping = True
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = RequestLocationSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def rl_detail(request, pk, format=None):
    try:
        rl = RequestLocation.objects.get(pk=pk)
    except RequestLocation.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = RequestLocationSerializer(rl)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = RequestLocationSerializer(rl, data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        rl.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

# Shop view
@api_view(['GET', 'POST'])
def shp_list(request, format=None):
    if request.method == 'GET':
        shp = Brokers.objects.all()
        serializer = ShopsSerializer(shp, many=True)
        distance_filter_field = 'geometry'
        filter_backends = (DistanceToPointFilter)
        bbox_filter_include_overlapping = True
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = ShopsSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def shp_detail(request, pk, format=None):
    try:
        shp = Shops.objects.get(pk=pk)
    except RequestLocation.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = ShopsSerializer(shp)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = ShopsSerializer(shp, data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        shp.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
 

когда я удалю requestlocations = RequestLocationSerializer(read_only=True) все, все будет в порядке, и я смогу публиковать и получать магазины. но когда эта строка возвращается, я получаю SkipField at /shp/ ошибку.

пожалуйста, веди меня.

Комментарии:

1. Так requestlocations как это коллекция объектов, попробуйте добавить many=True так RequestLocationSerializer(read_only=True, many=True)