Django HTML POST parameters causes NoReverseMatch - python

I have an HTML post with two drop down lists, I want to send selected Country in those lists to the search() method that's in views.py and then send me to the results view. Whenever I add government and location as parameters for the html POST action or add their value in the search regex, I try this I get a NoReverseMatch from my index page:
Reverse for 'search' with arguments '('', '')' and keyword arguments '{}' not found. 1 pattern(s) tried: ['search/(?P[A-Z]{3})/(?P[A-Z]{3})/']
and I don't what I'm doing wrong to cause this error. (See comments in code)
appname/views.py:
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from .models import Country, Embassy
from django.template import loader
from django.urls import reverse
def index(request):
country = Country.objects.filter()
template = loader.get_template('appname/index.html')
context = {'countries': country}
return render(request, 'appname/index.html', context)
def results(request, government, location):
return HttpResponse("Here are the Embassies sent by %s, located in %s." % (government, location))
def search(request):
countries = Country.objects.all()
form = request.POST
if request.method == 'POST':
try:
selected_government = get_object_or_404(pk=request.POST['government'])
except (KeyError, Country.DoesNotExist):
return render(request, 'appname/index.html', {
'error_message': "You didn't select a government.",
})
try:
selected_location = get_object_or_404(pk=request.POST['location'])
except (KeyError, Country.DoesNotExist):
return render(request, 'appname/index.html', {
'error_message': "You didn't select a location.",
})
else:
return HttpResponseRedirect(reverse('appname:results', args=(selected_government.code,selected_location.code,)))
appname/templates/appname/index.html:
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
# government and location in the form action causes a NoReverse Match
<form action="{% url 'appname:search' government location %}" method="POST">
{% csrf_token %}
<label>Find Embassies sent by</label>
<select name="government">
{% for entry in countries %}
<option value="{{ entry.code }}">{{ entry.name }}</option>
{% endfor %}
</select>
<label>that are located in</label>
<select name="location">
{% for entry in countries %}
<option value="{{ entry.code }}">{{ entry.name }}</option>
{% endfor %}
</select>
<input type="submit" value="Search" />
</form>
urls.py:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^', include('appname.urls')),
url(r'^appname/', include('appname.urls')),
url(r'^admin/', admin.site.urls),
]
appname/urls.py:
from django.conf.urls import url
from . import views
app_name = 'appname'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<embassy_id>[0-9]+)/$', views.embassy_info, name='embassy_info'),
url(r'^(?P<code>[A-Z]{3})/$', views.country_info, name='country_info'),
url(r'^find/(?P<government>[A-Z]{3})/(?P<location>[A-Z]{3})/$', views.results, name='results'),
# the government and location values in search regex also cause a NoReverse Match
url(r'^search/(?P<government>[A-Z]{3})/(?P<location>[A-Z]{3})/', views.search, name='search'),
]
appname/models.py:
from django.db import models
class Country(models.Model):
code = models.CharField(primary_key=True, max_length=3)
name = models.CharField(max_length=50, db_column="Name")
def __str__(self):
return self.name
class Meta:
verbose_name = 'Country'
verbose_name_plural = 'Countries'
class Embassy(models.Model):
government = models.ForeignKey(Country, on_delete=models.CASCADE, related_name="government")
location = models.ForeignKey(Country, on_delete=models.CASCADE, related_name="location")
name = models.CharField(max_length=200, db_column="Name")
street_address = models.CharField(max_length=200, db_column="Address")
city = models.CharField(max_length=50, db_column="City")
phone_number = models.IntegerField(default=-1, db_column="Phone Number")
fax_number = models.IntegerField(null=True, blank=True, db_column="Fax Number")
email_address = models.CharField(max_length=200, db_column="Email")
website = models.CharField(max_length=200, db_column="Link")
def __str__(self):
return self.name
class Meta:
verbose_name = 'Embassy'
verbose_name_plural = 'Embassies'

It doesn't work like that. The parameters to the url tag - like any template tag in fact - have to come from the context passed to the template at render time. But you're trying to use values dynamically from the form itself.
You should remove the parameters from the URL pattern altogether. You're not using them in the view anyway since you correctly get the values from request.POST.
url(r'^search/$', views.search, name='search'),
...
<form action="{% url 'search' %}" ...

