0

I'm a beginner with the Django REST framework and am building an app that summarizes articles with headers. I'm trying to get information from the Article model to pass into the Summary one. I'm having trouble understanding the use of get_object_or_404 in this scenario (how to instantiate a model) and how I use the pk argument. I tried changing the status URL to status/<int:article_id> and passed article as the pk, but I get a 404 when running the POST request. I'm stuck on how to use that argument otherwise. How do I instantiate a model from my request by using get_object_or_404 properly?

views.py:

import json
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, JsonResponse
from rest_framework.decorators import api_view
from .models import *


@api_view(['POST'])
def get_summary(request, pk):
    article = get_object_or_404(Article, pk=pk)
    mdl = Summary()
    return JsonResponse(mdl.preprocess(article.content), safe=False)

models.py:

# Article class
class Article(models.Model):
    headings = models.CharField(max_length=200)
    content = models.CharField(max_length=500000)


# Summary results class (so far)
class Summary(models.Model):
    preprocessor = TextPreprocessor()
    in_text = models.CharField(max_length=500000)
    topics = models.CharField(max_length=200)

    def preprocess(self, text):
        return self.preprocessor.preprocess(text)

urls.py:

from django.urls import path, include
from rest_framework import routers
from .api import *
from .views import *

router = routers.DefaultRouter()
router.register('my_api', SummaryViewSet, 'api')

urlpatterns = [
    path('api/', include(router.urls)),
    path('status/', get_summary)
]

1 Answers1

1

get_object_or_404 results are in the name. This will raise an error if the object is not found. So you're getting the 404 inside of the view then it is becuase the object does not yet exist. You might be confusing this with get_or_create. I will show you a solution using function-based views.

https://www.django-rest-framework.org/api-guide/views/

https://www.django-rest-framework.org/tutorial/2-requests-and-responses/

@api_view(['GET','POST'])
def get_summary(request, pk):
    mdl = Summary()
    if request.method == 'GET':
        article = get_object_or_404(Article, pk=pk)
        return JsonResponse(mdl.preprocess(article.content), safe=False)
    # this will run on POST
    article = Article()
    article.heading, article.content = request.data['heading'], request.POST['content']
    article.save()
    return JsonResponse(mdl.preprocess(article.content), safe=False)

============================

You might benefite from using CBV's

from rest_framework.views import APIView
from rest_framework.response import Response

class GetSummary(APIView):
    
    def get(self, request, pk):
        ..run get logic above..
        return Response(..any data from serialer or even a string)
  
    def post(self, request, pk):
        ...run post logic above

Also, simply make your model attr for content a text field like so..

models.py

class Article(models.Model):
    headings = models.CharField(max_length=200)
    content = models.TextField()
enjoi4life411
  • 568
  • 5
  • 11
  • What would be the difference here between using request.data['content'] and request.POST['content']? The former only works for me for some reason – Camille Dunning Jun 20 '21 at 23:32
  • Basically request.data is more flexible, and is recommended by the docs actually for Django Rest anyway. I'll update my answer to use request.data. https://stackoverflow.com/questions/28545553/django-rest-frameworks-request-post-vs-request-data – enjoi4life411 Jun 20 '21 at 23:35
  • Ok, got it. I also wouldn't need a GET request at all to retrieve this data right? – Camille Dunning Jun 20 '21 at 23:50
  • Please dont forget to accept the answer if this worked. Oh and right now, your decorator has set this view to only accept POST requests. If you try to do a GET, it will result in an error. So this endpoint is only accepting POST, and the logic here is the instance is being updated each time. At which point, after adding api_view(['GET', 'POST"]), you would have to build out the logic in the view.Like if request.method == 'GET' ...do such and such.. If you meant to allow GET for this endpoint as well I can add that – enjoi4life411 Jun 20 '21 at 23:54
  • Ok, accepted. Yes, I think allowing GET would be better, and I'm not sure what the logic would be for that (I think I just want to save each instance in my database) – Camille Dunning Jun 20 '21 at 23:58
  • Updated my anwer for you. In that case get_or_create would cuase things to be too confusing to work. I like using CBV's they help keep things concise. Function-based views draw the logic out and can make things a bit convuluted. – enjoi4life411 Jun 21 '21 at 00:07
  • Thank you! I'll start looking into CBVs. – Camille Dunning Jun 21 '21 at 00:08