How to display search results(django+haystack+elasticsearch) on the SAME page? - python

I included haystack+elasticsearch into my django project folowing by official haystack docs. Searching is working good, but results are displaying in separate page (search.html).I need show searching results on the same page I place searching query from.
I include search template into my base.html like this: {% include 'search/search.html' %}
My templates are in different dirs:templates/students/base.html and templates/search/search.html. As far I understand haystack uses its own /search/search.html for displaying search results. Which way can I change that behavior, how to display results on the same page? Please help!
urls.py:
from django.conf.urls import patterns, include, url
from django.contrib import admin
from students.views.students import StudentUpdateView
from students.views.students import StudentDeleteView
from students.views.students import StudentAddView
from students.views.groups import GroupDeleteView
from students.views.journal import JournalView
urlpatterns = patterns('',
#haystack search url
(r'^search/', include('haystack.urls')),
# main page url
url(r'^$', 'students.views.students.students_list', name ='home'),
search.html:
<form method="get" action="">
<table>
{{ form.as_table }}
<tr>
<td> </td>
<td>
<input type="text" name="q">
<button type="submit">Search</button>
</td>
</tr>
</table>
{% for student in page.object_list %}
<p><span style= "color:blue">Student:</
span> {{ student.object.first_name }} {{student.object.last_name }}</p>
<p>Ticket: {{ student.object.ticket }}</p>
<p>Group: {{ student.object.student_group }}</p>
{% empty %}
<p>No results found.</p>
{% endfor %}
seach_indexes.py:
from haystack import indexes
from students.models.students import Student
class StudentIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
last_name = indexes.CharField(model_attr='last_name')
def get_model(self):
return Student
def index_queryset(self, using=None):
return self.get_model().objects.all()

You can create a custom view and use that in your templates:
class CustomSearchView(SearchView):
template_name='/path/to/template.html'
and in your urls.py:
urlpatterns = patterns('',
url(r'^custom_search$', CustomSearchView.as_view(), name='custom_search'),
)
and in your templates, just call this view in your form:
<form method="get" action="{% url 'search:custom_search' %}">

Related

I keep getting : Reverse for 'delete_entry' with arguments '('',)' not found. 1 pattern(s) tried: ['deleteentry/(?P<input_id>[^/]+)/\\Z']

I am a begginer and tried to look up solutions from other threads to no avail,
Here is my views.py :
#login_required(login_url='/login')
def delete_entry(request, input_id):
input=Diary.objects.get(pk=input_id)
input.delete()
return redirect('home')
Here is my urls.py :
urlpatterns = [
path('', views.welcome, name='welcome'),
path('home', views.home, name='home'),
path('MyEntries/', views.MyEntries, name='entries'),
path('deleteentry/<input_id>/', views.delete_entry, name='delete_entry'),
]
Here is my html code :
<p>Hello, {{user.username}} !</p>
{% for article in articles %}
<p> {{ article.title}}<br>
{{ article.description }} <br>
{{ article.date }}
<div class="card-footer text-muted">
</p>
Delete
</div>
{% endfor %}
{% endblock %}
As the error says, this is because input.id resolves to the empty string, so likely input does not exists, or it has no id.
Likely you should work with article.id, or perhaps even more robust, use article.pk. If you delete items, you need to make a DELETE or POST request, so you can not work with a link, you use a mini-form, so:
<form action="post" method="{% url 'delete_entry' article.pk %}">
{% csrf_token %}
<button type="submit" class="delete">Delete</button>
</form>
The view can be further improved by using get_object_or_404, and restrict the view to only POST and DELETE requests:
from django.shortcuts import get_object_or_404
from django.views.decorators.http import require_http_methods
#login_required(login_url='/login')
#require_http_methods(["DELETE", "POST"])
def delete_entry(request, input_id):
input = get_object_or_404(Diary, pk=input_id)
input.delete()
return redirect('home')

NoReverseMatch at / Reverse for 'course_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['course/(?P<slug>[-a-zA-Z0-9_]+)/$']

I am trying to make a site that has a learning area so that instructors can upload courses for users to look at. i am trying to add a url to the home page to link to te course overview page and I keep getting a NoReverseMatch error when i try to add the url.
Here is the urls.py file
from django.urls import path
from . import views
urlpatterns = [
path('content/order/', views.ContentOrderView.as_view(), name='content_order'),
path('subject/<slug:subject>/', views.CourseListView.as_view(), name='course_list_subject'),
path('<slug:slug>/', views.CourseDetailView.as_view(), name='course_detail'),
]
views.py
class CourseDetailView(DetailView):
model = models.Course
template_name = 'courses/course/detail.html'
class CourseListView(TemplateResponseMixin, View):
model = models.Course
template_name = 'courses/course/list.html'
def get(self, request, subject=None):
subjects = models.Subject.objects.annotate(total_courses=Count('courses'))
courses = models.Course.objects.annotate(total_modules=Count('modules'))
if subject:
subject = get_object_or_404(models.Subject, slug=subject)
courses = courses.filter(subject=subject)
return self.render_to_response({'subjects': subjects, 'subject': subject, 'courses': courses})
template
<div class="module">
{% for course in courses %}
{% with subject=course.subject %}
<h3>
<a href="{% url 'course_detail' course.slug %}">
{{ course.title }}
</a>
</h3>
<p>
<a href="{% url 'course_list_subject' subject.slug %}">{{
subject }}</a>.
{{ course.total_modules }} modules.
Instructor: {{ course.owner.get_full_name }}
</p>
{% endwith %}
{% endfor %}

Django let User Update TextField value on Site via forms?

I hope someone can give me a little help on how to do the following with Django (excuse me if I don't explain everything correct, still new to Django and don't know about a lot of things) :
I have a table of Movies, those Movies have a "Description" Datafield, where when they click on it a form opens up with the current description of the movie. If they double click on this description they are allowed to change it and then save the value. I've made a small gif to visualize the idea:
At least thats the basic Idea behind this, so far I've managed to make most of the things run, but sadly not the Django part where the "new" data from the user is send to the Databank and replaces the old data of the Description.
So could someone explain to me how I can make that work? I know that I'd probably have to write a function to my views.py and then create a new url pattern, but I just can't figure out how exactly. So any help is welcome! Below is my code (I hope I've included every file you guys need):
views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import generic
from django.views.generic.list import ListView
from .models import *
class AllMovies(generic.ListView):
model = Movie
template_name = "consilium/index.html"
context_object_name = "latest_movie_list"
class MovieDetails(generic.DetailView):
model = Movie
template_name = "consilium/detail.html"
urls.py
from django.conf.urls import url
from . import views
from .models import *
from django.views.generic.list import ListView
app_name = "consilium"
urlpatterns = [
url(r'^$', views.AllMovies.as_view(), name="index"),
url(r'^(?P<slug>[\w_0-9]+)/$', views.MovieDetails.as_view(), name='detail'),
]
models.py
from django.db import models
from decimal import Decimal
from django import forms
from django.contrib import admin
class Movie(models.Model):
// removed the other models for better overview
description = models.TextField('Movie Description')
def __str__(self):
return self.title
index.html
{% extends "consilium/base.html" %}
{% block body %}
<table class="table">
<thead>
<tr>
<th></th>
<th colspan="2">My Movielist</th>
<th>
</tr>
<tr>
<th></th>
<th>TITLE</th>
<th>GENRE</th>
<th>RELEASE DATE</th>
<th>DIRECTOR</th>
<th>DESCRIPTION</th>
<th>RUNTIME</th>
<th>STATUS</th>
<th>IMDB</th>
</tr>
</thead>
<tbody>
{% if latest_movie_list %}
{% for movie in latest_movie_list %}
<tr>
<td></td>
<td>
<a href="{% url 'consilium:detail' movie.slug %}" data-toggle="popover" data-placement="left" data-content='<img class="title-image" src="{{movie.image.url}}"/>'>{{ movie.title }}</a>
</td>
<td>{{ movie.get_genre_display}}</td>
<td>{{ movie.date}}</td>
<td>{{ movie.director}}</td>
<td id="icn-change" data-toggle="collapse" data-target=".demo{{ forloop.counter }}">
Description <i class="fa fa-caret-right"></i>
</td>
<td>{{ movie.runtime}} min</td>
<td>{{ movie.get_status_display}}</td>
<td>{{ movie.imdb}}</td>
</tr>
<tr>
<td></td>
<td class="hiddenRow" colspan="8">
<div class="container collapse demo{{ forloop.counter }}">
<div class="row justify-content-center">
<div class="col">
<form method="post" id="usrform">{% csrf_token %}
<textarea id="text" class ="form-control" readonly="true" onkeydown="expandtext(this)" ondblclick="this.readOnly='';">{{movie.description}}</textarea>
</form>
</div>
</div>
<div class="row justify-content-center">
<div class="col align-self-start">Double Click to Edit</div>
<div class="col align-self-end">
<input type="submit" id="set" class="pull-right"/>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>No Movies are available.</td>
</tr>
{% endif %}
</tbody>
</table>
{% endblock %}
script.js
// removed all other code for overview
// replace description text with user input
$('#set').click(function() {
var test = $('#text').val();
localStorage.setItem("test", test);
});
$('#text').text(localStorage.getItem("test"));
I hope I didn't miss anything, thanks for everyone who can help me!
I worked on a similar project, and here is what I did.
from django.forms.models import model_to_dict
#login_required
def edit_profile(request):
profile, created = ClientProfile.objects.get_or_create(user_id=request.user.id)
if request.method == 'POST':
form = ProfileSubmissionForm(request.POST, instance=profile)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('jobs:list'))
else:
profile_dict = model_to_dict(profile)
form = ProfileSubmissionForm(profile_dict)
return render(request, 'jobs/profile.html', {'form': form})
Essentially, the model_to_dict renders the values stored in the database in the form. The instance=profile makes sure I'm updating the form and not creating a new object.
Figured it out thanks to the great help of the pythondev slack community!
views.py: getting the description field of my Movie Model
class MovieUpdateForm(forms.ModelForm):
class Meta:
model = Movie
fields = ['description']
reverse_lazy is important, so that when I click on my button it won't redirect me to consilium(my appname)/2/update and stays on the index site where I have my table
class MovieUpdateView(UpdateView):
model = Movie
form_class = MovieUpdateForm
success_url = reverse_lazy('consilium:index')
urls.py:
url(r'^(?P<pk>[0-9]+)/update/$', views.MovieUpdateView.as_view(), name='movie_update'),
here it was important to put this before my slug url pattern I had in my urls.py, otherwise it didn't work:
url(r'^(?P<slug>[\w_0-9]+)/$', views.MovieDetails.as_view(), name='detail'),
My form in my html: using pk=movie.pk so it will grab the correct movie and giving my textarea the name of "description" so my method knows where the data is coming from
<form action="{% url 'consilium:movie_update' pk=movie.pk %}" method="post" id="usrform">{% csrf_token %}
<textarea id="text" class ="form-control" name="description" readonly="true" onkeydown="expandtext(this)" ondblclick="this.readOnly='';">{{movie.description}}</textarea>
<input type="submit" id="set" class="pull-right"/>
</form>

How to get the correct URL for an image in Django

Hello I'm new to Django and I am trying to build a simple e-commerce application. In this app I want a user to upload a photo of an item which they want to sell. I want to display all the items in the home page, when you hit on the item name it redirects to the item details page. User can add a new item with the following fields title, item image, and a description. I want to show a thumbnail of the uploaded image in the home page near the title and the original image in the item details page, but when I try to do this the image is not appearing in the details page. Here is my code:
models.py
from __future__ import unicode_literals
from django.db import models
from django.utils import timezone
from PIL import Image
class Item(models.Model):
posted_user = models.ForeignKey('auth.User')
item_name = models.CharField(max_length=200)
item_image = models.ImageField(upload_to='img')
item_discription = models.TextField()
posted_date = models.DateTimeField(
default=timezone.now)
forms.py
from django import forms
from .models import Item
import re
from django.contrib.auth.models import User
class SellItemAddForm(forms.ModelForm):
class Meta:
model = Item
fields = ('item_name', 'item_discription', 'item_image')
urls.py
from django.conf.urls import url
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^$', views.item_list, name='item_list'),
url(r'^item/(?P<pk>\d+)/$', views.item_detail, name='item_detail'),
url(r'^item/new/$',views.item_new, name='item_new'),
url(r'^item/(?P<pk>\d+)/edit$', views.item_edit, name='item_edit'),
url(r'^item/(?P<pk>\d+)/remove/$', views.item_remove, name='item_remove'),
]
if settings.DEBUG:
urlpatterns = urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
views.py
from django.shortcuts import render, get_object_or_404
from .models import Item
from django.utils import timezone
from .forms import SellItemAddForm
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
def item_list(request):
items = Item.objects.filter(posted_date__lte=timezone.now())
return render(request, 'sbApp/item_list.html',{'items': items})
def item_detail(request, pk):
item = get_object_or_404(Item, pk=pk)
return render(request, 'sbApp/item_detail.html', {'item': item})
def item_remove(request, pk):
item = get_object_or_404(Item, pk=pk)
item.delete()
return redirect('item_list')
#login_required
def item_new(request):
if request.method == "POST":
form = SellItemAddForm(request.POST)
if form.is_valid():
item = form.save(commit=False)
item.posted_user = request.user
item.posted_date = timezone.now()
item.save()
return redirect('item_detail', pk=item.pk)
else:
form = SellItemAddForm()
return render(request, 'sbApp/new_item.html', {'form': form})
#login_required
def item_edit(request, pk):
item = get_object_or_404(Item, pk=pk)
if request.method == "POST":
form = SellItemAddForm(request.POST, instance=item)
if form.is_valid():
item = form.save(commit=False)
item.posted_user = request.user
item.posted_date= timezone.now()
item.save()
return redirect('item_detail', pk=item.pk)
else:
form = SellItemAddForm(instance=item)
return render(request, 'sbApp/item_edit.html', {'form': form})
item_detail.html
{% extends 'sbApp/base.html' %}
{% block content %}
<div class="item">
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'item_remove' pk=item.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<a class="btn btn-default" href="{% url 'item_edit' pk=item.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
{% endif %}
<h1>{{ item.item_name }}</h1>
{% if item.posted_date %}
<div class="date">
<p>posted on {{ item.posted_date }}</p>
</div>
{% endif %}
<div class="user_name">
<p>by {{item.posted_user}}</p>
</div>
<img src="{{ MEDIA_URL }}{{ item.item_image.url }}" alt="img">
<p>{{ item.item_discription|linebreaksbr }}</p>
</div>
{% endblock %}
item_list.html
{% extends 'sbApp/base.html' %}
{% block content %}
{% for item in items %}
<div class="item">
<h1>{{ item.item_name }} </h1>
<div class="date">
<p>posted on: {{ item.posted_date }}</p>
</div>
<p>{{ item.discription }}</p>
<img src="{{ MEDIA_URL }}{{ item.item_image.url }}" alt="img">
</div>
{% endfor %}
{% endblock %}
In your browser, look at the source code for the template where the img tag is, and let us know what is the value of the src attribute? My only guess is you are missing a / in there somewhere in the template {{ MEDIA_URL }}{{ item.item_image.url }}. Assuming the image exists and the MEDIA_URL constant is defined somewhere.
edit:
<img src="/{{ MEDIA_URL }}{{ item.item_image.url }}" alt="img">
^
it sounds like you have formed a relative URL, so one fix would be to make it an absolute URL by adding a / as shown above.
{{ MEDIA_URL }} you can checkout at template what the output of it, before combined with {{ item.item_image.url }}

