I wanna load results.html when I put vote button - python

I am making a web site by seeing Django tutorial.
I wanna load results.html when I put vote button is in detail.html ,but now index.html is loaded.detail.html is
{% extends "polls/base.html" %}
{% load bootstrap3 %}
{% block contents %}
<h1>{{ question.question_text }}</h1>
<!--{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}-->
<form action="{% url 'polls:poll_vote' question.id %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Vote" />
</form>
{% endblock %}
When I put vote button is this code <input type="submit" value="Vote" />,
I wanna show results.html .
views.py is
from django.shortcuts import render
from django.urls import reverse_lazy
from django.utils.html import mark_safe
from .models import Question
from django.http import HttpResponse
from django.shortcuts import Http404
from django.shortcuts import get_object_or_404,redirect
from .models import Choice
from django.views.generic import TemplateView
from django.views.generic import DetailView
from django.views.generic import ListView
from .forms import MyForm
from .forms import VoteForm
from django.views.generic import FormView
from django.views.generic.detail import SingleObjectMixin
from django.shortcuts import resolve_url
from django.contrib import messages
# Create your views here.
def index(request):
return render(request,'polls/index.html',{
'questions': Question.objects.all(),
})
def vote(request,pk):
question = get_object_or_404(Question,pk=pk)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError,Choice.DoesNotExist):
return render(request,'poll/detail.html',{
'question':question,
'error_message':"You didn't select a choice",
})
else:
selected_choice.votes += 1
selected_choice.save()
return redirect('index')
return redirect('poll_results', pk)
# pass
def results(request,pk):
obj = get_object_or_404(Question,pk=pk)
return render(request,'polls/results.html',{
'question':obj,
})
class FormTest(FormView):
form_class = MyForm
template_name = 'polls/form.html'
success_url = reverse_lazy('polls:index')
form_test = FormTest.as_view()
class Detail(SingleObjectMixin,FormView):
model = Question
form_class = VoteForm
context_object_name = 'question'
template_name = 'polls/detail.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().post(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super().post(request, *args, **kwargs)
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['question'] = self.object
return kwargs
def form_valid(self, form):
form.vote()
choice = form.cleaned_data['choice']
messages.success(self.request,'"%s"に投票しました' % choice)
return super().form_valid(form)
def get_success_url(self):
return resolve_url('polls:results',self.kwargs['pk'])
detail = Detail.as_view()
I think def vote(request,pk) is read,so return redirect('poll_results', pk) is also read and results.html is load.But my ideal flow is not realized.Was I wrong to write directory?
Directory is
How can I fix this?return redirect('polls_results', pk) did not work.
Now I received one answer,
vote method in views.py is
def vote(request,pk):
question = get_object_or_404(Question,pk=pk)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError,Choice.DoesNotExist):
return render(request,'poll/detail.html',{
'question':question,
'error_message':"You didn't select a choice",
})
else:
selected_choice.votes += 1
selected_choice.save()
return redirect('index')
return redirect(reverse('polls_results'), pk=pk)
but same error happens.
urls.py in polls is
from django.conf.urls import url
from django.views.generic import TemplateView
from . import views
app_name="polls"
urlpatterns = [
url(r'(?P<pk>\d+)/$', views.detail, name='poll_detail'),
url(r'(?P<pk>\d+)/vote$', views.vote, name='poll_vote'),
url(r'(?P<pk>\d+)/results$', views.results, name='poll_results'),
url(r'^$',views.index,name='index'),
url(r'^form$', views.form_test),
]

It seems that you are using namespaced urls.
In that case, you should use the namespace prefix whenever you use reverse, redirect or {% url %}.
return redirect('polls:polls_results', pk=pk)

