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.
Related
I was doing some How-To tutorials about Django Forms.
But it will not display anything for me. Any ideas why? Picture below illustrates my problem.
This is my Login -> index.html
<body>
<div class="gradient-border" id="box">
<h2>Log In</h2>
<form action = "" method = "post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
</div>
</body>
this is forms.py
class InputForm(forms.Form):
first_name = forms.CharField(max_length = 200)
last_name = forms.CharField(max_length = 200)
password = forms.CharField(widget = forms.PasswordInput())
this is views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import InputForm
def index(request):
return render(request, 'login/index.html')
def home_view(request):
context ={}
context['form']= InputForm()
return render(request, "index.html", context)
def main(request):
return render(request, 'login/main.html')
this is urls.py
from django.contrib import admin
from django.urls import path, include
from login.views import index, main
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', index),
path('main/', main),
path('accounts/', include('django.contrib.auth.urls')),
]
Login Page
You are not passing the form context for the login route. In your index function, you don't have any context, and you put the form in home_view function which is not the view function being called by the /login route.
form.save() not working my form.save for updating data isnt working when i try to update my post it shows the original unedited post it dosent save the updated version.i donnt know whats causing the error idk if its views or anything in template if anyone could help i will be very grateful please help.
here is the code:
views.py
from django.shortcuts import render
from django.shortcuts import HttpResponseRedirect
from .models import Post
from .forms import PostForm
def post_list(request):
posts = Post.objects.all()
context = {
'post_list': posts
}
return render(request, "posts/post_list.html", context)
def post_detail(request, post_id):
post = Post.objects.get(id=post_id)
context = {
'post': post
}
return render(request, "posts/post_detail.html", context)
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid():
form.save()
return HttpResponseRedirect('/posts')
context = {
"form": form,
"form_type": 'Create'
}
return render(request, "posts/post_create.html", context)
def post_update(request, post_id):
post = Post.objects.get(id=post_id)
form = PostForm(request.POST or None, instance=post)
if form.is_valid():
form.save()
return HttpResponseRedirect('/posts')
context = {
"form": form,
"form_type": 'Update'
}
return render(request, "posts/post_update.html", context)
def post_delete(request, post_id):
post = Post.objects.get(id=post_id)
post.delete()
return HttpResponseRedirect('/posts')
urls.py
from django.urls import path
from .views import post_list, post_detail, post_create, post_update, post_delete
urlpatterns = [
path('', post_list),
path('create/', post_create),
path('<post_id>/', post_detail),
path('<post_id>/update', post_update),
path('<post_id>/delete', post_delete),
]
post_update.html
<h1>welcome to post {{ form_type }}</h1>
<form method="POST" action=".">
{% csrf_token %}
<p>{{ form.as_p }}</p>
<button type="submit">{{ form_type }}</button>
</form>
action="." takes you from <post_id>/update to <post_id>/. You can fix this a few ways:
Change it to action="", which will submit from <post_id>/update to <post_id>/update.
Add a slash to the URL, i.e. path('<post_id>/update/', ...). Then action="." will submit from <post_id>/update/ to <post_id>/update/
Use the {% url %} tag instead of hardcoding the action. In your case there's a few changes you'd need to make, so I'll leave that as a challenge for you. The docs on reversing URLs should help.
When I try to delete a product on my django app, I get a 404 error stating:
Page not found (404)
Request Method: POST
Request URL: http://localhost:8000/product/1/delete/
Raised by: products.views.viewProduct
No Product matches the given query.
I'm confused as to why Django is routing the deletion request to viewProduct, since my urls.py clearly states that it should route to deleteProduct.
urls.py:
from django.urls import path
from . import views
from django.views.generic import TemplateView
urlpatterns = [
path('new/', views.NewProduct, name='NewProduct'),
path('product/<int:pk>/<str:slug>/', views.viewProduct, name='viewProduct'),
path('product/<int:pk>/delete/', views.deleteProduct, name='deleteProduct'),
]
Views:
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse
from .models import Product
from django.utils import timezone
from slugify import slugify
def viewProduct(request, pk, slug):
product = get_object_or_404(Product, pk = pk, slug = slug)
return render(request, 'viewProduct.html', {'product' : product})
def deleteProduct(request, pk):
if request.method == 'GET':
product = Product.objects.filter(pk = pk)
return redirect('viewProduct', pk = pk, slug = product.slug)
if request.method == 'POST':
product = get_object_or_404(Product, pk = pk)
if product.productAuthor == request.user:
product.delete()
return redirect('viewAll')
Deletion form:
{% if request.user == product.productAuthor %}
<form action="/product/{{ product.pk }}/delete/" method="post">
{% csrf_token %}
<input type="submit" name="pk" class="btn btn-link text-danger" value="delete product">
</form>
{% endif %}
If it helps you, I just recently changed the site to view posts by both ID and slug instead of just ID. Before I changed this, the deletion function worked perfectly.
Maybe it is the way you indent after deletion, try this
I cannot see your viewAll url handler where you want to redirect, you need to write a viewAll view where you list all your products
from django.urls import reverse
urlpatterns = [
path('',views.ViewAll, name='viewAll')
path('new/', views.NewProduct, name='NewProduct'),
path('product/<int:pk>/<str:slug>/', views.viewProduct, name='viewProduct'),
path('product/<int:pk>/delete/', views.deleteProduct, name='deleteProduct'),
]
def deleteProduct(request, pk):
if request.method == 'GET':
product = Product.objects.filter(pk = pk)
return redirect('viewProduct', pk = pk, slug = product.slug)
if request.method == 'POST':
product = get_object_or_404(Product, pk = pk)
if product.productAuthor == request.user:
product.delete()
return redirect(reverse('yourappname:viewAll'))
URL patterns are processed in order. "delete" is a perfectly valid value for a slug, so the view pattern is matched and its view called.
You could fix this by swapping the order of the URLs, so that "delete" is matched first.
views.py
name.html cannot be found
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import Get_name
# Create your views here.
def index(request):
if request.method == 'POST':
form = Get_name(request.POST)
if form.is_valid():
return HttpResponseRedirect('/THANKS/')
else:
form = Get_name()
return render(request,'name.html',{'from':form})
name.html:why python is not able to find my template? my template dir structure is test2/templates/test2/name.html
<form action="/username/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
forms.py
from django import forms
class Get_name(forms.Form):
user_name = forms.CharField(label='username',max_length='50')
test2/urls.py
from django.conf.urls import url
from .import views
urlpatterns=[
url(r'^$',views.index,name='index'),
]
test1/urls.py
from django.contrib import admin
from django.conf.urls import url , include
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test2/',include('test2.urls')),
]
I think this will solve the problem.
Modify your views such that.
def index(request):
if request.method == 'POST':
form = Get_name(request.POST)
if form.is_valid():
return HttpResponseRedirect('/THANKS/')
else:
form = Get_name()
return render(request,'test2/name.html',{'from':form})
prepend template name with test2 such that return render(request,'test2/name.html',{'from':form})
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