Stuck with urls when Saving Post data to the database using django - python

I am trying to save post data for a custom user registration form but I can't identify where I am going wrong. I am suspecting the problem is in mainapp/urls. I have done some research on the subject read the following
documentation,Question on StackOverflow,Question on StackOverflow and many others but I cannot find the problem.
template
{% extends 'base.html'%}
{% load staticfiles %}
{% block content%}
{% load bootstrap %}
<div class = "signup-box">
<h2>Sign up</h2>
<form class="form-horizontal" action="signup" method="post">
{% csrf_token %}
<!-- {{ form|bootstrap }} -->
{{ form.username.label }}
{{ form.username }}
{{ form.first_name.label }}
{{ form.first_name }}
{{ form.last_name.label }}
{{ form.last_name }}
{{ form.email.label }}
{{ form.email }}
{{ form.password1.label }}
{{ form.password1 }}
{{ form.password2.label }}
{{ form.password2 }}<br>
<input type="submit" value="Submit" />
</form>
</div>
{% endblock %}
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.home),
url(r'^login/$', views.login, name='login'),
url(r'^signup/$', views.signup, name='signup'),
]
Views.py
from django.shortcuts import render, redirect
from .forms import RegistrationForm
from .models import User
from django.contrib import messages
from django.http import HttpResponse
# Create your views here.
def register_page(request):
if request.method == "POST":
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse('<h1>The form is valid!<h1>')
else:
form = RegistrationForm(request.POST)
args = {'form':form}
return render(request, 'signup', args)
else:
form = RegistrationForm()
return render(request, 'signup.html', {'form': form})
I get the following error after submitting the form
The current path, register_page/register_page/signup, didn't match any of these.

The problem is the URL you are posting to. The action of your form is a relative path, "signup"; because it has no leading slash it will always be appended to the current path.
You could fix this by prepending a slash, but you should actually not do this; you should post to the same URL as you came from, so action=".".
Note, there are various other errors with your code, not least the fact that you unnecessarily re-instantiate the form if it fails validation, so you will never see any validation errors.

Related

django.contrib.auth.urls change redirect path