Use reverse or write the correct path in redirect method.
Example:
from django.urls import reverse
def the_view(request):
# change here
return redirect(reverse('poll_results'), pk=pk)
# or
return redirect('results_url', pk=pk)
EDIT: Based on your urlpatterns, it seems that you're passing the wrong name in the reverse method, polls_results, where as you've defined it to be as poll_results.
You haven't removed the redirect to index statement in else part of the code in vote method.
def vote(request, pk):
# your code
else:
# save to model
# remove redirect statement here
return redirect(reverse('poll_results'), pk=pk)
Ref: https://docs.djangoproject.com/en/1.11/ref/urlresolvers/#reverse

Related

Django: Problem deleting an Authenticated User profile

I'm having problems deleting a user, where the authenticated user can delete their own account.
But what happens is that the page just refreshes, in the same template and returning '200 ok from POST'
[06/Aug/2022 11:46:33] "POST /members/profile/ HTTP/1.1" 200 4998
members.views.profiles.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
#login_required(login_url="/accounts/login/")
def profile(request):
template_name = "members/profile.html"
context = {}
return render(request, template_name, context)
def profile_delete(request, pk):
user_profile = User.objects.filter(pk=pk)
template_name = "members/profile_delete.html"
context = {
"user_profile": user_profile,
},
if request.method == "POST":
user_profile.delete()
return render(request, template_name, context)
return render(request, template_name, context)
members.urls.py
from django.urls import path
from allauth.account import views as allauth_views
from . import views
app_name = "members"
urlpatterns = [
path("login/", allauth_views.LoginView.as_view(), name="login"),
path("logout/", allauth_views.LogoutView.as_view(), name="logout"),
path("profile/", views.profile, name="profile"),
path("profile/<int:pk>/delete/", views.profile_delete, name="profile_delete"),
]
profile.html
<div>
<form method="POST">
{% csrf_token %}
<p>Are you sure you want to delete <strong>{{ user | title }}</strong> ?</p>
<button class="btn btn-danger" href="{% url 'members:profile_delete' user.pk %}" type="submit">
Delete
</button>
</form>
</div>
Solution:
views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
#login_required(login_url="/accounts/login/")
def profile(request):
template_name = "members/profile.html"
context = {}
return render(request, template_name, context)
def profile_delete(request, pk):
user_profile = get_object_or_404(User, pk=pk)
user_profile.delete()
template_name = "members/profile_delete.html"
context = {}
return render(request, template_name, context)
When you're pressing your button the server sends a GET request, try changing the logic in your function, instead of:
if request.method == "POST":
Use:
if request.method == "GET":
You should use get_object_or_404 for querying single user's profile and then delete it, currently filter() makes no sense, so:
user_profile=get_object_or_404(User,pk=pk)
Note: you should always return HttpResponseRedirect after dealing with POST data, the tip is not specific to Django, it's a good web practice in general.

"Post.user" must be a "User" instance

I am new to using django and I'm creating a simple webpage that takes in user input and saves it to the Model Form
models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Post(models.Model):
post = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE)
forms.py
from django import forms
from .models import Post
class HomeForm(forms.ModelForm):
post = forms.CharField()
class Meta:
model = Post
fields = ('post',)
views.py
from django.shortcuts import render, redirect
# Create your views here.
from django.http import HttpResponse
from django.views.generic import TemplateView
from .forms import HomeForm
class HomeView(TemplateView):
template_name = 'home.html'
def get(self, request):
form = HomeForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = HomeForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
text = form.cleaned_data['post']
form = HomeForm()
return redirect('home.html')
args = {'form': form, 'text': text}
return render(request, self.template_name, args)
home.html
{% block body %}
<div class ='container'>
<h1>Home</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type ='submit'>Submit</button>
</form>
</div>
{% endblock %}
When I run the server the webpage comes up normal but when I type in some input an error page pops up and says : ValueError at /
Cannot assign ">": "Post.user" must be a "User" instance.
Any Help would be appreciated!

Django Form in ListView, error on POST of Form