You need to create a form with ModelChoiceField.
In forms.py
from django import forms
from models import Country
class SearchForm(forms.Form):
government = forms.ModelChoiceField(queryset=Country.objects.all(), to_field_name="code", label="Find Embassies sent by")
location = forms.ModelChoiceField(queryset=Country.objects.all(), to_field_name="code", label="that are located in")
In views.py
from forms import SearchForm
def index(request):
form = SearchForm()
context = {'form': form}
return render(request, 'appname/index.html', context)
def search(request):
form = SearchForm(request.POST or None)
if request.POST and form.is_valid():
govt = form.cleaned_data.get('government')
loc = form.cleaned_data.get('location')
return HttpResponseRedirect(reverse('appname:results', kwargs={"government": govt.code, "location": loc.code}))
else:
context = {'form': form}
return render(request, 'appname/index.html', context)
In appname/urls.py
add this url
url(r'^search/$', views.search, name='search'),
In index.html
<form method="post" action={% url 'appname:search' %}>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Search" />
</form>

Django URL resolver reverse takes keyword arguments as parameters
reverse('search', kwargs={'government':goverment.code, 'location':location.code})
Hope this helps

Related

ValueError: The view didn't return an HttpResponse object. It returned None instead

I have been getting the valueError where post_edit returns None instead of an HttpResponse object.
This is my views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, request
from django.urls import reverse
from markdown import Markdown
from django import forms
from . import util
md = Markdown()
class createPage(forms.Form):
title = forms.CharField(label="Title", widget=forms.TextInput(attrs={'cols': 60}))
description = forms.CharField(label="Description", widget=forms.Textarea(attrs={'cols': 120}))
def pages(request, name):
page_name = util.get_entry(name)
if page_name is None:
return render(request, "encyclopedia/invalidPage.html", {
"title": name.capitalize()
})
return render(request, "encyclopedia/wikiPages.html", {
"page": md.convert(page_name),
"title": name
})
def post_edit(request, name):
if request.method == "POST":
form = createPage(request.POST)
if form.is_valid():
description = request.POST.get('description')
title = form.cleaned_data["title"]
description = form.cleaned_data["description"]
util.save_entry(title, description)
return HttpResponseRedirect(reverse('pages', kwargs={'name': title }))
else:
description = {
'title': name,
'description':util.get_entry(name)
}
return render(request, "encyclopedia/edit.html", description)
My edit.html
{% extends "encyclopedia/layout.html" %}
{% block title %}
{{ title }} | Edit
{% endblock %}
{% block body %}
{{message}}
<form action="{% url 'post_edit' title %}" method="POST">
{% csrf_token %}
<table>
<tr>
<th><label for="title">Title:</label></th>
<td><input type="text" name="title" cols="60" required disabled value="{{title}}" id="title"></td>
</tr>
<tr>
<th><label for="description">Description:</label></th>
<td>
<textarea name="description" cols="120" rows="10" required id="id_content">{{ Description | linebreaksbr}}</textarea>
</td>
</tr>
</table>
<input type="submit" value="Edit">
</form>
{% endblock %}
My urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("search", views.search, name="search"),
path("wikiPLUS/new/", views.post_new, name="post_new"),
path('wikiPLUS/edit/<str:name>', views.post_edit, name='post_edit'),
path("<str:name>", views.pages, name="pages"),
]
I have been getting the error:
The view encyclopedia.views.post_edit didn't return an HttpResponse object. It returned None instead.
I am very new to Django. I hope I could provide relevant information for question and error.
Edit
I applied the following changes on post_edit function then it worked:
def post_edit(request, name):
if request.method == "POST":
form = createPage(request.POST)
description = request.POST.get('description')
util.save_entry(name, description)
return HttpResponseRedirect(reverse('pages', kwargs={'name': name }))
else:
form = createPage() # this will create empty form if it is a GET request
description = {
'title': name,
'description': util.get_entry(name)
}
return render(request, "encyclopedia/edit.html", description)
In post_edit function add:
else:
form = createPage() # this will create empty form if it is a GET request
description = {
'title': name,
'description':util.get_entry(name)
}
return render(request, "encyclopedia/edit.html", description)
Indentation of description(your context dictionary) and render should be at same as else.
For more info. like when this errors usually occurs, you may check these answers The view didn't return an HttpResponse object. It returned None instead

Search Form in Django with python

