David G.
David G.

Reputation: 43

Include foreign key in saving Django-Rest-Framework serializer

I am creating an API with Django Rest Framework. You can give a term to the api, it looks up data on a third party API and then everything should be stored to the database. All is handled in user scope and I have two tables, one with the search term and the ID of the user and another with the data received, which has the search_id as a foreing key. I now want that if you send a term to the API everything is stored and you get the search back, with ID and all dates. so far so good. I am now stuck, where I need to save the third party data to the database. The serializer demands the model object at saving and not the serializer from the user input. I tried around, but can't figure out, what I am doing wrong:

models.py:

class Search(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE,)
    term = models.CharField(max_length=200)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.term


class foundTables(models.Model):
    search = models.ForeignKey(Search,
                               related_name='search',
                               on_delete=models.CASCADE)
    code = models.CharField(max_length=200)
    content = models.CharField(max_length=1000)
    time = models.CharField(max_length=200, blank=True, default='')
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.content

serializers.py

class SearchSerializer(serializers.ModelSerializer):
    class Meta:
        model = Search
        fields = ['id', 'user', 'term', 'created', 'updated']
        read_only_fields = ['id', 'user', 'created', 'updated']


class foundTablesSerializer(serializers.ModelSerializer):
    search = serializers.PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = foundTables
        fields = [
            'id',
            'search',
            'code',
            'content',
            'time',
            'created',
            'updated']
        read_only_fields = [
            'id',
            'search',
            'created',
            'updated']

views.py

class genesisRequestViewSet(viewsets.ModelViewSet):
    queryset = Search.objects.all()
    serializer_class = SearchSerializer
    permission_classes = [permissions.IsAuthenticated]
    http_method_names = ['get', 'post']

    def get_queryset(self):
        user = self.request.user
        return Search.objects.filter(user=user).order_by('-created')[:1]

    def create(self, request):
        user = self.request.user
        term = request.data['term']
        seria = SearchSerializer(data=self.request.data)
        genesis = findRequest()
        if seria.is_valid():
            # search = Search(user=user, term=term)
            # search.save()
            seria.save(user=user)
            genesis.get(term=term)
            if genesis.data['Tables']:
                genesisdict = {}
                for element in genesis.data['Tables']:
                    genesisdict['code'] = element['Code']
                    genesisdict['content'] = element['Content']
                    genesisdict['time'] = element['Time']
                    tables = foundTablesSerializer(data=genesisdict)
                    if tables.is_valid():
                        tables.save(search=seria)
                    else:
                        return Response(tables.errors)
                return Response(seria.data)
            else:
                return Response({"status": "No tables found"})
        else:
            return Response({"errors": seria.errors})

So, if I use the muted "search=Search..." approach, it would kind of work, but I'd like to use the serializer, of course.

The save method returns an error, that it would need a instance of Search:

ValueError at /api/genesis/
Cannot assign "SearchSerializer(data={'term': 'testterm'}):
    id = IntegerField(label='ID', read_only=True)
    user = PrimaryKeyRelatedField(read_only=True)
    term = CharField(max_length=200)
    created = DateTimeField(read_only=True)
    updated = DateTimeField(read_only=True)": "foundTables.search" must be a "Search" instance.

Any idea, how I could get the foreign key in the tables serializer?

Upvotes: 0

Views: 818

Answers (1)

Reza Heydari
Reza Heydari

Reputation: 1211

I don't know I understand your question or not but serializer.save() return an instance you can change your code like this:

Get your Search instance from save() method:

search_ins = seria.save(user=user)

and use in foundTablesSerializer like this:

tables.save(search=search_ins)

Upvotes: 1

Related Questions