Im trying to implement a chat-function for my website. In order to do that, i followed the following tutorial: https://channels.readthedocs.io/en/latest/tutorial/
I've then changed the code a little bit in order to implement it. Until here, everything works just fine. Now I want to store the form-data inside of a database, and thats where the problem appears.
But first my code:
urls.py:
from django.urls import path
from .views import ChatOverView
urlpatterns = [
path('<int:pk>/', ChatOverView.as_view(), name='chat-explicit'),
path('', ChatOverView.as_view(), name='chat-home'),
]
views.py (theres much code here that is probably not needed for this question, but since i dont know what part of it i can ignore, im just posting the whole file-content):
from django.views.generic import ListView
from django.views.generic.edit import FormMixin, FormView
from django.db.models import Q
from django.urls import resolve
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from .models import Message
from .forms import MessageRegisterForm
class ChatOverView(ListView, FormMixin):
model = Message
template_name = 'chat/home-chat.html'
form_class = MessageRegisterForm
success_url = '/thanks/'
def form_valid(self, form):
form = self.get_form()
if form.is_valid():
data = form.cleaned_data
return super().form_valid(form)
def get_context_data(self, *args, **kwargs):
context = super(ChatOverView, self).get_context_data(*args, **kwargs)
messages_raw = reversed(Message.objects.filter(Q(sender=self.request.user) | Q(receiver=self.request.user)))
messages = {}
for mes in messages_raw:
# i am receiver
if mes.sender != self.request.user:
if mes.sender in messages:
messages[mes.sender].append({"received": mes})
else:
messages.update({mes.sender: [{"received": mes}]})
# i sent
else:
if mes.receiver in messages:
messages[mes.receiver].append({"sent": mes})
else:
messages.update({mes.receiver: [{"sent": mes}]})
active_user = self.get_active_chat(messages)
chatroom_name = self.get_chatroom_name(active_user)
context.update(messages_data=messages, active=active_user, roomname=chatroom_name)
return context
def get_chatroom_name(self, active_chat):
# my convention
ids = [active_chat.id, self.request.user.id]
ids.sort()
return str(ids[0]) + '_' + str(ids[1])
def get_active_chat(self, messages):
url_name = resolve(self.request.path_info).url_name
if url_name == "chat-home":
return list(messages.keys())[0]
else:
pk_user = self.request.build_absolute_uri().split("/")[-2]
user = get_object_or_404(User, pk=pk_user)
return user
home-chat.html:
{% extends "solawi/base.html" %}
{% load define_dictfilters %}
{% block content %}
<form class="bg-light" method="post">
<div class="input-group">
{% csrf_token %}
{{ form }}
<div class="input-group-append">
<button type="submit" id="chat-message-submit" value="enter">send</button>
</div>
</div>
</form>
{% endblock content %}
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Message(models.Model):
sender = models.ForeignKey(User, related_name="sender", on_delete=models.CASCADE)
receiver = models.ForeignKey(User, related_name="receiver", on_delete=models.CASCADE)
content = models.TextField()
date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.sender.username + ' to ' + self.receiver.username
The rest of the files/settings entrys are the same as in the tutorial linked above.
Now comes the problem: when submitting the form, i get the following error:
Method Not Allowed (POST): /chat/
Method Not Allowed: /chat/
HTTP POST /chat/ 405 [0.00, 127.0.0.1:54424]
How can i fix it?
Thank you for your Help!!
ListView implements a get() method, but no post() method. You need to implement a post() method in order for the view to allow POST requests.
You could subclass django.views.generic.ProcessFormView to get this, or, if you really need a ListView, then you can add a post() method to the class which handles the form validation and whatever else you need to do. Here is how ProcessFormView implements it:
def post(self, request, *args, **kwargs):
"""
Handle POST requests: instantiate a form instance with the passed
POST variables and then check if it's valid.
"""
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)

Reverse for 'edit' with arguments '(9,)' and keyword arguments '{}' not found. 0 pattern(s) tried: []