I'm trying to add a simple search form on my django website. When I hit the search button I'm redirected to the new_search.html page (as it should be) but the page doesn't show any result.
Thanks for your help!
The code is this:
I've got an homepage where I put the search form like this:
<form method="get" action="{% url 'new_search' %}">
{%csrf_token%}
<input type="text" name="srh" class= "form-control" placeholder="Search">
<button type="submit" name="submit">Search</button>
</form>
When a user search for something the result should be showed in the new_search.html page.
The function I wrote in the views.py is this:
def new_search(request):
if request.method == 'GET':
srch = request.GET.get('srh')
if srch:
sr = Info.objects.filter(Q(band__icontains=srch) | Q(disco__icontains=srch))
if sr:
return render(request, 'new_search.html', {'sr':sr})
else:
messages.error(request, 'no results')
else:
return render(request, 'new_search')
return render(request, 'new_search.html')
And the new_search.html page is this:
<div>
{% if sr %}
{% for k in sr %}
<table width="200px">
<tr><td>Band</td><td>{{k.band}}</td></tr>
<tr><td>Album</td><td>{{k.disco}}</td></tr>
</table>
{%endfor%}
{%endif%}
</div>
The model.py is this:
class Info(models.Model):
band = models.CharField(max_length=200, help_text="Write Here")
disco = models.CharField(max_length=200, help_text="Write Here")
etichetta_p = models.CharField(max_length=200, help_text="Write Here")
etichetta_d = models.CharField(max_length=200, help_text="Write Here")
matrice = models.CharField(max_length=200, help_text="Write Here")
anno = models.PositiveIntegerField(default=0)
cover = models.ImageField(upload_to='images/')
def __str__(self):
return self.band
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('search.urls')),
path('accounts/', include('django.contrib.auth.urls')),
app urls.py
urlpatterns = [
path('', homeView.as_view(), name='home'),
path('anno', views.anno, name='anno'),
path('band/', bandView.as_view(), name='band'),
path('album/', albumView.as_view(), name='album'),
path('add/create', views.AddInfo.as_view(), name='add_create'),
path('signup/', core_views.signup, name='signup'),
path('new_search/', new_searchView.as_view(), name='new_search'),
]
It looks to me like you should handle POST method in your class view, since you're using one, for example:
class new_searchView(TemplateView):
template_name = "new_search.html"
def post(self, request, *args, **kwargs):
print('FORM POSTED WITH {}'.format(request.POST['srh']))
return render(self.request, 'new_search.html')

NoReverseMatch for form using django-select2

I have two view section, one of them saves the fields into database and the other is to autocomplete a field. How can I use both of them in a html template?
First View:
def stock(request):
stocks_form=StocksForm(None)
if request.method == "POST":
stocks_form =StocksForm(data=request.POST)
if stocks_form.is_valid():
instance=stocks_form.save()
instance.user=request.user
instance.save()
messages.success(request,"Successful" ,extra_tags="savestock")
else:
messages.error(request, "Error!")
else:
stocks_form=StocksForm()
return render(request,'BallbearingSite/stock.html',{'stocks_form':stocks_form})
Second View:
class StocksAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated():
return Stocks.objects.none()
qs = Stocks.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
urls.py
url(r'^stock/$',views.stock,name='stock'),
url(r'^stock_autocomplete/$',views.StocksAutocomplete.as_view(create_field='name'),name='stock_autocomplete'),
Project urls.py:
urlpatterns = [
url(r'^$',views.index,name='index'),
url(r'^ajax_select/', include(ajax_select_urls)),
url(r'^admin/BallbearingSite/controlsite/$',views.sendemailview),
url(r'^admin/', include(admin.site.urls)),
url(r'^',include('BallbearingSite.urls', namespace='BallbearingSite')),
url(r'^logout/$',views.user_logout,name='logout'),
url(r'^login/$',views.user_login,name='login'),
url(r'^ckeditor/', include('ckeditor_uploader.urls')),
url('^', include('django.contrib.auth.urls')),
]
Template:
<form enctype="multipart/form-data" method="post" >
{% csrf_token %}
{{ stocks_form.as_p }}
<input id="savestocks" type="submit" name="" value="ثبت">
</form>
forms.py:
class StocksForm(forms.ModelForm):
class Meta():
model=Stocks
fields=('name','number','suffix','brand','comment','price')
widgets = {
'name': autocomplete.ModelSelect2(url='stock_autocomplete')
}
def clean_name(self):
return self.cleaned_data['comment'].upper()
It has this error:
NoReverseMatch at /stock/
Reverse for 'stock_autocomplete' with arguments '()' and keyword arguments'{}' not found. 0 pattern(s) tried: []
It highlighted these parts in error :
{{ stocks_form.as_p }}
and :
return render(request,'BallbearingSite/stock.html',{'stocks_form':stocks_form})
It looks like you might be missing the namespace from the url. If the stock_autocomplete url is in the BallbearingSite namespace, you would do:
'name': autocomplete.ModelSelect2(url='BallbearingSite:stock_autocomplete')

Django Form Not Posting to SQL

