简体   繁体   中英

POSTing foreign keys to Django Rest Framework, using Postman

So I've made a simple REST API for the company I work for. This is a side project, so I'm still learning a lot.

So far it works nicely for GET requests. The problem I'm facing now is trying to do POST requests (Using Postman for now, the idea is to connect the API straight to a sensor that broadcasts JSON data and upload all that data to our DB through the API).

The way we have set up the models, there are several ForeignKey relationships in our DB (we are using PostgreSQL if that makes a difference).

I'm trying to POST one of our most basic bits of information, but arguably the most important which is measurement data.

The model for a data point has a ForeignKey to a parameter, and a sensor. A parameter would be a model that has a parameter name, type, position, and a sensor would be another model that itself has a ForeignKey to a Chamber (another model that also includes it's own ForeignKeys, to Customers), and another ForeignKey to SensorType.

In short, for relationships, data relates to parameter, and sensor (which relates to SensorType, and to Chamber which itself relates to Customer which relates to User).

When I do a POST request to "api/parameter/create/" (parameter has no ForeignKeys) it works. I can create dummy parameters.

So I'm fairly certain my issue lies with sending a POST request to API views that depend on a ForeignKey on the model.

Sending a POST request on Postman, using basic authentication (user/pass), with all the fields that the Data view on the API needs gives me the following error:

"IntegrityError at /api/data/create/ null value in column "parameter_id" violates not-null constraint"

Which is understandable, a Data point is intrinsically related to a parameter. But if I include a parameter_id in the JSON body, it still gives the same error.

Here is views.py for Data on the API:

class DataCreateAPIView(CreateAPIView):
    queryset = Data.objects.all()
    serializer_class = DataCreateSerializer
    permission_classes = [IsAuthenticated]
    def post(self,request):
        serializer = DataCreateSerializer(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)

Here is the snippet for Data on serializers.py on the API:

class DataCreateSerializer(ModelSerializer):
    sensor = SerializerMethodField()
    parameter = SerializerMethodField()
    class Meta:
        model = Data
        fields = [
            'id',
            'time',
            'sensor',
            'parameter',
            'parameter_value'
        ]
    def get_sensor(self, obj):
        return str(obj.sensor)
    def get_parameter(self, obj):
        return str(obj.parameter.parameter_name)

Here is the Data model on models.py

class Data(models.Model):
    time = models.DateTimeField()
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
    parameter = models.ForeignKey(Parameter, on_delete=models.CASCADE)
    parameter_value = models.FloatField()

    def __str__(self):
        return str(self.time) + ' : ' + self.parameter.parameter_name + ' = ' + str(self.parameter_value)

    def __key(self):
        return self.time, self.sensor, self.parameter

    def __eq__(self, y):
        return isinstance(y, self.__class__) and self.__key() == y.__key()

    def __hash__(self):
        return hash(self.__key())

Just in case, here is the Data related snippet URLs on urls.py:

    url(r'^data/$', DataListAPIView.as_view(), name='data_list'),
    url(r'^data/create/$', DataCreateAPIView.as_view(), name='data_list_create'),
    url(r'^data/(?P<pk>\d+)/$', DataDetailAPIView.as_view(), name='data_list_detail'),
    url(r'^data/(?P<pk>\d+)/edit/$', DataUpdateAPIView.as_view(), name='data_list_update'),
    url(r'^data/(?P<pk>\d+)/delete/$', DataDeleteAPIView.as_view(), name='data_list_delete'),

Here is (start of)the JSON blurb I get from Postman:

IntegrityError at /expert/api/data/create/
null value in column "parameter_id" violates not-null constraint
DETAIL:  Failing row contains (21490030, 2010-10-10 10:10:10+00, 999999999, null, null).


Request Method: POST
Request URL: http://localhost:8000/expert/api/data/create/
Django Version: 1.10.8
Python Executable: /home/luke/.virtualenvs/expert/bin/python
Python Version: 3.5.3

When I tried to send JSON including "parameter_id": 1 (which is a velid PK, it already exists)

You need to change get_parameter method to get_parameter_name for example, and use two separate fields for parameter and parameter_name .

class DataCreateSerializer(ModelSerializer):
    sensor = SerializerMethodField()
    parameter_name = SerializerMethodField()
    class Meta:
        model = Data
        fields = [
            'id',
            'time',
            'sensor',
            'parameter', # it is the field for FK model field
            'parameter_name' # field for custom method
            'parameter_value'
        ]

    def get_sensor(self, obj):
        return str(obj.sensor)

    def get_parameter_name(self, obj):
        return str(obj.parameter.parameter_name)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM