DRF request.data issue with POST method - django-rest-framework

I'm using DRF to test a api,when i POST a data,DRF return status_code 500 and error 'MacList' object has no attribute 'data'. but the GET is not problem.
Views:
class MacList(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
queryset = Testable.objects.all()
serializer_class = TestableSerializer
def get(self,request,*args,**kwargs):
return self.list(self, request, *args, **kwargs)
def post(self,request,*args,**kwargs):
return self.create(self, request, *args, **kwargs)
URLs:
path(r'api/maclist',views.MacList.as_view())
I'm checking the mixins.CreateModelMixin source code
class CreateModelMixin:
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data) **#### problem here**
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
if i use APIView to POST success.
class MacList(APIView):
def post(self,request):
serializer = TestableSerializer(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)
Please help me!
Django-->3.0.8
djangorestframework-->3.11.0

Don't need to pass derived class instance into inherited class method while calling it from derived class, when we use self python automatically pass this instance
It will works if you change your code to
.
.
def get(self,request,*args,**kwargs):
return self.list(request, *args, **kwargs)
def post(self,request,*args,**kwargs):
return self.create(request, *args, **kwargs)

Related

django rest framework - override viewsets.ViewSet#retrieve in order to use 2 parameters for lookup resource

I'd like to use two model's attributes to lookup a Route's record
models.py
class Route(DateTimeModel):
start_poi = models.ForeignKey(Poi, related_name="start_pois", on_delete=models.CASCADE)
end_poi = models.ForeignKey(Poi, related_name="end_pois", on_delete=models.CASCADE)
...
def __str__(self):
return 'From %s to %s' % (self.start_poi.slug, self.end_poi.slug)
views.py
class RouteViewSet(viewsets.ViewSet):
http_method_names = ['get']
#staticmethod
def list(request):
queryset = ...
serializer = RouteSerializer(queryset, many=True)
return Response(serializer.data)
#staticmethod
def retrieve(request, from_poi_slug, to_poi_slug):
queryset = ...
route = get_object_or_404(queryset, from_poi_slug=from_poi_slug, to_poi_slug=to_poi_slug)
serializer = RouteSerializer(route)
return Response(serializer.data)
urls.py
urlpatterns.extend([
path(rf'{BASE_API_PATH}/routes/(?P<from_poi_slug>[-\w]+)/(?P<to_poi_slug>[-\w]+)', RouteViewSet),
])
I get
Not Found: /api/v1/routes/xyz/abc
[29/Apr/2019 10:07:01] "GET /api/v1/routes/molo-santa-maria/kennedy-ne HTTP/1.1" 404 13191
What am I missing?
How can I properly override #retrieve and correctly configure urls?
Since you are only using read operations, you could use ReadOnlyModelViewSet.
#views.py
class RouteViewSet(viewsets.ReadOnlyModelViewSet):
http_method_names = ['get']
def list(self, request, *args, **kwargs):
queryset = ...
serializer = RouteSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, *args, **kwargs):
from_poi_slug = kwargs['from_poi_slug']
to_poi_slug = kwargs['to_poi_slug']
queryset = ...
route = get_object_or_404(queryset, from_poi_slug=from_poi_slug, to_poi_slug=to_poi_slug)
serializer = RouteSerializer(route)
return Response(serializer.data)
and in your urls.py
urlpatterns.extend([
path(rf'{BASE_API_PATH}/routes/(<from_poi_slug>)/(<to_poi_slug>)/', RouteViewSet.as_view({"get": "retrieve"})),
])

multiple object creation on a single API call on django

i have to create multiple object creation on a single API call.My
serializer class is like this
def create(self, validated_data):
dt = datetime.now()
strg = '{:%d%m%Y%H%M%S}'.format(dt, dt.microsecond // 1000)
hat= "REQ" + strg
creater = dot_order_models.DotOrder(reqnum=hat,**validated_data)
creater.save()
return creater
class Meta:
model = dot_order_models.DotOrder
fields = ('merchant', 'biker','batch','customer_name','contact','city','locality','order_amount')
i just given many=true but did not work. then i give
def __init__(self, *args, **kwargs):
many = kwargs.pop('many', True)
super(BikerSerializer, self).__init__(many=many, *args, **kwargs)
this too didn't work.how can i solve it using serializers and view class.
thanks in advance
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data, many=isinstance(request.data, list))
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
results = dot_order_models.DotOrder.objects.all()
output_serializer = dot_order_serializers.DotOrderSerializer(results, many=True)
return super(DotOrderViewSet, self).create(request)

