Got AttributeError when attempting to get a value for field `matchingKey` on serializer `ParameterSerializer`.

I created an api app as per tutorial and populated serializers.py, urls.py and views.py

I have three models instructins, paramters and questions (from polls tutorial)

I am getting this error when going to http://localhost:8000/api/questions/6/ where 6 is a valid instance of question

Here is the error

AttributeError at /api/questions/6/

Got AttributeError when attempting to get a value for field matchingKey on serializer ParameterSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Question instance. Original exception text was: ‘Question’ object has no attribute ‘matchingKey’.

Request Method: GET
Request URL: http://localhost:8000/api/questions/6/
Django Version: 3.2.15
Exception Type: AttributeError
Exception Value: Got AttributeError when attempting to get a value for field matchingKey on serializer ParameterSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Question instance. Original exception text was: ‘Question’ object has no attribute ‘matchingKey’.

Here is the serializer in question.

#/api/serializers.py
from django.forms import widgets
from rest_framework import serializers
from correlator.models import Instruction
from reviews.models import Question
from parameters.models import Parameter
from reviews.models import Question
from reviews.models import Choice

class ParametersListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Parameter
        fields = ('id', 'matchingKey', 'sequence', 'param_kwargs_json', 'param1', 'param2', 'param3', 'param4', 'param5', 
        'param6', 'param7', 'param8', 'param9', 'param10', 'description')

class ParameterSerializer(serializers.ModelSerializer):
    class Meta:
        model = Parameter
        fields = ('id', 'matchingKey', 'sequence', 'param_kwargs_json', 'param1', 'param2', 'param3', 'param4', 'param5', 
        'param6', 'param7', 'param8', 'param9', 'param10', 'description')

class InstructionListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Instruction
        fields = '__all__'

class InstructionSerializer(serializers.ModelSerializer):
 
    class Meta:
        model = Instruction
        fields = '__all__'
#Polls

class QuestionListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Question
        fields = '__all__'

class QuestionSerializer(serializers.ModelSerializer):
 
    class Meta:
        model = Question
        fields = '__all__'

# class QuestionChoiceSerializer(serializers.ModelSerializer):

#     class Meta:
#         model = Choice
#         fields = ('id', 'choice_text')

# class ChoiceSerializer(serializers.ModelSerializer):
#     question_text = serializers.CharField(read_only=True, source='question.question_text')

#     class Meta:
#         model = Choice
#         fields = ('id', 'choice_text', 'question', 'question_text')
#         extra_kwargs = {
#             'question': {'write_only': True}
#         }


# class QuestionChoiceSerializerWithVotes(QuestionChoiceSerializer):

#     class Meta(QuestionChoiceSerializer.Meta):
#         fields = QuestionChoiceSerializer.Meta.fields + ('votes',)


# class QuestionListPageSerializer(serializers.ModelSerializer):

#     # was_published_recently = serializers.BooleanField(read_only=True)

#     class Meta:
#         model = Question
#         # fields = '__all__'
#         fields = ('id', 'question_text')

# class QuestionDetailPageSerializer(QuestionListPageSerializer):
#     choice_set = QuestionChoiceSerializer(many=True)

#     def create(Question, validated_data):
#         choice_validated_data = validated_data.pop('choice_set')
#         question = Question.objects.create(**validated_data)
#         choice_set_serializer = Question.fields['choice_set']
#         for each in choice_validated_data:
#             each['question'] = question
#         choices = choice_set_serializer.create(choice_validated_data)
#         return question


# class QuestionResultPageSerializer(QuestionListPageSerializer):
#     choices = QuestionChoiceSerializerWithVotes(many=True, read_only=True)

# class VoteSerializer(serializers.Serializer):
#     choice_id = serializers.IntegerField()

/api/views.py


#/api/views.py
from django.shortcuts import render
from django.shortcuts import get_object_or_404

# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.reverse import reverse
from rest_framework import generics
from correlator.models import Instruction
from parameters.models import Parameter
from reviews.models import Question
from reviews.models import Choice

from rest_framework.generics import ListCreateAPIView
from rest_framework import status
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action

#from .serializers import QuestionListPageSerializer, QuestionDetailPageSerializer, QuestionChoiceSerializer, VoteSerializer, QuestionResultPageSerializer, ChoiceSerializer



import api.serializers as serializers

