Here I want to increase the number of views by 1 each time the detail view is called.How can I do it ?
class Package(models.Model):
name = models.CharField(max_length=255,unique=True)
slug = AutoSlugField(populate_from='name')
package_desc = models.TextField()
views = models.IntegerField(default=0) #want to increase views by 1 when detail_package url hits
views.py
class DetailPackage(generics.RetrieveAPIView):
serializer_class = PackageDetailSerializer
lookup_field = 'slug'
queryset = Package.objects.all()
urls.py
path('<slug>/detail/', DetailPackage.as_view(), name='detail_package'),
I am very new to django rest framework.So am I going the right way by using the generics API view for such cases ?
You can override the retrieve method on (generics.RetrieveAPIView)..take a look at this http://www.cdrf.co/3.9/rest_framework.generics/RetrieveAPIView.html#retrieve
Here is an example
from django.db.models import F
class DetailPackage(generics.RetrieveAPIView):
...
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
# increment the value
type(instance).objects.filter(pk=instance.pk).update(
views=F('views') + 1,
)
return Response(serializer.data)
As #Aprimus suggested I solved this by overriding the retrieve() method like this:
Please correct me if I didn't do it correctly.
class DetailPackage(generics.RetrieveAPIView):
serializer_class = PackageDetailSerializer
lookup_field = 'slug'
queryset = Package.objects.all()
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
instance.views += 1
instance.save()
serializer = self.get_serializer(instance)
return Response(serializer.data)
Related
I need to increase the view count with 1 on each refresh. I'm not sure about the method since I'm new to DRF. Thanks in advance.
models.py
class Module(models.Model):
name = models.CharField(max_length=250, default="")
view_count = models.IntegerField(default=0)
serializers.py
class ModuleSerializer(serializers.ModelSerializer):
class Meta:
model = Module
fields = "__all__"
views.py
class ModuleView(generics.ListAPIView):
queryset = Module.objects.all()
serializer_class = ModuleSerializer
def get(self, request):
obj = self.get_object
print(obj)
obj.view_count = obj.view_count + 1
obj.save(view_count="view_count")
return super().get(request)
i implemented view count with F expression because a view count is basicly a race condidition and the docs clearly state that
Avoiding race conditions using F()
Documentation
class ElonDetail(generics.RetrieveAPIView):
queryset = Elon.objects.all()
serializer_class = ElonDetailSerializer
lookup_field = 'slug'
#retrieve
def retrieve(self, request, *args, **kwargs):
obj = self.get_object()
print(obj)
obj.view = obj.view + 1
obj.save(update_fields=['view',])
serializer = self.get_serializer(obj)
return Response(serializer.data, status=200)
here i used RetrieveAPIView
I'm trying to use this django app https://github.com/TheBimHub/django-flaggit
I have installed the flaggit via pip. Then in views.py I have
import flaggit
def flag_thread(request, **kwargs):
thread_id = request.GET.get('thread_id')
thread = Thread.objects.find(id=thread_id)
flaggit.utils.flag(thread, user=None, ip=None, comment=None)
is this correct? what does urls.py look like?
First make a serializer
from flaggit.models import FlagInstance
...
class FlagInstanceSerializer(serializers.ModelSerializer):
class Meta:
model = FlagInstance
fields = '__all__'
then use the serializer in a new endpoint
class ThreadViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
queryset = Thread.objects.all().order_by('-created_at')
pagination_class = ThreadViewSetPaginationClass
#action(detail=True, methods=['post'])
def flag(self, request, pk=None):
thread = self.get_object()
flag_instance = flaggit.utils.flag(thread, user=request.user, ip=None, comment=None)
serializer = FlagInstanceSerializer(data=flag_instance)
serializer.is_valid()
return Response(serializer.data)
I went ahead and fixed the migrations and admin panel in a fork https://github.com/morenoh149/django-flaggit
views.py
class variable__list(ListAPIView):
"""
get:
returns a list of variable names
"""
serializer_class = VariableSerializer
pagination_class = PageNumberPagination
page_size = 5
def get_queryset(self):
return Variable.objects.all()
def get(self, request, format=None):
# base queryset
queryset = self.get_queryset()
# return serialized data
if queryset.exists():
serializer = VariableSerializer(queryset, many=True)
return Response(serializer.data)
else:
return Response({"Returned empty queryset"}, status=status.HTTP_404_NOT_FOUND)
settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 5,
}
When I go to the endpoint api/v1/variable/?page=1,
I get the same list returned of 100 results. My understanding is this should automatically be working when I set the pagination globally in settings.py, on top of that I have ALSO defined the paginator at the class level and still nothing is being paginated. What am I doing wrong here?
Remove get and get_queryset method, if there is no custom logic inside it.
class variable__list(ListAPIView):
"""
get:
returns a list of variable names
"""
queryset = Variable.objects.all()
serializer_class = VariableSerializer
pagination_class = PageNumberPagination
page_size = 5
If you have some custom code inside it, you need to send paginated response manually
def get(self, request, format=None)
paginator = PageNumberPagination()
paginator.page_size = 10
queryset = self.get_queryset()
result_page = paginator.paginate_queryset(queryset, request)
serializer = VariableSerializer(result_page, many=True)
return paginator.get_paginated_response(serializer.data)
my filter isn't working Whenever I access http://localhost:8080/payables/invoices/?status=NOT_PAID It just returns all the invoices. I have no runtime error, the parameter I enter simply seems to be ignored. I really don't understand, other than that, it works well.
views.py
class InvoiceViewSet(viewsets.ViewSet):
serializer_class = InvoiceSerializer
filter_backend = filters.DjangoFilterBackend
filter_fields = ('status','supplier',)
def list(self,request,):
queryset = Invoice.objects.filter()
serializer = InvoiceSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
queryset = Invoice.objects.filter()
invoice = get_object_or_404(queryset, pk=pk)
serializer = InvoiceSerializer(invoice)
return Response(serializer.data)
class InvoiceItemViewSet(viewsets.ViewSet):
serializer_class = InvoiceItemSerializer
def list(self,request,invoice_pk=None):
queryset = InvoiceItem.objects.filter(invoice=invoice_pk)
serializer = InvoiceItemSerializer(queryset,many=True)
return Response(serializer.data)
def retrieve(self,request,pk,invoice_pk):
queryset = InvoiceItem.objects.filter(pk=pk,invoice=invoice_pk)
invoice_item = get_object_or_404(queryset,pk=pk)
serializer = InvoiceItemSerializer(invoice_item)
return Response(serializer.data)
url.py
from django.conf.urls import url, include
#viewset
from rest_framework_nested import routers
from payables.views import InvoiceViewSet,InvoiceItemViewSet
router = routers.SimpleRouter()
router.register(r'invoices', InvoiceViewSet,base_name='invoices')
invoice_item_router = routers.NestedSimpleRouter(router,r'invoices',lookup='invoice')
invoice_item_router.register(r'items', InvoiceItemViewSet, base_name='invoice_items')
urlpatterns = [
url(r'^',include(router.urls)),
url(r'^',include(invoice_item_router.urls))
]
It is because you are explicitly creating the queryset and hence the filter backend is never used:
queryset = Invoice.objects.filter()
I suggest looking at ModelViewSet. In that case you just have to pass queryset at the view level and rest will be taken care of.
instead of queryset = Invoice.objects.filter()
with queryset = self.filter_queryset(self.get_queryset()).filter()
instead of queryset = Invoice.objects.filter()
use queryset = self.get_queryset()
self.get_queryset() returns the filtered object list
models.py
class Lab(Model):
acronym = CharField(max_length=10)
class Message(Model):
lab = ForeignKey(Lab)
urls.py
urlpatterns = patterns('',
url(r'^(?P<lab>\w+)/$', ListView.as_view(
queryset=Message.objects.filter(lab__acronym='')
)),
)
I want to pass the lab keyword argument to the ListView queryset. That means if lab equals to TEST, the resulting queryset will be Message.objects.filter(lab__acronym='TEST').
How can I do that?
You need to write your own view for that and then just override the get_queryset method:
class CustomListView(ListView):
def get_queryset(self):
return Message.objects.filter(lab__acronym=self.kwargs['lab'])
and use CustomListView in urls also.
class CustomListView(ListView):
model = Message
def get(self, request, *args, **kwargs):
# either
self.object_list = self.get_queryset()
self.object_list = self.object_list.filter(lab__acronym=kwargs['lab'])
# or
queryset = Lab.objects.filter(acronym=kwargs['lab'])
if queryset.exists():
self.object_list = self.object_list.filter(lab__acronym=kwargs['lab'])
else:
raise Http404("No lab found for this acronym")
# in both cases
context = self.get_context_data()
return self.render_to_response(context)