How to use hyperlinkedModelSerializer in django rest framework - django

How to use hyperlinkedModelSerializer in django rest framework My output shows:
HyperlinkedRelatedField requires the request in the serializer context. Add context={'request': request} when instantiating the serializer.
The code is given below:
serailizers.py
#Program Serializer
class ProgramSerializer(serializers.ModelSerializer):
class Meta:
model = Program
fields = '__all__'
#Program MiniSerializer
class ProgramMiniSerializer(serializers.HyperlinkedModelSerializer):
programCode = serializers.HyperlinkedRelatedField(many=True,view_name='program-detail', read_only=True)
class Meta:
model = Program
fields = ('programCode', 'pro_name', 'url', 'DepartmentID')
viewsets.py
class ProgramViewSet(viewsets.ModelViewSet):
queryset = Program.objects.all()
serializer_class = ProgramSerializer
filterset_class = ProgramFilter
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
__basic_fields = ( 'programCode', 'pro_name','pro_shortForm', 'DepartmentID')
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
filter_fields = ('programCode', 'DepartmentID')
search_fields = ('DepartmentID')
def list(self, request, *args, **kwargs):
programs = Program.objects.all()
serializer = ProgramMiniSerializer(programs, many=True)
return Response(serializer.data)
def get_queryset(self):
programs = Program.objects.all()
return programs
def retrieve(self, request, *args, **kwargs):
params=kwargs
print(params['pk'])
# programs = Program.objects.all()
programs = Program.objects.filter(DepartmentID = params['pk'])
serializer = ProgramMiniSerializer(programs, many=True)
return Response(serializer.data)

In list and retrieve methods where you initialize serializer, you need to pass context to it, like this:
serializer = ProgramMiniSerializer(
programs,
many=True,
context={
'request': request,
},
)

Related

CurrentUserDefault doesn't work using Django Rest

I'm working with Django / Django Rest Framework and I'm looking for a solution to insert the logged user id automatically.
i tried to use, user = serializers.HiddenField(default=serializers.CurrentUserDefault()) :
But i doesn't work
This is my serializer class
from rest_framework import serializers
from contact.models import Contact
class ContactSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Contact
fields = '__all__'
My View :
class ContactView(ListModelMixin, viewsets.GenericViewSet):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
def create(self, request):
serializeObject = ContactSerializer(data = request.data, many=True)
if serializeObject.is_valid():
serializeObject.save()
contactObject = Contact.objects.all()
contactSerializer = ContactSerializer(contactObject, many=True)
return Response(contactSerializer.data, status = status.HTTP_201_CREATED)
return Response(serializeObject.errors, status.HTTP_400_BAD_REQUEST)
When you use CurrentUserDefault you need to pass the request in the context to your serializer as that is where the serializer will get the current user from. See Including extra context [DRF docs]:
class ContactView(ListModelMixin, viewsets.GenericViewSet):
queryset = Contact.objects.all()
serializer_class = ContactSerializer
def create(self, request):
serializeObject = ContactSerializer(data = request.data, many=True, context={'request': request})
...

Django | REST | Add of top level JSON field breaks filtering option

I have to work ListAPIView view, via which I can filter via django-filter values. But I need to add an object in JSON (because AMP HTML needs that) and when I add this, It will break this filtering.
When I use this view, filtering is works great:
class TypeAPIView(generics.ListAPIView):
permission_classes = (AllowAny, )
queryset = Type.objects.all()
serializer_class = TypeSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ('code', )
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
But when I want to add a top level JSON object, it will breaks a filtering option:
class TypeAPIView(generics.ListAPIView):
permission_classes = (AllowAny, )
queryset = Type.objects.all()
serializer_class = TypeSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ('code', )
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
# --- modified from here ---
custom_data = {
'vehicles': serializer.data
}
return Response(custom_data)
# --- END modified from here ---
Is possible to add a top-level JSON object and keep the filtering of django-filter working?
Thank you!
This code is taken from django source code:
class ListModelMixin:
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
Try to use this format and add the tracklog from your terminal.

Allow partial update in serializer_class in Django REST

I am trying to partially update my ProfileSerializer when i am making PATCH request. However i am not able to make it beacuse by default Serializer doesn't allow partial changes to be made. I am using Django Rest Framwork UpdateModelMixin to handle my patch request. Where can i set partial=True in my case?
View:
class ProfileViewPartialUpdate(GenericAPIView, UpdateModelMixin):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'token'
lookup_url_kwarg = 'pk'
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')
View:
from rest_framework import generics
class ProfileViewPartialUpdate(generics.RetrieveUpdateAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'pk'
Serializer:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('token', 'bio', 'name', 'email', 'sport', 'location', 'image')
Look at this snippet code from one of my projects. You can modify accordingly. Add this to ProfileViewPartialUpdate class instead of patch.
def partial_update(self, request, slug):
user = self.request.user
get_blog = Blog.objects.get(slug=slug)
instance = self.get_object()
serializer = BlogSerializer(instance, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(data=serializer.data, status=HTTP_201_CREATED)
return Response(data="wrong parameters", status=HTTP_400_BAD_REQUEST)
Hope this might help

django restframework how to get the filtered queryset

This is an example code. In the real environment there are a lot of query params.
views.py
class EavValueViewSet(PandasMixin, viewsets.ModelViewSet):
serializer_class = serializers.EavValueSerializer
queryset = models.EavValue.objects.all()
pagination_class = None
filter_backends = (filters.DjangoFilterBackend, OrderingFilter, SearchFilter,)
search_fields = ('value',)
filter_class = EavValueFilter
ordering_fields = ('timestamp',)
ordering = ('-timestamp',)
I searched the value , url is
http://localhost:8000/api/eav_value/?search=test , and I want to something then return another Response.
How to get the filtered queryset.
you can override mixins.ListModelMixin inside viewsets.ModelViewSet if you want get filtered queryset or try anything you want. In my example i only print it in console.
class EavValueViewSet(PandasMixin, viewsets.ModelViewSet):
serializer_class = serializers.EavValueSerializer
queryset = models.EavValue.objects.all()
pagination_class = None
filter_backends = (filters.DjangoFilterBackend, OrderingFilter, SearchFilter,)
search_fields = ('value',)
filter_class = EavValueFilter
ordering_fields = ('timestamp',)
ordering = ('-timestamp',)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
# this is filtered queryset
print(queryset)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

Filters of Django REST Framework inside GET function?

Is there a way of using the Django REST filters inside a GET function I created?
It works when I use this:
class ContactListView(generics.ListAPIView):
queryset = Profile.objects.all()
serializer_class = UserContactListSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('name', 'last_name',)
But I want it to work in the GET function I created:
def get(self, request, pk, format=None):
contacts = Profile.objects.get(pk=pk)
serializer = UserContactListSerializer(contacts)
filter_backends = (filters.SearchFilter,)
search_fields = ('name', 'last_name',)
return Response(serializer.data)
Inside a Get function...
Say you had a URL like mywebsite.com/mypage/?search=[searchterm]
then in your GET function use this:
def get(self, request):
filterurl = self.request.query_params.get('search', None)
contacts = Profile.objects.all()
if filterurl is not None:
contacts = Profile.objects.filter([fieldname]=filterurl)
return Response(contacts)
In get function, the View is an instance. So filter_backends is a property of this instance. You must reupdate the property of its and call "filter_queryset" function. "filter_backends" will be used in this function.:
def get(self, request, pk, format=None):
self.filter_backends = (filters.SearchFilter,)
self.search_fields = ('name', 'last_name',)
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)