Django Template Second Form Input Triggering Wrong View - django

Trying to have two forms on one page and have a user select a create input or load input. Should be pretty straight forward. Doesn't seem to work. Anytime I click select a person and click load, it evaluates the first URL for Create. Can someone please point out what I'm missing? I'm sure it's something simple.
Views:
def Create(request):
print('Create View')
def Load(request):
print('Load View')
URLs:
urlpatterns = [
path('', views.Index, name='index'),
path('person/', views.Create, name='Create'),
path('person/', views.Load, name='Load'),
Template:
{% block body_main %}
<form action={% url 'Create' %} method='POST'>
<h2>Name</h2>
{% csrf_token %}
{{ form1 }}
<input class="btn btn-success" name="form1btn" value="Submit" type="submit"/>
</form>
<br>
<form action={% url 'Load' %} method='POST'>
<h2>Select Existing Name</h2>
{% csrf_token %}
{{ form2 }}
<input class="btn btn-success" name="form2btn" value="Submit" type="submit"/>
<form>
{% endblock %}

Here is the problem (also mentioned in point 3 in Django URL docs:
path('person/', views.Create, name='Create'),
path('person/', views.Load, name='Load'),
Everytime django URL matcher gets here, it will usually hit Create first and return.
Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL, matching against path_info.
So it will always return the Create view.
To solve this problem I suggest creating 3 separate URLs that are more readable:
path('person/new', views.Create, name='Create'),
path('person/load', views.Load, name='Load'),

Related

Django - Add two names - Couldn't print results

I'm new to Django.
Trying to build an app that adds two names. Pretty Basic.
Built a page that collects the names but not printing the final result.
Here is my code:
urls.py - inside the app
urlpatterns = [
path('',views.home, name='home'),
path('add',views.addname,name='add')
]
views.py
from django.shortcuts import render
from django.http import HttpResponse
def home(request):
return render(request,'input.html')
def addname(request):
val1 = (request.POST['fname'])
val2 = (request.POST['lname'])
res = 'Hi' + val1 +val2
return render(request, 'resultprint.html',{'resultprint':res})
templates/input.html
{% block content %}
<h1>Hello!</h1>
<form action='addname' method='post'>
{% csrf_token %}
Enter 1st name : <input type='text' name='fname'><br>
Enter 2nd name : <input type='text' name='lname'><br>
<input type='submit'>
</form>
{%endblock%}
templates/resultprint.html
{% block content %}
Result: {{resultprint}}
{%endblock%}
Below are the screenshots:
Couldn't really find where is the mistake happening.
I added the templates and app in the Settings file.
You have to set the same url in your urls.py :
urlpatterns = [
path('', views.home, name='home'),
path('addname', views.addname, name='addname')
]
But you can use directly the name of the url in your html file like that :
{% block content %}
<h1>Hello!</h1>
<form action='{% url 'addname' %}' method='post'>
{% csrf_token %}
Enter 1st name : <input type='text' name='fname'><br>
Enter 2nd name : <input type='text' name='lname'><br>
<input type='submit'>
</form>
{%endblock%}

Reverse for 's_note' with arguments '()' and keyword arguments '{'note_t': 'note_1 opeth', 'user_name': 'opeth'}' not found. 0 pattern(s) tried: []

I have a link to note detail page (s_note) in the user page (username). So as long as I have no entries(notes) in the database for the user the user page renders fine, but as soon as there is a valid note the render fails with the above error and points to ln:6 of user.html.
my urls.py
from django.conf.urls import url
from notes.models import User, Note
from . import views
app_name = 'notes'
urlpatterns = [
url(r'^$', views.index, name='u_index'),
my url
url(r'^signup/$', views.signup, name='u_signup'),
url(r'^(?P<user_id>[\w\-]+)/$', views.user, name='username'),
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-]+)/$', views.note, name='s_note'),
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-]+)/$', views.note, name='s_note')
]
my views
def note(request, user_name, note_t):
nt = Note.objects.get(note_title=note_t)
return render (request, 'notes/detail.html', {'note': nt})
my users.html
<h2>Hi! {{ user.user_n }} Your notes are here.</h2>
{% if allnotes %}
<ul>
{% for note in allnotes %}
<li>{{ note.note_title }}</li>
{% endfor %}
</ul>
{% else %}
<p>You have no notes yet!</p>
{% endif %}
<form method="post" action"">
<table>
{% csrf_token %}
{{ NForm }}
</table>
<input type="submit" value="Create">
</form>
Your url doesn't match for underscores or spaces which your keyword currently contains.
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-]+)/$', views.note, name='s_note'),
should be
url(r'^(?P<user_name>[\w\-]+)/(?P<note_t>[\w\-\_\s]+)/$', views.note, name='s_note'),
although this isn't much of a solution since most spaces would turn into %20's, you should try to remove any spaces from your keywords and update your regex accordingly.
It was a namespacing problem as #Alasdair observed, it sorted with the edit -
'{% url 'notes:s_note'...%}'
in the template.

Django password_change view & PasswordChangeForm not working

