HttpResponseRedirect Reverse not working Django - python

I am trying to redirect my page after submitting a like button to the same page but I keep getting a
NoReverseMatch at /score/like/2
Here is the urls
urlpatterns = [
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('', PostListView.as_view(), name='score'),
path('<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('like/<int:pk>', LikeView, name='like_post'),
Here is the views
def LikeView(request, pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
post.likes.add(request.user)
return HttpResponseRedirect(reverse('post-detail', args=[str(pk)])) <-----Error highlighting here
here is the templates
<form action="{% url 'score:like_post' post.pk %}" method='POST'>
{% csrf_token %}
<button type='submit' name='post_id' class= "btn btn-primary btn-sm" value="{{post.id}}"> Like </button>
</form>
<strong>{{post.total_liked}} Likes </strong>

Given the template your urls.py specify an app_name. You need to use that as prefix in the name of the view.
Furthermore you can make use of redirect(…) [Django-doc] which calls reverse and wraps the result in a HttpResponseRedirect (so it removes some boilerplate):
from django.shortcuts import redirect
def LikeView(request, pk):
post = get_object_or_404(Post, id=request.POST.get('post_id'))
post.likes.add(request.user)
return redirect('score:post-detail', pk=pk)

Related

An issue with posting a reply in the Django website

I am following the tutorial on [Protecting Views][1] and I have trouble understanding the tutorial. When I click the the Reply Button, it does not take me to the link to reply to the topic, and displayed a # in the URL instead. I had to type in the URL to get to that point. And when I posted something, it didn't redirect, and the new topic that I replied to wasn't there. I don't know why this is happening.
Here's my forms.py file
from django import forms
from .models import Topic, Post
class NewTopicForm(forms.ModelForm):
message = forms.CharField(
widget=forms.Textarea(),
max_length=4000,
help_text='The max length of this field is 4000.'
)
class Meta:
model = Topic
fields = ['subject', 'message']
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['message', ]
and here's my urls.py file
from django.conf.urls import url
from django.contrib import admin
from django.contrib.auth import views as auth_views
from accounts import views as accounts_views
from boards import views
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^signup/$', accounts_views.signup, name='signup'),
url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
url(r'^logout/$', auth_views.LogoutView.as_view(), name='logout'),
url(r'^reset/$',
auth_views.PasswordResetView.as_view(
template_name='password_reset.html',
email_template_name='password_reset_email.html',
subject_template_name='password_reset_subject.txt'
),
name='password_reset'),
url(r'^reset/done/$',
auth_views.PasswordResetDoneView.as_view(template_name='password_reset_done.html'),
name='password_reset_done'),
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
auth_views.PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html'),
name='password_reset_confirm'),
url(r'^reset/complete/$',
auth_views.PasswordResetCompleteView.as_view(template_name='password_reset_complete.html'),
name='password_reset_complete'),
url(r'^settings/password/$', auth_views.PasswordChangeView.as_view(template_name='password_change.html'),
name='password_change'),
url(r'^settings/password/done/$', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'),
name='password_change_done'),
url(r'^boards/(?P<pk>\d+)/$', views.board_topics, name='board_topics'),
url(r'^boards/(?P<pk>\d+)/new/$', views.new_topic, name='new_topic'),
url(r'^boards/(?P<pk>\d+)/topics/(?P<topic_pk>\d+)/$', views.topic_posts, name='topic_posts'),
url(r'^boards/(?P<pk>\d+)/topics/(?P<topic_pk>\d+)/reply/$', views.reply_topic, name='reply_topic'),
url(r'^admin/', admin.site.urls),
]
And here is my views.py file
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, redirect, render
from .forms import NewTopicForm, PostForm
from .models import Board, Post, Topic
def home(request):
boards = Board.objects.all()
return render(request, 'home.html', {'boards': boards})
def board_topics(request, pk):
board = get_object_or_404(Board, pk=pk)
return render(request, 'topics.html', {'board': board})
#login_required
def new_topic(request, pk):
board = get_object_or_404(Board, pk=pk)
if request.method == 'POST':
form = NewTopicForm(request.POST)
if form.is_valid():
topic = form.save(commit=False)
topic.board = board
topic.starter = request.user
topic.save()
Post.objects.create(
message=form.cleaned_data.get('message'),
topic=topic,
created_by=request.user
)
return redirect('topic_posts', pk=pk, topic_pk=topic.pk)
else:
form = NewTopicForm()
return render(request, 'new_topic.html', {'board': board, 'form': form})
def topic_posts(request, pk, topic_pk):
topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
return render(request, 'topic_posts.html', {'topic': topic})
#login_required
def reply_topic(request, pk, topic_pk):
topic = get_object_or_404(Topic, board__pk=pk, pk=topic_pk)
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.topic = topic
post.created_by = request.user
post.save()
return redirect('topic_posts', pk=pk, topic_pk=topic_pk)
else:
form = PostForm()
return render(request, 'reply_topic.html', {'topic': topic, 'form': form})
and here's my templates/reply_topic file
{% extends 'base.html' %}
{% load static %}
{% block title %}Post a reply{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Boards</li>
<li class="breadcrumb-item">{{ topic.board.name }}</li>
<li class="breadcrumb-item">{{ topic.subject }}</li>
<li class="breadcrumb-item active">Post a reply</li>
{% endblock %}
{% block content %}
<form method="post" class="mb-4" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Post a reply</button>
</form>
{% for post in topic.posts.all %}
<div class="card mb-2">
<div class="card-body p-3">
<div class="row mb-3">
<div class="col-6">
<strong class="text-muted">{{ post.created_by.username }}</strong>
</div>
<div class="col-6 text-right">
<small class="text-muted">{{ post.created_at }}</small>
</div>
</div>
{{ post.message }}
</div>
</div>
{% endfor %}
{% endblock %}
I followed the tutorial exactly, but the reply worked when I typed in the URL, not when I clicked on the reply button. Is there an explanation for this, or am I missing something?

django: Take table name as input from user and show the content of the table from database

I am trying to implement form in django, where I will take input from user, e.g, its table name and then I want to show all the content on the webpage. So, far I tried below code.
views.py
from django.shortcuts import render
# Create your views here.
from django.shortcuts import HttpResponse
from .models import my_custom_sql
from django.core.exceptions import *
def index(request):
return render(request, 'forms_spy/form.html')
def search(request):
if request.method == 'POST':
search_id = request.POST.get('textfield', None)
try:
webpages_list = my_custom_sql.objects.get(name = search_id)
data_list = {'access_record':webpages_list}
return render(request,'forms_spy/index.html', context=data_list)
except my_custom_sql.DoesNotExist:
return HttpResponse("no such user")
else:
return render(request, 'forms_spy/form.html')
forms_spy/models.py
from django.db import models
# Create your models here.
def my_custom_sql(TABLE):
with connections["my_oracle"].cursor() as cursor:
cursor.execute("SELECT * FROM {};".format(TABLE))
row = cursor.fetchall()
return row
templates/forms_spy/form.html
<form method="POST" action="/search">
{% csrf_token %}
<input type="text" name="textfield">
<button type="submit">Upload text</button>
</form>
urls.py under project folder:
from django.contrib import admin
from django.urls import path
from django.conf.urls import url,include
from forms_spy.views import *
urlpatterns = [
# url(r'^$', views.index, name='index'),
#url(r'^', include('livefleet.urls', namespace='livefleet')),
path('admin/', admin.site.urls),
url(r'^search/', search),
url(r'^index/', index),
]
I referred to this link. When I entered the value getting below error.
RuntimeError at /search
You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/search/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
change in urls.py
from
url(r'^search/', search),
to
url(r'^search/', search, name='search'),
<form method="POST" action="{% url 'search' %}">
{% csrf_token %}
<input type="text" name="textfield">
<button type="submit">Upload text</button>
</form>
ur url is search/ , so u need to put the same in the form action
change urls to
path('search/', search)
slash character for dynamic route, example call in browser (http://domain/search) or (http://domain/search/) if you using both it's work.
templates
<form method="POST" action="/search/">
{% csrf_token %}
<input type="text" name="textfield">
<button type="submit">Upload text</button>
</form>

Django form submission & CSRF (403 Forbidden)

Upon providing valid data and submitting a form, I get the following: Forbidden (CSRF cookie not set.): /membership/success/. I have a {% csrf_token %} in my template and my settings.py middleware is configured for CSRF.
#urls.py
from django.contrib import admin
from django.urls import path, include
from membership import views as ms_views
membership_patterns = ([
path("", ms_views.RegistrationPage.as_view(), name="register"),
path("success/", ms_views.SuccessPage.as_view(), name="success")
], 'membership')
urlpatterns = [
path('admin/', admin.site.urls),
path('membership/', include(membership_patterns, namespace="new_members"))
]
# membership/views.py
from django.shortcuts import render
from django.template.loader import get_template
from django.views import View
from django.http import HttpResponse, HttpResponseRedirect
from membership.forms import RegisterForm
from django.urls import reverse
# Create your views here.
class RegistrationPage(View):
def get(self, request):
register_page = get_template('membership/signup.html')
register_form = RegisterForm()
return HttpResponse(register_page.render({'form' : register_form}))
def post(self, request):
submitted_form = RegisterForm(request.POST)
if submitted_form.is_valid():
return HttpResponseRedirect(reverse('membership:success'))
return HttpResponse(reverse('membership:register'))
class SuccessPage(View):
def get(self, request):
return HttpResponse("Success")
# signup.html
{% extends 'index.html' %}
{% block content %}
<form action="{% url 'membership:success' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
Once the form is submitted and valid, I'm expecting a 302 to occur. Like I said though I get 403 forbidden.
Since your success page has no logic, you can choose to exempt CSRF token for that.
Import the following module
from django.views.decorators.csrf import csrf_exempt
and put #csrf_exempt at the start of function
#csrf_exempt
def get(self, request):
return HttpResponse("Success")
Refer to https://docs.djangoproject.com/en/2.2/ref/csrf/
However, it is better to include {% csrf_token %} for each template you use to ensure consistent passing around of CSRF token

Django POST request redirects to empty url after submitting form

I have a login form with POST method and when I submit the login data, it goes straight to the empty url and doesn't execute the login method in views.py. Ideally, after I submit the form in www.url.com/login via submit button, it should return a HttpResponse but instead, it takes me to www.url.com/
I am new to Django, I'd appreciate it if you could look into it. Thanks!
home.html
<center><h1>Welcome to my website</h1>
<form method='POST'> {% csrf_token %}
{{ form }}
<button type='submit' class='btn btn-default'>Submit</button>
</form>
</center>
urls.py
from django.contrib import admin
from django.urls import path
from .views import home, login
urlpatterns = [
path('', home),
path('login/', login),
path('admin/', admin.site.urls),
]
forms.py
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(attrs={"class":"form-control", "placeholder":"Your username"}))
password = forms.CharField(widget=forms.PasswordInput(attrs={"class":"form-control", "placeholder":"Your password"}))
views.py
from django.contrib.auth import authenticate, login
from django.http import HttpResponse
from django.shortcuts import render
from .forms import LoginForm
def home(request):
context={
"form": "Test"
}
return render(request, "home.html", context)
def login(request):
login_form = LoginForm(request.POST or None)
context={
"form": login_form
}
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
#request.user.is_authenticated()
login(request, user)
return HttpResponse("You are now logged in")
else:
return HttpResponse('Error')
return render(request, "home.html", context)
First, you should set an attribute action in the form which set a url to send.
Second, a url value in action must be clear. It's not a matter of Django but HTML.
I'd like to recommend you to use absolute path. If you use relative path, a slash string would be added whenever you send a request.
<form action="/login/" method='POST'>
{% csrf_token %}
{{ form }}
<button type='submit' class='btn btn-default'>Submit</button>
</form>
This is because your form doesn't contain action, i.e. where should the POST call be made with the user credentials.
Try following change in home.html:
<center><h1>Welcome to my website</h1>
<form action="" method='POST'> {% csrf_token %}
{{ form }}
<button type='submit' class='btn btn-default'>Submit</button>
</form>
</center>
Following the answers before, it would be a good practice to use named patterns instead of fixed urls.
# urls
...
path('login/', login, name='login'),
...
# template
<form action="{% url 'login' %}" method='POST'>
So if you change for example
login/
for
accounts/login/
You don't have to change the template as well.
urlpatterns = [
re_path('^$', home_page),
re_path('^admin/', admin.site.urls),
re_path('^register/$', register_page, name='register'),
re_path('^login/$', login_page, name='login'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
I solved this by adding ^$to the beginning and end of the patterns.

My url template not work

I have a problem with my template tag url. The redirect not work when i click on button.
Django version => 1.9
Python version => 2.7
In my urls.py(main) i have:
from django.conf import settings
from django.conf.urls import include, url
from django.conf.urls.static import static
from django.contrib import admin
from memoryposts.views import home, profile, preregistration
urlpatterns = [
url(r'^$', home, name="home"),
url(r'^grappelli/', include('grappelli.urls')),
url(r'^admin/', admin.site.urls),
url(r'^memory/', include("memoryposts.urls", namespace="memory")),
url(r'^avatar/', include('avatar.urls')),
url(r'^accounts/', include('registration.backends.hmac.urls')),
url(r'^preregistration/', preregistration, name="preregistration"),
url(r'^profile/', profile, name="profile"),
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In my urls.py(apps) i have:
from django.conf.urls import url
from django.contrib import admin
from .views import (
memory_list,
memory_create,
memory_detail,
memory_update,
memory_delete,
)
urlpatterns = [
url(r'^$', memory_list, name='list'),
url(r'^create/$', memory_create, name='create'),
url(r'^(?P<slug>[-\w]+)/$', memory_detail, name='detail'),
url(r'^(?P<slug>[-\w]+)/edit/$', memory_update, name='update'),
url(r'^(?P<slug>[-\w]+)/delete/$', memory_delete, name='delete'),
]
In my views.py(apps) i have:
from django.contrib import messages
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post
from .forms import PostForm
def home(request):
return render(request, "base.html")
def profile(request):
return render(request, "profile.html")
def preregistration(request):
return render(request, "preregistration.html")
def memory_create(request):
form = PostForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
messages.success(request,"Succès !")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
return render(request, "memory_create.html", context)
def memory_detail(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
context = {
"title":instance.title,
"instance":instance,
}
return render(request, "memory_detail.html", context)
def memory_list(request):
queryset = Post.objects.all()
context = {
"object_list": queryset,
}
return render(request, "memory_list.html", context)
def memory_update(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
form = PostForm(request.POST or None, request.FILES or None, instance=instance)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
messages.success(request,"Mis à jour !")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"title":instance.title,
"instance":instance,
"form": form,
}
return render(request, "memory_create.html", context)
def memory_delete(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
instance.delete()
messages.success(request, "Supprimer !")
return redirect("posts:list")
In my template html i have:
<button type="button" class="btn btn-primary"><a id="back-profile" href="{% url 'memory:update' %}"> Update</a></button>
<button type="button" class="btn btn-primary"><a id="back-profile" href="{% url 'memory:delete' %}"> Delete</a></button>
The redirect not work with this template tag.
can you help me please :) ?
From doc here URL dispatcher
<button type="button" class="btn btn-primary"><a id="back-profile" href="{% url 'memory:update' %}"> Update</a></button>
<button type="button" class="btn btn-primary"><a id="back-profile" href="{% url 'memory:delete' %}"> Delete</a></button>
You should put what you 'slug' in your button, like this (if slug is 200)
<button type="button" class="btn btn-primary"><a id="back-profile" href="{% url 'memory:update' 200 %}"> Update</a></button>
Usually will look like this:
{% for slug in slug_list %}
<button type="button" class="btn btn-primary"><a id="back-profile" href="{% url 'memory:update' slug %}"> Update</a></button>
{% endfor %}

Categories

Resources