1

I'm trying to render some objects from my model to HTML. I initially thought this was going to be straightforward (and it likely is) but I'm coming up against numerous errors.

In this project I have built some API views that work fine (HintsListApiView and HintsRudView work). But I'd ideally like to use the API to produce a regular - read only HTML page that I can then style as I wish - my HTMLAPIView. I'm trying to use TemplateHTMLRenderer, but am coming up against errors. All I want is to get the text attribute to show up in HTML. The actual texts are just a sentence long each. These are my files:

models.py:

from django.db import models
from rest_framework.reverse import reverse as api_reverse

class Hints(models.Model):

    text = models.TextField(max_length=255)
    author = models.CharField(max_length=20)
    timestamp = models.DateTimeField(auto_now_add=True)


    def __str__(self):
        return str(self.text)

    def timestamp_pretty(self):
        return self.timestamp.strftime('%b %d %Y')

    def get_api_url(self, request=None):
        return api_reverse("api-hints1:hints-rud", kwargs={'pk': self.pk}, request=request)

views.py:

class HTMLAPIView(generics.RetrieveAPIView):
    lookup_field = 'pk'
    serializer_class = HTMLSerializer
    renderer_classes = (TemplateHTMLRenderer,)

    def get_queryset(self):
        queryset = Hints.objects.value('text')
        return Response({'queryset': queryset}, template_name='base.html') 



class HintsListApiView(mixins.CreateModelMixin, generics.ListAPIView):

    lookup_field = 'pk'
    serializer_class = HintsSerializer

    def get_queryset(self):
        qs = Hints.objects.all()
        query = self.request.GET.get("q")
        if query is not None:
            qs = qs.filter(
                Q(text__icontains=query)|
                Q(author__icontains=query)
                ).distinct()
        return qs

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

    def get_serializer_context(self, *args, **kwargs):
        return {"request": self.request}



class HintsRudView(generics.RetrieveUpdateDestroyAPIView):

    lookup_field = 'pk'
    serializer_class = HintsSerializer

    def get_queryset(self):
        return Hints.objects.all()

    def get_serializer_context(self, *args, **kwargs):
        return {"request": self.request}

serializers.py:

class HintsSerializer(serializers.ModelSerializer):
    url = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Hints
        fields = [
            'url',
            'id', 
            'text', 
            'author', 
            'timestamp_pretty'
            ]

        read_only_fields = ['timestamp_pretty', 'id']

    def get_url(self, obj):
        request = self.context.get("request")
        return obj.get_api_url(request=request)


class HTMLSerializer(serializers.ModelSerializer):

    class Meta:
        model = Hints
        fields = [ 
        'text', 
        ]

        read_only_fields = ['text',]

root urls.py:

from django.contrib import admin
from django.conf.urls import url, include
from rest_framework import routers, serializers, viewsets

urlpatterns = [
    url('admin/', admin.site.urls),
    url(r'^api/hints/', include(('hints1.api.urls', 'api'), namespace='api-hints1')),
    url(r'^api-auth/', include('rest_framework.urls')),
]

urls.py:

from .views import HintsRudView, HintsListApiView, HTMLAPIView
from . import views
from django.contrib import admin
from django.conf.urls import url, include
from rest_framework import routers, serializers, viewsets

urlpatterns = [
    url(r'^(?P<pk>\d+)$', HintsRudView.as_view(), name='hints-rud'),
    url(r'^$', HintsListApiView.as_view(), name='hints-list'),
    url(r'^html/', HTMLAPIView.as_view(), name='html' )    
]

The errors I've faced were varied, currently I'm encountering AttributeError at /api/hints/html/

Manager object has no attribute 'value'.

I've tried with and without a serializer (because in the documentation it mentions TemplateHTMLRenderer doesn't need one). I think the problem lies within the view.py and the get_queryset function. I've tried various approaches but will get other errors like

TypeError context must be a dict rather than QuerySet.

Any help that can be provided will be greatly appreciated! Thanks!

2
  • 3
    You missed as_view method for HTMLALIView in urls.py : url(r'^html/', HTMLAPIView.as_view(), name='html' ) Commented Jul 5, 2018 at 6:46
  • @neverwalkaloner Thanks for the help! Upon adding the as_view(), I receive a AttributeError at /api/hints/html/ 'Manager' object has no attribute 'value' Commented Jul 5, 2018 at 7:39

1 Answer 1

1

So I managed to do what I wanted. But to be honest I'm not completely sure why it worked, so if anyone can provide clarification, please do.

I changed my HTMLAPIView in views.py to a Viewset:

class HTMLAPIView(viewsets.ViewSet):
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'base.html'
    serializer_class = HTMLSerializer


    def list(self, request):
        queryset = Hints.objects.order_by('pk')        
        return Response({'queryset': queryset}) 

I then got an error in my urls.py but was able to fix that by including the dictionary portion in the .as_view()

url(r'^html/', HTMLAPIView.as_view({'get': 'list'}), name='html' )

The reason why I'm not sure why this worked is that it returns my text attribute from my model as I wanted but I don't see where I specified that that's the correct attribute. Is it just because it is the first one?

I also tried commenting out the serializer and it still worked fine, so I concluded that wasn't the reason for the results.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.