I am coding a basic login and register page app in Django/Python
Currently, after someone logs in, it redirects them back to the register page. I am trying to change the redirect path to "home/"
Please see the following code:
URLS.PY:
from django.contrib import admin
from django.urls import path , include
from accounts import views as v
from main import views as views
urlpatterns = [
path('admin/', admin.site.urls),
path('home/' , views.home , name = 'home'),
path('', v.register , name='register'),
path('' , include('django.contrib.auth.urls') , name = 'login'),
]
Views.py:
from django.shortcuts import render , redirect
from .forms import RegisterForm
# Create your views here.
def register(response):
if response.method == "POST":
form = UserCreationForm(response.POST)
if form.is_valid():
form.save()
return redirect("/home")
else:
form = RegisterForm()
return render(response, "registration/register.html", {"form":form})
Login.html
{% extends "main/base.html"%}
{% block title %}
Login here
{% endblock %}
{% load crispy_forms_tags %}
{% block content %}
<form class="form-group" method="post">
{% csrf_token %}
{{ form|crispy }}
<p>Don't have an account ? Create one </p>
<button type="submit" class="btn btn-success">Login</button>
</form>
{% endblock %}
Register.html
{% extends "main/base.html"%}
{% block title %}Create an Account{% endblock %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST" class="form-group">
{% csrf_token %}
{{ form|crispy }}
<p>Already have an account? Login here</p>
<button type="submit" class="btn btn-success">Register</button>
</form>
{% endblock %}
You can use this in settings.py file to redirect user after login :-
LOGIN_REDIRECT_URL = 'home/'

DJANGO not returning context in my html template

why this context not rendering in my html template:
return render(request, 'index.html',{'message_name':name})
This context will print user name after successful submit my contact form. here is my code:
views.py
#csrf_exempt
def home_view(request,*args,**kwargs):
name = None
if request.method == "POST":
contact_form = ContactForm(request.POST)
if contact_form.is_valid():
name = request.POST['name']
email = request.POST['email']
subject = request.POST['subject']
message = request.POST['message']
save_details = Contact(name=name,email=email,subject=subject,message=message)
save_details.save()
return HttpResponseRedirect("http://127.0.0.1:8000/")
return render(request, 'index.html',{'message_name':name})
else:
print("not submitted")
else:
contact_form = ContactForm()
return render(request, 'index.html',{'form':contact_form})
app urls.py
from django.urls import path
from pages import views
urlpatterns = [
path('', views.home_view, name="home"),
]
root urls.py
from django.contrib import admin
from django.urls import path,include
from pages import urls
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('pages.urls')),
]
index.html
<!--===== CONTACT =====-->
<section class="contact section" id="contact">
<h2 class="section-title">Contact</h2>
{% if message_name %}
<div class="centerTest">
<h1> Thanks {{ message_name }} for your message. We will get back to you very soon</h1>
</div>
{% else %}
<div class="contact__container bd-grid">
<form action="#contact" method = "POST" class="contact__form">
{% for error in form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
<label>Name:</label>
{{ form.errors.name }}
<input type="text" placeholder="Name" name="name" class="contact__input" {% if form.is_bound %}value="{{ form.name.value }} {% endif %}">
<label>Email:</label>
{{ form.errors.email }}
<input type="mail" placeholder="Email" name="email" class="contact__input" {% if form.is_bound %}value="{{ form.email.value }} {% endif %}">
<label>Subject:</label>
{{ form.errors.subject }}
<input type="text" placeholder="optional" name="subject" class="contact__input" {% if form.is_bound %}value="{{ form.subject.value }} {% endif %}">
<label>Message:</label>
{{ form.errors.message }}
<textarea name="message" placeholder="message" id="" cols="0" rows="10" class="contact__input" >{% if form.is_bound %}{{ form.message.value }} {% endif %}</textarea>
<input type="submit" value="Send" class="contact__button button">
{% endif %}
if I remove the HttpResponseRedirect then it showing context in my html template
But the problem is it resubmitting my from again and again on refresh. After adding HttpResponseRedirect it stop resubmitting the form but not printing the context.
You can't pass context directly in redirect or HttpResponseRedirect in django. You need to be use session method. Try this:
#csrf_exempt
def home_view(request,*args,**kwargs):
name = None
if request.method == "POST":
contact_form = ContactForm(request.POST)
if contact_form.is_valid():
name = request.POST['name']
email = request.POST['email']
subject = request.POST['subject']
message = request.POST['message']
save_details = Contact(name=name,email=email,subject=subject,message=message)
save_details.save()
request.session['name'] = name
return redirect(home_view)
else:
print("not submitted")
else:
contact_form = ContactForm()
return render(request, 'index.html',{'form':contact_form})
Pass this {{ request.session.name }} in your index.html for show your context.
As a basic Python concept (and probably any other programming language), you cannot have two return sentences, one above the other in a function as the first one will make the second one unreachable.
Example:
def say_hello(name, age):
return f"hello {name}"
return f"your age is {age}"
If you execute this function, you will only get "hello john doe" as the second return statement is never executed.
In your case, if you keep the return HttpResponseRedirect(), the return render() will never be executed, therefore you will never see the context.
If you want to redirect the user to a specific route you should do it conditionally in order to have the chance to execute one return or the other.

Register page couldn't register user

I have setup register page by Django. The URL of register input on IE, register page is ok, but I cliked 'register' button on page, no register form display.
enter image description here
users\urls.py
urlpatterns = [
# register page
re_path('^register/$', views.register, name='register'),
]
users\views.py
def register(request):
"""register new user"""
if request.method != 'POST':
# display blank register form
form = UserCreationForm()
else:
# deal filled form
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
# auto login, and redirect to home page
authenticated_user =authenticate(username=new_user.username,password=request.POST['password1'])
login(request, authenticated_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form': form}
return render(request, 'users/register.html', context)
register.html
{% extends "learning_logs/base.html" %}
{% block content %}
<form method="post" action="{% url 'users:register' %}">
{% csrf_token %}
{{ form.as_P }}
<button name="submit">register</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
These are three methods to render the form.
{{ form.as_table }} will render them as table cells wrapped in tags
{{ form.as_p }} will render them wrapped in tags
{{ form.as_ul }} will render them wrapped in li
You can manually render the form with HTML also but fields name should be the same as the registration form.

Reverse for 'edit_post' with arguments '('',)' not found. 1 pattern(s) tried: ['edit_post/(?P<post_id>\\d+)/$']

I am going through a Django tutorial and getting this error when trying to edit posts in my blog app. I use Django Version: 2.0.6 and Python Version: 3.6.5.
models.py
from django.db import models
class BlogPost(models.Model):
title = models.CharField(max_length=100)
text = models.TextField()
def __str__(self):
return self.title
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^new_post/', views.new_post, name='new_post'),
url(r'^edit_post/(?P<post_id>\d+)/$', views.edit_post, name='edit_post'),
]
A template that causes the error in line 3 - edit_post.html. The error message highlights {% url 'edit_post' post.id %}
{% block content %}
<form action="{% url 'edit_post' post.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">save changes</button>
</form>
{% endblock content %}
A template (index.html) with a link to edit_post.html
{% block content %}
<form action="{% url 'new_post' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Make a new post</button>
</form>
<ul>
{% for post in posts %}
<li>
{{ post.id }} - {{ post.title }}
<p>{{ post.text }}</p>
edit post
</li>
{% empty %}
<li>No posts have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}
views.py
def edit_post(request, post_id):
post = BlogPost.objects.get(id=post_id)
text = post.text
title = post.title
if request.method != 'POST':
form = BlogForm(instance=post)
else:
form = BlogForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('index'))
context = {'title': title, 'text': text, 'form': form}
return render(request, 'blog/edit_post.html', context)
forms.py
from django import forms
from .models import BlogPost
class BlogForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'text']
The problem
When I click edit post link on index page, I get the aforementioned error. Creating a new post using this approach works flawlessly but editing does not.
I am stuck with this problem and have no idea what is wrong.
What I have tried
I have tried replacing django.conf.urls.url with django.urls.path and the patterns correspondingly.
I have change a link to a button.
I have tried
I have read What is a NoReverseMatch error, and how do I fix it?
on StackOverflow and as many topics as I could find.
Any help is appreciated. Thank you in advance!
in your blog/edit_post.html you use post.id
<form action="{% url 'edit_post' post.id %}" method='post'>
...
</form>
but in views.py you don't pass post variable to context variable
def edit_post(request, post_id):
post = BlogPost.objects.get(id=post_id)
...
context = {
'title': title,
'text': text,
'form': form,
'post': post # here
}
return render(request, 'blog/edit_post.html', context)