I'm trying to get password_change view and PasswordChangeForm working, but I get an html where the form renders correctly but nothing happens when I fill the form and click enter and there isn't a "send" button for the form. I'm probably missing something simple here, but the docs doesn't seem very helpful.
So, this is the urls.py:
from django.contrib.auth.views import password_change
from sisacademico import views
url(r'^password_changed/$', views.password_changed, name='password_changed'),
url(r'^change_password/$', password_change,
{'template_name': 'sisacademico/change_password.html',
'post_change_redirect': sisacademico/password_changed/'}),
this is the html, change_password.html:
{% extends 'base_sisacademico.html' %}
{% block content %}
{{form.as_ul}}
{% endblock content %}
What I get is this form with no submit button that doesn't work:
The Django template form tags {{ form }} don't output a submit button. You're going to need to put that in your HTML. You'll have something like:
<form method="post">
{% csrf_token %}
{{ form.as_ul }}
<input type="submit" value="Submit" />
</form>
take a look at the form docs for other examples

Django NoReverseMatch url issue

I'm getting the error
"Reverse for 'recall' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'associate/recall/']"
When I try to submit a form. Here is my html:
<form action="{% url 'associate:recall' ordered_group %}" method="post">
{% csrf_token %}
<div>
<label for="recall">enter as many members of {{ ordered_group }} as you can recall </label>
<input type="text" id="recall" name="recall">
</div>
<div id="enter_button">
<input type="submit" value="enter" name="enter" />
</div>
<div id="done_button">
<input type="submit" value="done" name="done" />
</div>
</form>
"ordered_group" is a model object that is carried over from the 'learn' view:
urls.py:
urlpatterns = patterns('',
url(r'^learn/', "associate.views.learn", name='learn'),
url(r'^recall/', 'associate.views.recall', name='recall'),
url(r'^$', "associate.views.index", name='index'),
)
I am trying to use the ordered_group model object that is submitted in the learn view context to the html, back to the recall view as an argument. Can one do this? It makes sense to me, but what is the correct way of doing this?
views.py
def recall(request, ordered_group):
...
def learn(request):
...
ordered_group = ordered_groups[index]
return render(request, 'associate/learn.html', {'dataset':model, 'ordered_group':ordered_group})
I want to submit the form with
In you HTML, you are doing:
{% url 'associate:recall' ordered_group %}
Django expects that "recall" url is in "associate" namespace, because of the ":". But, you need to declare the namespace in urls.py, like:
url(r'^recall/', 'associate.views.recall', namespace='associate', name='recall')
If you don't want the namespace, just do:
{% url 'recall' ordered_group %}
And, about "ordered_group", you need to declare it in your url, like:
url(r'^recall/(?P<ordered_group>\w+)', 'associate.views.recall', namespace='associate', name='recall')
You are passing ordered_group in HTML, youare expecting this in views.py, but you are not expecting this on you URL.

Django: Next value is changing oddly in login page

I wanted to redirect the users in my app to their users page if they were already logged in and tried to go directly to "../login/". I've found this answer:
Django: Redirect logged in users from login page
It works fantastic until I decide to hit the "Registration" link I have below my login fields. I don't know why but when I hit it, I get redirect to the login page again but the only thing that changes is the url, for some reason it becomes "http://localhost:8000/users/login/?next=/users/register/", and it wont take me to my registration page.
Why the "next" variable changes if I've set it with another url in the login template like so:
{% extends "base.html" %}
{% block title %}User Login{% endblock %}
{% block head %}User Login{% endblock %}
{% block content %}
{% if form.errors %}
<p>User name or password is incorrect.</p>
{% endif %}
<form method="post" action="{% url login %}">
{% csrf_token %}
<p><label for="id_username">Username:</label>
{{ form.username }}</p>
<p><label for="id_password">Password:</label>
{{ form.password }}</p>
<input type="submit" value="Login" />
<input type="hidden" name="next" value="users/"/>
</form>
<li>Register</li>
{% endblock %}
I'm using django1.4 and python 2.7. My urls.py are:
For the whole application:
urlpatterns = patterns('',
url(r'^$', main_page, name="main_page"),
url(r'^users/',include('user_manager.urls')),
)
For the user_manager module:
urlpatterns = patterns('user_manager.views',
url(r'^$', users, name="user_page"),
url(r'^logout/$', user_logout, name="logout"),
url(r'^login/$', user_login, name="login"),
url(r'^(\w+)/$', user_page),
url(r'^register/$', register_page),
)
Do you have a #login_required decorator on that register_page view? If so, remove it
Ok I've found the problem. Django checks the urls regex in order so the "register" url was matching the "(\w+)/" intended to work for the users pages. So all I had to do is put that url at the end, the urls.py now looks like this:
urlpatterns = patterns('user_manager.views',
url(r'^$', users, name="user_page"),
url(r'^logout/$', user_logout, name="logout"),
url(r'^login/$', user_login, name="login"),
url(r'^register/$', register_page),
url(r'^(\w+)/$', user_page),
)
Nevertheless I still don't understand quite well why that mistaken match was changing the next value. I know that caused it but I don't know why...
Thank you very much for your time!