I have a page where an item from a list nested within my form can be favorited, it redirects back to the same page following what should be an update to the database, then it shows a star next to the item. While this should work fine my form doesn't change the DB at all. I am confident it is not the html rendering since when I manually change the field in the admin panel it renders fine. What is causing this to not post?
view.py:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from django.template import loader
from .models import Album, Song
# Create your views here.
def index(request):
all_albums = Album.objects.all()
template = loader.get_template('music/index.html')
context = {'all_albums' : all_albums,}
return render(request, 'music/index.html', context)
def detail(request, album_id):
album = get_object_or_404(Album, pk=album_id)
return render(request, 'music/detail.html', {'album' : album})
def favorite(request, album_id):
album = get_object_or_404(Album, pk=album_id)
print("favorite stuff happens here")
try:
selected_song = album.song_set.get(pk=int(request.POST['song']))
except (KeyError, Song.DoesNotExist):
return render(request, 'music/detail.html', {
'album' : album,
'error_message': 'Did not select a valid song'
})
else:
selected_song.favorite = True
selected_song.save()
return render(request, 'music/detail.html', {'album' : album})
<img src="{{album.album_logo}}">
<h1>{{album.album_title}} </h1>
<h2>{{album.artist}} </h2>
{% if error_message %}
<p><strong> {{error_message}} </strong></p>
{% endif %}
<form action="{% url 'music:favorite' album.id %}" method="post">
{% csrf_token %}
{% for song in album.song_set.all %}
<input type="radio" id="song{{forloop.counter}}" name="song" value="{{song.id}}" />
<label for="song{{forloop.counter}}">
<span>{{song.song_title}}
{% if song.is_favorite %}
<img src="http://i.imgur.com/b9b13Rd.png" />
{% endif %}
</span>
</label><br>
{% endfor %}
<input type="submit" value="Favorite">
</form>
model.py:
from django.db import models
# Create your models here.
class Album(models.Model):
artist = models.CharField(max_length=255)
album_title = models.CharField(max_length=255)
genre = models.CharField(max_length=255)
album_logo = models.CharField(max_length=255)
def __str__(self):
return self.album_title + ' -- ' + self.artist
class Song(models.Model):
# on delete this deletes this entry
album = models.ForeignKey(Album, on_delete=models.CASCADE)
file_type = models.CharField(max_length=4)
song_title = models.CharField(max_length=255)
is_favorite = models.BooleanField(default=False)
def __str__(self):
return self.song_title
urls.py:
from django.conf.urls import url
from . import views
app_name = 'music'
urlpatterns = [
# /music/
url(r'^$', views.index, name='index'),
# /music/<album_id>/
url(r'^(\d+)/$', views.detail, name='detail'),
# logic for favoriting adjusts model and redirects to same place
# /music/<album_id>/favorite
url(r'^(\d+)/favorite/$', views.favorite, name='favorite'),
]

Reverse for 'sending_message' not found. 'sending_message' is not a valid view function or pattern name

I have an app called com when I try to access viewing_user template which contains a form with action to another view get the error above
this is urls.py
app_name = 'com'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<name>[\w\-]+)/$',views.viewing_user, name='viewing_user'),
]
this is the views.py
from django.shortcuts import render
from django.contrib.auth.models import User
# Create your views here.
RECEIVER_ID = 0
def index(request):
return render(request, 'com/index.html',{})
def viewing_user(request, name):
#username = request.GET.get('username','')
try:
User_obj = User.objects.get(username = name)
RECEIVER_ID = User_obj.id
except User.DoesNotExist:
User_obj = None
return render(request, 'com/viewing_user.html',{'u':name,'obj':User_obj})
def sending_message(request):
form = MessageForm()
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid:
message = message_form.save(commit = False)
message.date = datetime.date.now()
message.from_user = user.id
message._to = RECEIVER_ID
message.save()
else:
print form.errors
return render(request, 'com/viewing_user.html', {'form':form})
this is the template vieweing_user.html which seems that has a problem in the action of the form
<html>
{% if obj == None %}
<h2>Sorry this user ({{u}}) DoesNotExist</h2>
{% else %}
<h3>Be honest, and Tellme what you want</h3>
<br>
<i>{{obj.username}}</i>
<form method="post" action="{%url 'com:sending_message' %}">
{%csrf_token%}
{% for hidden in form.hidden_fields%}
{{hidden}}
{%endfor%}
{% for visible in form.visible_fields%}
{{visible}}
{%endfor%}
<input type="submit" value='Tell'/>
</form>
{%endif%}
</html>
reverse tries to look for its parameter value in urlpatterns. You do not have any url pattern with name sending_message in com namespace.
You would want to create an url pattern with name sending_message
url(r'^(?Psomepattern)/$',views.sending_message, name='sending_message'),

Categories