I'm getting an error when trying to access edit link in django, i have looked here on stack overflow but i haven't found the solution that works in my case.
ERROR :
Exception Type : NoReverseMatch
Exception Value : Reverse for 'edit' with arguments '(9,)' and keyword arguments '{}' not found. 0 pattern(s) tried: [] arguments '{}' not found. 0 pattern(s) tried: []
this is my urls.py
from django.conf.urls import url, include
from django.contrib import admin
from posts import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^create/$', views.create, name='create'),
url(r'^(?P<id>\d+)/$', views.show_post, name = 'show_post'),
url(r'^(?P<id>\d+)/edit/$', views.update_post, name = 'update_post'),
url(r'^(?P<id>\d+)/delete/$', views.delete_post),
]
views.py
from django.contrib import messages
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse, HttpResponseRedirect
from .forms import PostForm
from .models import Post
# Create your views here.
def index(request):
post_list = Post.objects.order_by('-created_date')[:10]
context = {'post_list': post_list}
return render(request, 'index.html', context)
def create(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
#flass messages
messages.success(request, "Successfully created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form":form,
}
return render(request, 'post_form.html', context)
def show_post(request, id=None):
instance = get_object_or_404(Post, id=id)
context = {'instance': instance}
return render(request, 'show_post.html', context)
def update_post(request, id=None):
instance = get_object_or_404(Post, id=id)
form = PostForm(request.POST or None, instance=instance)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
messages.success(request, "Post updated")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form":form,
"instance":instance
}
return render(request, 'post_form.html', context)
def delete_post(request, id=None):
instance = get_object_or_404(Post, id=id)
instance.delete()
messages.success(request, "Successfully deleted")
return redirect("posts:index")
show_post.html
{% extends "base.html" %}
<div class="container">
{% block content %}
<h1> {{instance.title}} </h1>
<h3>{{instance.content| linebreaks}} </h3>
Home | <a href="{{instance.url}}" target="_blank" > visit url</a> |
Edit
{% endblock %}
</div>
You need to use the namespace. Rather than 'edit', you should use 'posts:edit'.
Or 'posts:update_post' depending which name you're using in urls.py.

Django 'WSGIRequest' object has no attribute 'text'

Goal/tl;dr I want to call my added method from views.py when you submit the forum and use the stuff from the textfield to make a new post object.
I am new to django, and I have looked through other stack posts, but most of these errors seem to be for cookies or users. I have also looked at the python documentation as most people have suggested, but I haven't seen all the pieces together and I am not sure how to get the textfield from the forum. Correct code and/or and explanation of what I am doing wrong and how to do it would be much appreciated.
models.py
from django.db import models
class Post(models.Model):
text = models.TextField(max_length=250)
time = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.text
views.py
from django.http import Http404, HttpResponse
from django.shortcuts import render_to_response, redirect
from blog.models import Post
from django.core.context_processors import csrf
def home(request):
try:
p = Post.objects.all()
except Post.DoesNotExist:
raise Http404
return render_to_response('index.html',
{'post':p})
def post(request, uID):
try:
p = Post.objects.get(pk=uID)
except:
raise Http404
return render_to_response('post.html',
{'post':p})
def delete(request, uID):
try:
p = Post.objects.get(pk=uID).delete()
except:
raise Http404
return render_to_response('delete.html',
{'post':p})
def new(request):
context = {}
context.update(csrf(request))
return render_to_response('new.html', context)
def added(request):
if request.method == 'POST':
context = {}
context.update(csrf(request))
p = Post.objects.create(text=request.text)
p.save()
return render_to_response("index.html", context)
else:
raise Http404
urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'blog.views.home', name='home'),
url(r'^(?P<uID>\d+)/$', 'blog.views.post', name='Post Id'),
url(r'^(?P<uID>\d+)/delete/$', 'blog.views.delete', name='del'),
url(r'^new/$', 'blog.views.new'),
url(r'^created/$', 'blog.views.added'),
# url(r'^myApp/', include('myApp.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
)
new.html
<html>
<body>
<h2> Create a new Post </h2>
<form method="post" action="/created/">
{% csrf_token %}
Body: <input type="textarea" name="text">
<input type="submit" value="Submit">
</form>
</body>
</html>
You mean request.POST['text'].
You should probably investigate the forms framework though.

Categories