class InstructionsListAPIView(generics.ListCreateAPIView):
    queryset = Instruction.objects.all()
    serializer_class = serializers.InstructionListSerializer

class InstructionsAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Instruction.objects.all()
    serializer_class = serializers.InstructionSerializer

class ParametersListAPIView(generics.ListCreateAPIView):
    queryset = Parameter.objects.all()
    serializer_class = serializers.ParametersListSerializer

class ParameterAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Parameter.objects.all()
    serializer_class = serializers.ParameterSerializer

#reviews 

class QuestionsListAPIView(generics.ListCreateAPIView):
    queryset = Question.objects.all()
    serializer_class = serializers.QuestionListSerializer

class QuesttionsAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Question.objects.all()
    serializer_class = serializers.QuestionSerializer



@api_view(('GET',))
def api_root(request, format=None):
    return Response({
        'instructions': reverse('instructions', request=request, format=format),
        'parameters': reverse('parameters', request=request, format=format),
        'questions' : reverse('questions', request=request, format=format),
        })

/api/urls.py

#/api/urls.py

from django.conf.urls import url, include
from . import views
from rest_framework.routers import SimpleRouter

from . import api
from tastypie.api import Api

from rest_framework_swagger.views import get_swagger_view

schema_view = get_swagger_view(title='Reviews API')

apiurls = [
    url(r'^instructions/$',
    views.InstructionsListAPIView.as_view(),
        name='instructions'
    ),
    url(r'^instructions/(?P<pk>[0-9]+)/$',
        views.InstructionsAPIView.as_view(),
        name='instruction-detail'
    ),
    url(r'^parameters/(?P<pk>[0-9]+)/$',
        views.ParameterAPIView.as_view(),
        name='parameter-detail'
    ),
    url(r'^parameters/$',
        views.ParametersListAPIView.as_view(),
        name='parameters'
    ),
    url(r'^questions/$',
        views.QuestionsListAPIView.as_view(),
        name='questions'
    ),
    url(r'^questions/(?P<pk>[0-9]+)/$',
        views.QuesttionsAPIView.as_view(),
        name='questions-detail'
    )
    ] 


# app_name = 'polls'
# urlpatterns = [
#     path('choices/', apiviews.ChoicesView.as_view(), name='choices_view'),
# ]

# Multiple viewsets can be registered with a single router.
# Each viewset will probably have actions list, create, retrieve, partial_update, destroy.
#router = SimpleRouter()
#router.register('questions', views.QuestionsViewSet, basename='question')

# urlpatterns += router.urls

question_resource = api.QuestionResource()
choice_resource = api.ChoiceResource()

v1_api = Api(api_name='v1')
v1_api.register(api.QuestionResource())
v1_api.register(api.ChoiceResource())

tastypie_patterns = [
    url(r'tastypie/', include(question_resource.urls)),
    url(r'tastypie/', include(choice_resource.urls)),
    url(r'tapi/', include(v1_api.urls)),
]



