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
notsnake_case
also function / variable names should be insnake_case
notPascalCase
. Hence instead ofyour model should be namedpost
Post
and instead ofit should beUpvoteView
upvote_view
, etc. Have a look at PEP 8 — Style Guide for Python Code