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 serializerParameterSerializer
. The serializer field might be named incorrectly and not match any attribute or key on theQuestion
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 serializerParameterSerializer
. The serializer field might be named incorrectly and not match any attribute or key on theQuestion
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