urlpatterns = [
    url(r'^$', views.api_root, name='api-root'),
    url(r'^', include(apiurls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    #url('choices/', views.ChoicesView.as_view(), name='choices_view'),
    url(r'tastypie/', include(question_resource.urls)),
    url(r'tastypie/', include(choice_resource.urls)),
    url(r'vapi/', include(v1_api.urls)),
    url(r'swagger-docs/', schema_view),
]

#urlpatterns += router.urls
urlpatterns += tastypie_patterns

Here are the models…

from asyncio.windows_events import NULL
import datetime
from email.policy import default
from msilib import sequence
from pickle import FALSE
from typing_extensions import Required


#import flag
from django.db import models
from django.utils import timezone
from django.contrib.contenttypes.fields import GenericRelation
from django.utils.translation import gettext_lazy as _

class Instruction(models.Model):

    class METHODS(models.TextChoices):
        GET = 'GET', _('GET')
        POST = 'POST', _('POST')
        PUT = 'PUT', _('PUT')
        DELETE = 'DELETE', _('DELETE')

    class DIRECTION(models.TextChoices):
        REQ = 'REQ', _('REQUEST')
        RES = 'RES', _('RESPONSE')

    id = models.BigAutoField(primary_key = True)
    requestpath = models.CharField(max_length=200)
    requestmethod = models.CharField(max_length=6,choices=METHODS.choices, default=METHODS.GET)
    direction = models.CharField(max_length=3,choices=DIRECTION.choices, default=DIRECTION.REQ)
    urllist = models.CharField(max_length=200,default='.')
    appusername = models.CharField(max_length=200, default='appusername')
    executescript = models.CharField(max_length=200, default='none')
    description = models.CharField(max_length=255, default='none')
    parameters_json = models.JSONField(null=True, blank=True)
    pub_date = models.DateTimeField('date published', default=datetime.datetime.now)
    #flags = GenericRelation(Flag)

    def __str__(self):
        return self.requestpath

    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
#/parameters/models.py

from symbol import parameters
from django.db import models

# Create your models here.
from django.db import models

class Parameter(models.Model):
    id = models.BigAutoField(primary_key=True)
    matchingKey = models.CharField(max_length=200)
    sequence = models.IntegerField(default = 1)
    param_kwargs_json = models.JSONField(null=True, blank=True)
    param1 = models.CharField(max_length=200)
    param2 = models.CharField(max_length=200, null = True, default = 'N/A' )
    param3 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    param4 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    param5 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    param6 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    param7 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    param8 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    param9 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    param10 = models.CharField(max_length=200, null = True, default = 'N/A'  )
    description = models.CharField(max_length=250, null = True, default = 'N/A'  )

    # def __str__(self):
    #     return self.matchingKey

    class Meta:
        ordering = ('matchingKey', )

    def save(self, *args, **kwargs):
        """
        Use the `pygments` library to create a highlighted HTML
        representation of the code snippet.
        """
        super(Parameter, self).save(*args, **kwargs)

#reviews/models.py
import datetime

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


class Question(models.Model):
    jsonDefault = {'json':'sample'}

    id = models.BigAutoField(primary_key = True)
    question_text = models.CharField( null=True, max_length=200, blank=True)
    request_details = models.TextField(null=True, max_length = 250, blank=True)
    json_field = models.JSONField( null=True, blank=True,  default = dict)
    approve_and_train = models.BooleanField(null=True, default=False)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

Ok I posted all three of the files in the /api/ and the models involved. I commented out the serializers related to the join between Question and Choice to get rid of the error so I could proceed with other tasks.

Thanks,

MO

Which tutorial? The standard Django tutorial doesn’t use serializers or create an API and the DRF tutorial doesn’t use the Django polls app.

You’re probably going to need to post a fair bit of your code here for us to figure this out, including your URL definitions, view, and models involved.

I took pieces from the DRF Tutorial and another tutorial that added DRF to the django Polls turorial.

I have added all three of the files I created in the /api/ app folder.

Thanks

MO

@CodenameTim - This is more up your alley than mine. Any thoughts?

@trexmo can you include your models? Specifically Question and Parameter.

Also according to the error message, it sounds like the ParameterSerializer is being passed an instance of the Question model. Can you confirm that the code that you shared is exactly the same as the code that was used to generate the error?

yes it is the same code. I did ocmment out the question choice join serializers I will add the models.

Yes did that and yes i looked for any referrence but found none

@trexmo so unfortunately if the error is still:

Got AttributeError when attempting to get a value for field matchingKey on serializer ParameterSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Question instance. Original exception text was: ‘Question’ object has no attribute ‘matchingKey’.

Then that means that a Question instance is being passed into ParameterSerializer. I can’t help more with the given information. I’d have to start a debugging process which would start with the full stacktrace of the error and the exact files that are referenced in that stacktrace from your project.

Alternatively, if you’d like to give this a go on your own, you could change ParameterSerializer to:

class ParameterSerializer(serializers.ModelSerializer):
    matchingKey = serializers.SerializerMethodField()
    class Meta:
        model = Parameter
        fields = ('id', 'matchingKey', 'sequence', 'param_kwargs_json', 'param1', 'param2', 'param3', 'param4', 'param5', 
        'param6', 'param7', 'param8', 'param9', 'param10', 'description')

    def get_matchingKey(self, obj):
        breakpoint()
        return obj.matchingKey

When you run the flow that breaks this, it’ll hit breakpoint(), then drop you into the Python Debugger. From there you can inspect the locals in the terminal, such as obj.__class__ which should tell you what the class is. Or use where to see what code was all executed that lead to the current statement to be executed. You can use next to step to the next line or continue to let the program run until the next breakpoint or completion. It’s a really nice tool to have when debugging problems like this.

Thanks will give that a try

i believe it’s incompatibility between the code the database , what worked for me is to flush the database by using :

python manage.py flush