Basic Django form response

I am new to Django and looking to build a quick form with a response.
I am trying to build a form which would ask the user to input his name when the user clicks submit the page should reload and just say "Hello .
urls.py
class Question1Form(forms.Form):
n = forms.CharField(max_length=100,
widget=forms.TextInput(
attrs={'placeholder': 'Number', 'class': 'form-control'}))
views.py
def home(request):
if request.method == 'POST':
form = Question1Form(request.POST)
if form.is_valid():
result = [Question1Form.ans()]
return HttpResponse(Question1Form.n)
else:
form = Question1Form()
return render(request, 'index.html', {'form': form})
index.html
<form action="" method="post" class="form">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="form-row form">
<div class="col-sm-4">
{{ form.n.errors }}
{{ form.n }}
</div>
<input class="btn btn-primary" type="submit" value="Submit" />
</div>
</form>
So how the code s
You should call instance field, not class field and get value from validated(cleaned) data (see documentation):
return HttpResponse(form.cleaned_data['n'])
If you want to reload the same template with n value:
return render(request, 'index.html', {'form': form, 'n': form.cleaned_data['n']})
and at the template add:
{% if form.is_valid %}
<p> Hello {{ n }} </p>
{% endif %}
if request.method == 'POST':
form = Question1Form(request.POST)
if form.is_valid():
result = form.save()
return render(request, 'index.html', {'created': True})
Then in your HTML you can say
{% if created %}
<p> Hello </p>
{% endif %}
edit I see now you have no action in your form.
So you need to point to that view in your URLS.py.
for example.
from myapp import views as app_views
from django.conf.urls import url
urlpatterns =[
url(r'^my_form/$', app_views.home, name='save_form'),
]
And then add the action to your form.
<form action="{% url 'save_form' %}" method="post" class="form">

Categories

Resources