DRF-Haystack SearchIndex returning from ALL index classes?

I'm using haystack with elasticsearch backend in django, and drf-haystack to implement serializers for results.
I first created a StudentIndex, which indexes over StudentProfiles to use in searches for students in search_indexes.py
class StudentIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(
document=True,
use_template=True,
template_name="search/indexes/user_search_text.txt")
//other indexes or indices or whatever
def get_model(self):
return StudentProfile
def index_queryset(self, using=None):
return StudentProfile.objects.filter(user__is_active=True)
Which is passed to the serializer and viewset in views.py:
class StudentSerializer(HaystackSerializer):
class Meta:
index_classes = [StudentIndex]
class StudentSearchView(ListModelMixin, HaystackGenericAPIView):
index_models = [StudentProfile]
serializer_class = StudentSerializer
pagination_class = None
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
and everything was fine and dandy....UNTIL I added two more indexes over other profiles and a single view/serializer to handle them. All exist in the same respective files:
search_indexes.py
class TeacherIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(
document=True,
use_template=True,
template_name="search/indexes/user_search_text.txt")
//other indexes or indices or whatever
def get_model(self):
return TeacherProfile
def index_queryset(self, using=None):
return TeacherProfile.objects.filter(user__is_active=True)
class StaffIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(
document=True,
use_template=True,
template_name="search/indexes/user_search_text.txt")
//other indexes or indices or whatever
def get_model(self):
return StaffProfile
def index_queryset(self, using=None):
return StaffProfile.objects.filter(user__is_active=True)
and added to views.py:
class StaffSerializer(HaystackSerializer):
class Meta:
index_classes = [StaffIndex, TeacherIndex]
class StaffSearchView(ListModelMixin, HaystackGenericAPIView):
index_models = [StaffProfile, TeacherProfile]
serializer_class = StaffSerializer
pagination_class = None
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
NOW....each view goes to its own url endpoint (/student-search and /staff-search respectively), but ONLY the staff-search endpoint properly returns Staff and TeacherProfile results, while the student-search, in a seperate endpoint with seperate view and models and indexes all explicitly stated, is return StudentProfiles AND Teacher and StaffProfiles and I can not for the life of me figure out why.
If anyone has run into this before, I'd really appreciate help solving, and more importantly, understanding, this issue.
Thanks in advance!
Well, for future people with the same issues, here's all i needed to do to solve it.
I'm using the DRF-Haystack genericviewapi, and on the view, I simply defined the filter_queryset to use the proper haystack connection (which ignored other indices). So for example:
class StudentSearchView(ListModelMixin, HaystackGenericAPIView):
index_models = [StudentProfile]
serializer_class = StudentSerializer
pagination_class = None
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def filter_queryset(self, queryset):
queryset = super(HaystackGenericAPIView, self).filter_queryset(queryset)
return queryset.using('student')
Everything now works properly :)
I have the same problem, but when i use the queryset.using('dynamic'), it raises django.core.exceptions.ImproperlyConfigured: The key 'dynamic' isn't an available connection.
class DynamicSearchView(ListModelMixin, HaystackGenericAPIView):
serializer_class = serializers.DynamicSearchSerializer
filter_backends = [HaystackHighlightFilter]
#swagger_auto_schema(
manual_parameters=[text, type]
)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def filter_queryset(self, queryset):
return super(DynamicSearchView, self).filter_queryset(queryset).using('dynamic')

django rest framework find url kwarg in APIView

I have a url that looks like this:
url(r'^client_profile/address/(?P<id>.+)/$', views.ClientProfileAddressView.as_view())
And an APIView:
class ClientProfileAddressView(APIView):
renderer_classes = (JSONRenderer,)
permission_classes = (IsAuthenticated,)
def put(self, request):
....
def get(self, request):
....
In both put and get, I need to access the id url kwarg, the first one to update the object, the second to update it. How can I access the url argument in those methods?
This should work:
def put(self, request, *args, **kwargs):
id = kwargs.get('id', 'Default Value if not there')
def get(self, request, *args, **kwargs):
id = kwargs.get('id', 'Default Value if not there')

where the serializer in perform_createt comes from?

Although serializer as parameter passed in perform_create method, it is not clear where it pass from. Can anyone explain where the serializer parameter pass from and how it works?
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
It comes from the CreateModelMixin:
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Resources