Django Model form don't update database records

I am new in django and I want to create a form to update some database entries.
this is a simple form where I have a simple input text where I write the id of the record that I want to update:
main.html
<form method='post' action='/config/{{ idprov }}' >
<input type="text" class="form-control" name="idprov" id="idprov" value ="{{ idprov }}" />
<input class="btn btn-danger" type="submit" value="Config">
</form>
forms.py
from django import forms
from .models import Proveedor, Estado, Config
class ConfigForm(forms.ModelForm):
class Meta:
model = Config
this is my views.py:
def configView(request,idprov):
prov = Config.objects.get(idproveedor=idprov)
if request.method == 'POST':
form = ConfigForm(request.POST or None, instance=prov)
if form.is_valid():
form.save(commit=false)
return HttpResponseRedirect('/monitor/')
else:
form = ConfigForm( instance=prov)
return render_to_response('config.html',
{'form':form})
my template config.html:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-4">
<form method='POST' action='' >
<div class="form-group">{% csrf_token %}
{{ form.as_p }}
</div>
<button type='submit' class="btn btn-primary">Grabar</button>
</form>
</div>
</div>
</div>
{% endblock %}
my urls.py:
from django.conf.urls import patterns, include, url
from prov.views import home
from prov.views import proveedores
from prov.views import estado
from prov.views import monitorViewV2
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'prov.views.home', name='home'),
url(r'^proveedores/$', 'prov.views.proveedores', name='proveedor'),
url(r'^estado/$', 'prov.views.estado', name='estado'),
url(r'^monitor/$', 'prov.views.monitorView', name='monitor'),
url(r'^monitorv/$', 'prov.views.monitorViewV2', name='monitorv2'),
url(r'^config/(?P<idprov>\d+)/$', 'prov.views.configView',name='config'),
url(r'^admin/', include(admin.site.urls)),
)
But I receive the error Page not found.
I try to follow other snippets and always raise different errors.
I think the error is in the urls.py and in the way I pass the argument from the main.html.
Any advice or snippet will be very appreciated
Thanks in advance
First you have a form.save(commit=false) in your view without saving it later, thats mean the data is never saved into the model.
Second in your template config.html the form action is empty <form method='POST' action=''> change for <form method='POST' action='.'>
I hope that help to you.

Categories

Resources