Search Form in Django with python - 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')

Related

Is it necessary to create new app for homepage models in Django?

I want to add a slider to my homepage. What is best way to do it? Should I create a new app for slider? Or can I create a class for slider in home(app)/models.py?
I tried to create Slider class in home/models.py. But I couldn't list on homepage.
home/views.py
def slider_index(request):
slides = Slider.objects.all()
return render(request, 'home.html', {'slides': slides})
def slider_detail(request, id):
slide = get_object_or_404(Slider, id=id)
context = {
'slide': slide,
}
return render(request, 'home.html', context)
home/models.py
class Slider(models.Model):
title = models.CharField(max_length=120, verbose_name='Başlık')
content = models.TextField(verbose_name='Açıklama')
publishing_date = models.DateTimeField(verbose_name='Yayınlanma Tarihi', auto_now_add=True)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('slide:detail', kwargs={'id': self.id})
# return "/slider/{}".format(self.id)
class Meta:
ordering = ['-publishing_date', '-id']
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', home_view),
path('slider/', slider_index, name='index'),
path('slider/<int:id>/', slider_detail, name='detail'),
path('post/', include('post.urls')),
]
and home.html:
{% for slide in slides %}
<!-- Slide #1 image -->
{% if slide.image %}
<img src="{{ slide.image.url }}" alt="{{ slide.content }}" title="{{ slide.title }}" />
{% endif %}
{% endfor %}
Nothing appears about slider. I'm newbie in django. I want to learn how to list slides in homepage.
Thanks in advance.

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'),

Django redirect doesn't append to previous pattern

urls.py
url(r'^reg/$', views.reg_view, name='reg'),
url(r'^logout/$', views.logout_view, name="logout"),
url(r'^search/$', views.search_redirect, name='search_redirect'),
url(r'^search/(?P<keyword>.*?)/page/(?P<page>[0-9]+)/$', views.SearchView.as_view(), name='search'),
url(r'^search/(?P<keyword>.*?)/$', views.SearchView.as_view(), name='search'),
url(r'^t/create/$', views.create_topic, name='create_topic'),
url(r'^notifications/$', views.NotificationView.as_view(), name='notifications'),
url(r'^avatar/$', views.upload_avatar, name="upload_avatar"),
Those are icluded in the main urls.py as this(the forum one):
url(r'^accounts/', include('userena.urls')),
url(r'^forum/', include(niji_urls, namespace="niji")),
url(r'^$', index, name="index"),
url(r'^despre-noi/$', despre_noi, name='desprenoi'),
url(r'^(mugshots/.*)$', serve, {'document_root': settings.MEDIA_ROOT, }),
url(r'^messages/', include('userena.contrib.umessages.urls')),
url(r'^magazin/', include(application.urls)),
# url(r'^magazin/', include('magazin.urls', namespace="magazin")),
url(r'^oferte/', include('oferte.urls', namespace="oferte")),
Form
<form class="navbar-form navbar-left" role="search" method="get" action="{% url 'niji:search_redirect' %}">
<div class="form-group">
<input type="text" id="keywordInput" name="keyword" class="form-control" placeholder="{% trans 'Search' %}">
</div>
<button type="submit" id="navSearchBtn" class="btn btn-default">{% trans 'Search' %}</button>
</form>
Views.py
class SearchView(ListView):
model = Topic
paginate_by = 30
template_name = 'niji/search.html'
context_object_name = 'topics'
def get_queryset(self):
keywords = self.kwargs.get('keyword')
query = get_query(keywords, ['title'])
return Topic.objects.visible().filter(
query
).select_related(
'user', 'node'
).prefetch_related(
'user__forum_avatar'
).order_by(
get_topic_ordering(self.request)
)
def get_context_data(self, **kwargs):
context = super(ListView, self).get_context_data(**kwargs)
context['title'] = context['panel_title'] = _('Search: ') + self.kwargs.get('keyword')
context['show_order'] = True
return context
def search_redirect(request):
if request.method == 'GET':
keyword = request.GET.get('keyword')
return HttpResponseRedirect(reverse('niji:search', kwargs={'keyword': keyword}))
else:
return HttpResponseForbidden('Post you cannot')
When the user uses the form to submit a search query, the url becomes example.com/search/... instead of example.com/forum/search/.. . If I manually enter the url latter, it works perfectly, so I assume it has to be some how related to the form? Or the search_redirect function?
Apparently, it had something to do with the button. Specifically the id I think. I don't know exactly what.. but removing it made it work

Django HTML POST parameters causes NoReverseMatch

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

Categories