Django from doesn't get processed. HTTP 405 error raises - python

I am trying to process a post form, but I can't manage. I have prepared the form, gave the action link, set the method to post, but when I hit the submit button, nothing happens, not even an error page isn't shown by django despite my debug option is True.
Here is the form code in my template file:
<form method="post" action="{% url 'articles:stepprocess' 0 %}">
{% csrf_token %}
<p><label for="title">Title:</label>
<input name="title" id="title" type="text"/></p>
<p>
<label for="dif">Difficulty</label>
<select name="dif" id="dif">
{% if difficulties %}
{% for difficulty in difficulties %}
<option value="{{ difficulty.pk }}">{{ difficulty }}</option>
{% endfor %}
{% endif %}
</select>
</p>
<p><label for="article">Content:</label>
<textarea cols="37" rows="11" name="article" id="article"></textarea></p>
<p><input name="send" style="margin-left: 150px;" class="formbutton" value="Send"
type="submit"/></p>
</form>
My urls.py file:
from django.conf.urls import url
from .views import *
urlpatterns = [
url(r'^$', Index.as_view(), name="index"),
url(r'^new/(?P<step>[0-9]+)/$', NewArticle.as_view(), name="newarticle_continue"),
url(r'^new/', NewArticle.as_view(), name="newarticle"),
url(r'^new/process/(?P<step>[0-9]+)/$', FormManager.as_view(), name='stepprocess')
#url(r'^show/(?P<article>[0-9]+)/$'),
]
And lastly, my views.py file:
#required imports...
class FormManager(View):
def post(self, request, *args, **kwargs):
return HttpResponse(kwargs['step'])
When I hit the submit button, it gives me HTTP 405 error. I can see this error in python console but nothing shows in browser. Just blank white screen.
This was actually to test if view works properly. My final purpose is that I would like to access the post variables and redirect the page. However, HttpResponseRedirect also doesn't work. How can I fix this?

