Reputation: 111
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:\Users\Andre\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Andre\AppData\Local\Programs\Python\Python37\lib\site-packages\django\utils\deprecation.py", line 116, in __call__
response = self.process_response(request, response)
File "C:\Users\Andre\AppData\Local\Programs\Python\Python37\lib\site-packages\django\middleware\clickjacking.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 %}
Upvotes: 1
Views: 3362
Reputation: 21807
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
Upvotes: 1
Reputation: 527
could you try it like this:
def UpvoteView(request, pk):
selected_post = post.objects.get(pk=pk)
selected_post.ranking = selected_post.ranking +1
selected_post.save()
return reverse('feed-home')
are you able to get post.objects.all()
Upvotes: 1