Is there a way to call pagination methods get_next_link and get_previous_link in DRF viewset? - django-rest-framework

I want to add additional values ​​to the pagination response in my viewset and keep the fields what already there. I was able to add count, but i can`t add next and previous urls to response, is where a way to call pagination_class methods in viewset.
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(queryset, many=True)
return self.get_paginated_response(serializer.data)
else:
status_count = Vps.objects.all().aggregate(
started=Count("status", filter=Q(status="started")),
blocked=Count("status", filter=Q(status="blocked")),
stopped=Count("status", filter=Q(status="stopped"))
)
serializer = self.get_serializer(queryset, many=True)
status_count["results"] = serializer.data
return Response(status_count)
def get_paginated_response(self, data):
status_count = Vps.objects.all().aggregate(
started=Count("status", filter=Q(status="started")),
blocked=Count("status", filter=Q(status="blocked")),
stopped=Count("status", filter=Q(status="stopped"))
)
pagination = self.pagination_class()
page = self.paginate_queryset(data)
return Response(OrderedDict([
('count', pagination.get_count(data)),
('next', self.pagination_class.get_next_link),
('previous', self.pagination_class.get_previous_link),
('started', status_count["started"]),
('blocked', status_count["blocked"]),
('stopped', status_count["stopped"]),
('results', page)
]))

I was able to solve this by creating custom pagination class
class VpsLimitOffsetPagination(LimitOffsetPagination):
def get_paginated_response(self, data):
status_count = Vps.objects.all().aggregate(
started=Count("status", filter=Q(status="started")),
blocked=Count("status", filter=Q(status="blocked")),
stopped=Count("status", filter=Q(status="stopped"))
)
return Response(OrderedDict([
('count', self.count),
('started', status_count["started"]),
('blocked', status_count["blocked"]),
('stopped', status_count["stopped"]),
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data)
]))

Related

How can I delete cache_page in Django?

I cached the view using cache_page in Django. But I want to clear the cache_page when a model in my view is updated.
views.py
#method_decorator(cache_page(168 * 3600,), name="dispatch")
class DashboardView(APIView):
permission_classes = [AllowAny]
def get(self, request):
m1 = Model1.objects.all()
m1_serializer = Model1Serializer(sliders, many=True)
m2 = Model2.objects.all()
m2_serializer = Model2Serializer(
collections, many=True
)
m3 = Model3.objects.all()
m3_serializer = Model3Serializer(categories, many=True)
response = {
"m1": m1_serializer.data,
"m2": m2_serializer.data,
"m3": m3_serializer.data,
}
return Response(response)
If a new record is added to any of these models, cache_page should be deleted.
signals.py
#receiver(post_save, sender=Model1)
def clear_cache_when_update_model1(
sender, instance, created, **kwargs
):
if created:
pass
#receiver(post_save, sender=Model2)
def clear_cache_when_update_model2(
sender, instance, created, **kwargs
):
if created:
pass
#receiver(post_save, sender=Model3)
def clear_cache_when_update_model3(
sender, instance, created, **kwargs
):
if created:
pass
I couldn't find the key of cache_page and couldn't find how to clear cache_page.

SerializerMethodField doesn't work on DRF

Here is the simplified verison of the Serializer what I have:
class CommentSerializer(serializers.HyperlinkedModelSerializer):
def __init__(self, *args, **kwargs):
init = super().__init__(*args, **kwargs)
return init
username = serializers.ReadOnlyField(source='user.username')
user_id = serializers.ReadOnlyField(source='user.id')
user = UserSerializer(read_only=True)
url_field_name = 'url_api'
# and more definitions
content_type_id = serializers.IntegerField()
site_id = serializers.SerializerMethodField('_siteId')
def _siteId(self, threadedcomment):
site_id = settings.SITE_ID
return site_id
class Meta:
model = ThreadedComment
fields = ('url_api','url','id','title','tree_path','comment','submit_date','submit_date_unix','submit_date_humanized','root_id','is_removed',
'parent_id','last_child_id','newest_activity','depth','username','user_id','object_pk','content_type_id','user',
'site_id',
)
read_only_fields = ('id','title','tree_path','submit_date','root_id','is_removed',
'parent_id','last_child_id','newest_activity','depth','username','user_id',
# 'site_id',
)
class CommentViewSet(viewsets.ModelViewSet):
queryset = ThreadedComment.objects.all().annotate().all()
serializer_class = CommentSerializer
permission_classes = []
filter_backends = [filters.OrderingFilter]
def filter_queryset(self, queryset):
return queryset
def list(self, request):
return super().list(request)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
# site_id = settings.SITE_ID
# serializer.save(user=self.request.user, site_id=site_id, )
return super().perform_create(serializer)
Now I make an http post request on the api as i.e.:
axios.post('/api/comments/', {
"comment":"test.",
"object_pk":34,
"content_type_id":12,
},
It shows me an error:
500 (Internal Server Error)
IntegrityError: NOT NULL constraint failed: django_comments.site_id
The problem (a pure question) is, why the SerializerMethodField doesn't work? I put a breakpoint on the site_id = settings.SITE_ID line, but it doesn't hit, which means the line hasn't even executed.
I also tried putting a set of lines (the commented lines) on perform_create, reading a SO post, but the result is the same, the same error, NOT NULL constraint failed.
I'm certainly passing a value, but it shows it's a null value, saying nothing is passed, what this means? What am I donig wrong here? Thanks.

'InMemoryUploadedFile' object is not callable

While uploading the csv file showing "'InMemoryUploadedFile' object is not callable " this error, i want to import the csv file data into database using APIview.
Here My Apiview
class UploadViewSet(APIView):
parser_classes = (MultiPartParser, FormParser)
permission_classes = (AllowAny,)
serializer_class= UploadSerializer
def post(self, request, *args, **kwargs):
serializer = UploadSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
file = serializer.validated_data['File']
reader = csv.reader(file('file','r'))
for row in reader():
new_company = Company(
name=row['name'],
hr_name=row['hr_name'],
hr_email=row['hr_email'],
hr_verified=row['hr_verified'],
user_id=row['user_id'],
primary_phone=row['primary_phone'],
comments=row['comments'],
)
new_company.save()
return Response({"status": "success"},status.HTTP_201_CREATED)

how could I POST the data in DJANGO rest_frame?

I want to insert Track record through a condition but it does not happen. Please help me how could I do fix it?
this is views.py
class Track(APIView):
http_method_names = ['post',]
def post(self,request, *args, **kwargs):
employee = Employee.objects.filter(username=kwargs.get('username'), password=kwargs.get('password'))
if employee.exists():
serializer_class = TrackSerializer
try:
if serializer_class.is_valid():
serializer_class.save()
return Response(serializer_class.data, status = status.HTTP_201_CREATED)
except Exception as e:
print(e)
return Response(serializer_class.errors, status = status.HTTP_404_NOT_FOUND)
urls.py
path('track/<username>/<password>/',views.TrackList.as_view(),name = 'track'),
You have to pass data to your serializer
class Track(APIView):
http_method_names = ['post',]
def post(self,request, *args, **kwargs):
employee = Employee.objects.filter(username=kwargs.get('username'), password=kwargs.get('password'))
if employee.exists():
serializer_class = TrackSerializer(data=request.data)
try:
if serializer_class.is_valid():
serializer_class.save()
return Response(serializer_class.data, status = status.HTTP_201_CREATED)
except Exception as e:
print(e)
return Response(serializer_class.errors, status = status.HTTP_404_NOT_FOUND)

Django Rest Framework, custom page_size for list_route action

I have a list_route:
#list_route(methods=['get'])
def bought(self, request):
bought_photos = Photo.objects.filter(is_bought=True)
page = self.paginate_queryset(bought_photos)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(bought_photos, many=True)
return Response(serializer.data)
How can I set a custom page_size only for the list_route, not for its ModelViewSet?
SOLUTION
1) create CustomPagination class
from rest_framework.pagination import PageNumberPagination
class CustomPagination(PageNumberPagination):
page_size = 10000
page_size_query_param = 'page_size'
2) edit the list_route code:
#list_route(methods=['get'])
def bought(self, request):
bought_photos = Photo.objects.filter(is_bought=True)
paginator = CustomPagination()
page = paginator.paginate_queryset(bought_photos, request)
if page is not None:
serializer = self.get_serializer(page, many=True)
return paginator.get_paginated_response(serializer.data)
serializer = self.get_serializer(bought_photos, many=True)
return Response(serializer.data)
I think the following code should be enough:
#list_route(methods=['get'], pagination_class=CustomPagination)
def bought(self, request):
bought_photos = Photo.objects.filter(is_bought=True)
page = self.paginate_queryset(bought_photos)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(bought_photos, many=True)
return Response(serializer.data)

Resources