Skip to content
Advertisement

Django: ‘str’ object has no attribute ‘get’

I am trying to effectively make a Reddit clone just for practice with Django and I am trying to set up my upvote/downvote system with just a simple integer(upvote adds one, downvotes subtract one) however when I hit my “upvote” or “downvote” buttons it gives me the error 'str' object has no attribute 'get'. I have no idea what is causing this and all of the other answers with this error were not at all related, any help would be awesome. Full TraceBack:

Traceback (most recent call last):
  File "C:UsersAndreAppDataLocalProgramsPythonPython37libsite-packagesdjangocorehandlersexception.py", line 47, in inner
    response = get_response(request)
  File "C:UsersAndreAppDataLocalProgramsPythonPython37libsite-packagesdjangoutilsdeprecation.py", line 116, in __call__
    response = self.process_response(request, response)
  File "C:UsersAndreAppDataLocalProgramsPythonPython37libsite-packagesdjangomiddlewareclickjacking.py", line 26, in process_response
    if response.get('X-Frame-Options') is not None:
AttributeError: 'str' object has no attribute 'get'

My Model:

class post(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    ranking = models.IntegerField(default=0)

My Views:

class Feed(ListView):
    model = post
    template_name = 'thefeed/feed.html'

def UpvoteView(request, pk):
    selected_post = post.objects.get(pk=pk)
    selected_post.ranking+=1
    selected_post.save()
    return reverse('feed-home')

def DownvoteView(request, pk):
    selected_post = post.objects.get(pk=pk)
    selected_post.ranking-=1
    selected_post.save()
    return reverse('feed-home')

My Urls:

urlpatterns = [
    path('', views.Feed.as_view(), name="feed-home"),
    path('post/<int:pk>/downvote', views.DownvoteView, name='downvote-post'),
    path('post/<int:pk>/upvote', views.DownvoteView, name='upvote-post'),
]

My Feed.html(homepage):

{% block content %}
<div class="announcement">
    <h5 style="background: yellow;">Forum.Chat is the Internet's home for debate on any topic, keep it civil!</h5>
</div>
<br>
{% for post in object_list %}
    <div style="margin-bottom: 2%;">
        <h3><a href="{% url 'feed-post' post.pk %}">{{post.title}}</a><a href="#"></h3>
        <p><a href="#">By: {{post.author}}</a><a href="{% url 'edit-post' post.pk %}">    Edit Post</a></p>
        <p><a href="{% url 'upvote-post' pk=post.pk %}">Upvote</a><a href="{% url 'downvote-post' pk=post.pk %}">    DownVote</a></p>
    </div>
{% endfor %}
{% endblock %}

Advertisement

Answer

In your views you write return reverse('feed-home') but this will return a string being the url of the url pattern named feed-home. A view should always be returning a response object. As a shortcut you can use the redirect [Django docs] to return a response which will redirect the user:

from django.shortcuts import redirect


def UpvoteView(request, pk):
    selected_post = post.objects.get(pk=pk)
    selected_post.ranking+=1
    selected_post.save()
    return redirect('feed-home')  # Change here

def DownvoteView(request, pk):
    selected_post = post.objects.get(pk=pk)
    selected_post.ranking-=1
    selected_post.save()
    return redirect('feed-home')  # Change here

Note: Class names should ideally be in PascalCase not snake_case also function / variable names should be in snake_case not PascalCase. Hence instead of post your model should be named Post and instead of UpvoteView it should be upvote_view, etc. Have a look at PEP 8 — Style Guide for Python Code

Advertisement