HTTP 405 error means "method not allowed"
In your case you are POSTing... the view looks like it should accept POST requests though.
The problem is your urls.py is wrong, the url you POSTed to is intercepted by the NewArticle view instead, which I guess only accepts GETs.
from django.conf.urls import url
from .views import *
urlpatterns = [
url(r'^$', Index.as_view(), name="index"),
url(r'^new/process/(?P<step>[0-9]+)/$', FormManager.as_view(), name='stepprocess')
url(r'^new/(?P<step>[0-9]+)/$', NewArticle.as_view(), name="newarticle_continue"),
url(r'^new/', NewArticle.as_view(), name="newarticle"),
#url(r'^show/(?P<article>[0-9]+)/$'),
]
Django looks at the urls in the urlconf in the order they are defined and will dispatch your request to the first one that matches.
Above I have modified the order, alternatively you could just add the $ to end of url:
url(r'^new/$', NewArticle.as_view(), name="newarticle"),
this will prevent it matching any new/* url paths.

Related

Django. CSRF token missing or incorrect

I have just recently started learning Django.
I have a problem with the password change page
403
Reason given for failure:
CSRF token missing or incorrect.
My users/urls.py
urlpatterns = [
path(
'logout/',
LogoutView.as_view(template_name='users/logged_out.html'),
name='logout'
),
path(
'login/',
LoginView.as_view(template_name='users/login.html'),
name='login'
),
path(
'password_change/',
PasswordChangeView.as_view(template_name='users/password_change_form.html'),
name='password_change_form'
),
path(
'password_change/done/',
PasswordChangeDoneView.as_view(template_name='users/password_change_done.html'),
name='password_change_done'
),
...,
]
And My Form in Template starts
<form method="post"
{% if action_url %}
action="{% url action_url %}"
{% endif %}
>
{% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="">
With this form, I get the error 403 and "CSRF token missing or incorrect."
Without this string everythink works
<input type="hidden" name="csrfmiddlewaretoken" value="">
everythink works.
1)Could you please explain me why? And what is it?
What is the best way to use csrf?
2) I also used to write like
<form method="post" action="{% url 'users:password_change_form' %}">
But founded this example using action_url.
What is action_url?
What way is better?
action is the attribute in the form tag. and "action_url" is the URL(a page) it goes to when you click on submit button. So you need to define that URL there. and the correct syntax in Django is :
<form action={% url 'process' %} method="POST">
So here process is name of that URL you define in urls.py file.
Something like this :
path('process/', views.process, name='process')
And in order to work you need to have that file in your app.
So in your case type the name of your URL you've defined in ulrs.py file in if condition.
Try to use only:
{% csrf_token %}
instead of
{% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="">
I'm afraid that the second line of code overwritten the csrf_token value.
'action' in the form specifies where to send the form-data when a form is submitted. In this case, after the form is submitted, it will go to 'users' app, url name 'password_change_form', then pass to the view associated with it.

How can I get values from a view in Django every time I access the home page

I currently have the following view created in Django:
#login_required
def retrieve_from_db(request):
some_ids = get_some_data()
context = {'some_ids': some_ids}
return render(request, 'index.html', context)
This is my urls.py:
from django.urls import path
from . import views
app_name = 'blabla'
urlpatterns = [
path('', views.another_view, name='index'),
path('', views.retrieve_from_db, name='index'),
...
...
...
]
And this is part of my index.html
<div>
<select name="myIdList" id="myIdList">
{% for some_id in some_ids %}
<option value="{{ some_id }}">{{ some_id }}</option>
{% endfor %}
</select>
</div>
I would like to know how can I get the results from the function retrieve_from_db(). What I want is that every time I access the home page, by default the selects are populated with the result of the view.
All I have found so far on StackOverflow have been answers using forms in which the user somehow has to perform some action to trigger the POST, is there any way to do all of this without the user having to press any buttons or perform an action? simply every time the page loads, get the results of the retrieve_from_db() function defined in the view.
You can use "GET" method which is not safe for passing sensitive data!
GET should send data while rendering page.
Your views.py function to retrieve data would look like this:
#login_required
def retrieve_from_db(request, some_id):
if request.method == "GET":
some_ids = request.GET.get('some_id')
context = {'some_ids': some_ids}
return render(request, 'index.html', context)
Your HTML would look like this:
<div>
<form action="/retrieve_from_db/{{some_id}}" method="GET">
<select name="myIdList" id="myIdList">
{% for some_id in some_ids %}
<option value="{{ some_id }}">{{ some_id }}</option>
{% endfor %}
</select>
</div>
Interesting part here is, how it will pass many 'some_id' objects as you generate them from for loop.
This solution maybe is not one of the most elegant ones, but should pass data without user interference.

Python Django - django-filters app - autogenerate searchfield based on model

Alright,
First time I'm asking a question over here, i did search for similar question but haven't found my answer yet..
I'm working on a simple delivery app with Django, it shows an overview of customers checkin in and out and some details on the delivery.
I have a view called "CheckInsListView" and "CheckOutListView" and i would like to filter these lists on a user given date, based on the django-filters app.
I tried following this link: https://simpleisbetterthancomplex.com/tutorial/2016/11/28/how-to-filter-querysets-dynamically.html
The problem now is, the searchform is not automatically created. It does show the submit button but the formfield isn't generated. It doesn't come up with any errors either.
Can somebody point out what I'm missing here?
Thanks in advance,
Kevin
#filters.py
from .models import Delivery
import django_filters
class DeliveryFilter(django_filters.FilterSet):
class Meta:
model = Delivery
fields = ['arrival_date']
Adding the view:
#views.py
"""
Create a search view to sort deliveries on date, django-filter app is used
"""
from django.shortcuts import render
from .models import Delivery
from .filters import DeliveryFilter
def search(request):
delivery_list = Delivery.objects.all()
delivery_filter = DeliveryFilter(request.GET, queryset=delivery_list)
return render(request, 'all_deliveries.html', {'filter': delivery_filter})
And urls
#urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^search/$', views.search, name='search'),
]
The form in html
{% extends "framework.html" %}
{% block content %}
<div class="form_search_header">
<form method="get">
{{ filter.form.as_p }}
<button type="submit">Search</button>
</form>
</div>
{% endblock %}
delivery_filter = DeliveryFilter(request.GET, queryset=delivery_list)
This is still going to return filtered records. There you need to write a for loop in the template, something like below:
<option value="" disabled selected>Select Delivery Item</option>
{% for d in filter %}
<option value="{{ d.id }}">{{ d.arrival_date }}</option>
{% endfor %}

Django - POST get options from select

I have a html form that looks like this.
{% url 'myapp:myapp_submit' as submit %}
<form name='main' method="POST" action={{submit}}>
{% csrf_token %}
<select class='form-control' size=10 id="test" name='test' multiple>
<option>Test</option>
</select>
<input type="submit"/>
</form>
and url.py
from . import views
app_name = 'myapp'
urlpatterns = [
url(r'^$', views.myapp, name='myapp'),
url(r'results/$', views.myapp_submit, name='myapp_submit')
]
and views.py
def myapp_submit(request):
print request.POST
The only thing I get back is
<QueryDict: {u'csrfmiddlewaretoken'...]}>
How do I get back the options held in the select tag? I would use the model/view form here but I'm doing some very crazy things with JS to constantly update the options available.
UPDATE
I have used:
request.POST.getlist('test')
But it will only return ['Test'] If I highlight it with my mouse. I simply want all the options under the select tag. ex.
<select class='form-control' size=10 id="test" name='test' multiple>
<option>Test1</option>
<option>Test2</option>
<option>Test3</option>
<option>Test4</option>
</select>
and
###Not sure if it's still getlist method
>>request.POST.getlist('test')
['Test','Test2','Test3','Test4']
Try to change your views.py:
def myapp_submit(request):
request.POST.getlist('test[]')
Because you say you're doing weird things with Js, you can first check the POST request from your browser and what parameters you send with it.
A month ago I solved this problem, you need to use name in your option tag
Example:
<select name="status">
<option name="status">
and see result in your view.

Django html redirects but doesn't load page

I am creating a Django web application and have come across the following problem.
I have created a new html page called teamList.html, which when clicking a href hyperlink on the main page, should redirect to teamList page. The url in the browser, which starts as http://127.0.0.1:8000/ changes to http://127.0.0.1:8000/teamList, but the page underneath doesn't change, but instead reloads the starting page.
The current application handles the login and main page in the html as such (default after login displays a graph):
#index.html
<body>
<img src="{% static "myApp/images/logo.gif" %}" alt="logo" />
{% if user.is_authenticated %}
<p>currently logged in as: {{ user.first_name }} {{ user.last_name }}
<p>logout
<p>Team List
<div id="radarChart">
{% block radarChartBlock %}{% endblock %}
</div>
{% else%}
<div id="login">
{% block login %}{% endblock %}
</div>
{% endif %}
</body>
My urls.py looks like this:
from django.conf.urls import patterns, url
from myApp import views
urlpatterns = patterns('',
#http://localhost:8000/
url(r'^$', views.index, name='index'),
url(r'^/teamList/$', views.renderTeamList, name='teamList')
)
EDIT: My views.py method for my teamList.html looks like this:
from django.shortcuts import render
from django.views.generic.base import TemplateView
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from myApp.models import FocusArea
from myApp.tables import TeamTable
from django_tables2 import RequestConfig
def renderTeamList(request):
table = TeamTable()
RequestConfig(request).configure(table)
return render(request, 'teamList.html', {'table': table})
In addition to the comments there is a problem with your urls.py. Your regular expression for teamList url starts with / and therefore will not match http://127.0.0.1:8000/teamList as Django replaces a leading slash by default. From the docs:
There’s no need to add a leading slash, because every URL has that. For example, it’s ^articles, not ^/articles.
For more details see Django docs here.

Categories