#python #django #search #solr #django-haystack
Вопрос:
Я внедряю «функцию поиска» в свой блог django, используя Solr и Haystack. В «http://127.0.0.1:8000/blog/search/», в нем говорится, что ошибка типа в /блоге/поиске/ post_detail() отсутствуют 3 обязательных позиционных аргумента: «год», «месяц» и «день» Также в «http://localhost:8000/blog/search», в нем говорится, что ошибка ValueError в /blog/поиск в представлении blog.views.post_search не вернул объект HttpResponse. Вместо этого он ничего не вернул.
- blog/forms.py
from django import forms
class SearchForm(forms.Form):
query = forms.CharField()
- blog/search_indexes.py
from haystack import indexes
from .models import Post
class PostIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
publish = indexes.DateTimeField(model_attr='publish')
def get_model(self):
return Post
def index_queryset(self, using=None):
return self.get_model().published.all()
- blog/urls.py
from blog.feeds import LatestPostsFeed
from django.conf.urls import url
from django.urls import include, path
from . import views
app_name = 'blog'
urlpatterns = [
path('search', views.post_search, name='post_search'),
]
- blog/views.py
from .forms import SearchForm
from haystack.query import SearchQuerySet
def post_search(request):
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
return render(request, 'blog/post/search.html', {'form': form, 'cd': cd, 'results': results, 'total_results': total_results})
- blog/templates/blog/post/search.html
{% extends "blog/base.html" %}
{% block title %}Search{% endblock %}
{% block content %}
{% if "query" in request.GET %}
<h1>Posts containing "{{ cd.query }}"</h1>
<h3>Found {{ total_results }} result{{ total_results|pluralize}}</h3>
{% for result in results %}
{% with post=result.object %}
<h4><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h4>
{{ post.body|truncatewords:5 }}
{% endwith %}
{% empty %}
<p>There are no results for your query.</p>
{% endfor %}
<p><a href="{% url 'blog:post_search' %}">Search again</a></p>
{% else %}
<h1>Search for posts</h1>
<form action="." method="get">
{{ form.as_p }}
<input type="submit" value="Search">
</form>
{% endif %}
{% endblock %}
- blog/templates/search/indexes/blog/post_text.txt
{{ object.title }}
{{ object.tags.all|join:", " }}
{{ object.body }}
Edit 1
- blog/urls.py
from blog.feeds import LatestPostsFeed
from django.conf.urls import url
from django.urls import include, path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.post_list, name='post_list'),
url(r'^(?P<year>d{4})/(?P<month>d{2})/(?P<day>d{2})/(?P<slug>[-w] )/
- urls.py
from blog.feeds import LatestPostsFeed
from django.conf.urls import url
from django.urls import include, path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.post_list, name='post_list'),
path('<int:year>/<int:month>/<int:day>/<slug:slug>/', views.post_detail, name='post_detail'),
path('<int:post_id>/share/', views.post_share, name='post_share'),
path('tag/<slug:tag_slug>/', views.post_list, name='post_list_by_tag'),
path('feed/', LatestPostsFeed(), name='post_feed'),
path('search/', views.post_search, name='post_search'),
]
Ответ №1:
Попробуй сделать это так :-
def post_search(request):
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
#Changed some indention Here
return render(request, 'blog/post/search.html', {'form': form, 'cd': cd, 'results': results, 'total_results': total_results})
Что я изменил :-
Вы передавали return render
if
заявление внутри, поэтому Django
предположили, что return render
это часть if starement
.
Правка-1
Вы передаете "year", "month" and "day"
параметр для get
сообщений в соответствии с year
? Я понятия не имею, почему вы передаете их в качестве параметра.
Вы пытаетесь показать конкретное сообщение на post_detail
странице, но не передаете , какое сообщение вы пытаетесь открыть, я имею в виду, что вы не передаете Post's id
, поэтому Django никогда не узнает, какое сообщение вы хотите увидеть.
Вы можете сделать это так :-
urls.py
path('post_detail/<slug:slug>/<int:post_id>/, views.post_detail, name='post_detail'),
views.py
def post_detail(request, post_id, slug):
post = get_object_or_404(Post,pk=post_id)
# List of active comments for this post
......
..........
И попробуйте удалить parameters
"год", "месяц" и "день".
Комментарии:
1. Я изменил отступ, но вышла другая ошибка. "127.0.0.1:8000/блог/поиск" или "localhost:8000/блог/поиск" сообщает, что в " post_detail() отсутствуют 3 обязательных позиционных аргумента:" год"," месяц "и"день ""Нет ошибки в" 127.0.0.1:8000/блог " или "localhost:8000/блог".
2. Загрузите свой
urls.py
иview
, в котором вы указываете параметры -"year" , "month" and "day"
.3. Я загрузил его! Вы можете это проверить?
4. @ecrire06, Обновил ответ, Проверьте отредактированный ответ
Ответ №2:
Я внимательно изучил свой код и обнаружил, что ключом к устранению ошибки было добавление возврата еще раз.
def post_search(request):
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
return render(request, 'blog/post/search.html', {'form': form, 'cd': cd, 'results': results, 'total_results': total_results})
return render(request, 'blog/post/search.html', {'form': form})
добавив "возврат рендеринга(запрос, 'blog/post/search.html', {'форма': форма})" после окончания if.
, views.post_detail, name='post_detail'),
url(r'^(?P<post_id>d )/share/
- urls.py
Ответ №1:
Попробуй сделать это так :-
Что я изменил :-
Вы передавали return render
if
заявление внутри, поэтому Django
предположили, что return render
это часть if starement
.
Правка-1
Вы передаете "year", "month" and "day"
параметр для get
сообщений в соответствии с year
? Я понятия не имею, почему вы передаете их в качестве параметра.
Вы пытаетесь показать конкретное сообщение на post_detail
странице, но не передаете , какое сообщение вы пытаетесь открыть, я имею в виду, что вы не передаете Post's id
, поэтому Django никогда не узнает, какое сообщение вы хотите увидеть.
Вы можете сделать это так :-
urls.py
views.py
И попробуйте удалить parameters
"год", "месяц" и "день".
Комментарии:
1. Я изменил отступ, но вышла другая ошибка. "127.0.0.1:8000/блог/поиск" или "localhost:8000/блог/поиск" сообщает, что в " post_detail() отсутствуют 3 обязательных позиционных аргумента:" год"," месяц "и"день ""Нет ошибки в" 127.0.0.1:8000/блог " или "localhost:8000/блог".
2. Загрузите свой
urls.py
иview
, в котором вы указываете параметры -"year" , "month" and "day"
.3. Я загрузил его! Вы можете это проверить?
4. @ecrire06, Обновил ответ, Проверьте отредактированный ответ
Ответ №2:
Я внимательно изучил свой код и обнаружил, что ключом к устранению ошибки было добавление возврата еще раз.
добавив "возврат рендеринга(запрос, 'blog/post/search.html', {'форма': форма})" после окончания if.
, views.post_share, name='post_share'),
path('<slug:slug>/', views.post_detail, name='post_detail'),
url(r'^tag/(?P<tag_slug>[-w] )/
- urls.py
Ответ №1:
Попробуй сделать это так :-
Что я изменил :-
Вы передавали return render
if
заявление внутри, поэтому Django
предположили, что return render
это часть if starement
.
Правка-1
Вы передаете "year", "month" and "day"
параметр для get
сообщений в соответствии с year
? Я понятия не имею, почему вы передаете их в качестве параметра.
Вы пытаетесь показать конкретное сообщение на post_detail
странице, но не передаете , какое сообщение вы пытаетесь открыть, я имею в виду, что вы не передаете Post's id
, поэтому Django никогда не узнает, какое сообщение вы хотите увидеть.
Вы можете сделать это так :-
urls.py
views.py
И попробуйте удалить parameters
"год", "месяц" и "день".
Комментарии:
1. Я изменил отступ, но вышла другая ошибка. "127.0.0.1:8000/блог/поиск" или "localhost:8000/блог/поиск" сообщает, что в " post_detail() отсутствуют 3 обязательных позиционных аргумента:" год"," месяц "и"день ""Нет ошибки в" 127.0.0.1:8000/блог " или "localhost:8000/блог".
2. Загрузите свой
urls.py
иview
, в котором вы указываете параметры -"year" , "month" and "day"
.3. Я загрузил его! Вы можете это проверить?
4. @ecrire06, Обновил ответ, Проверьте отредактированный ответ
Ответ №2:
Я внимательно изучил свой код и обнаружил, что ключом к устранению ошибки было добавление возврата еще раз.
добавив "возврат рендеринга(запрос, 'blog/post/search.html', {'форма': форма})" после окончания if.
, views.post_list, name='post_list_by_tag'),
path('feed', LatestPostsFeed(), name='post_feed'),
url(r'^search/
- urls.py
Ответ №1:
Попробуй сделать это так :-
Что я изменил :-
Вы передавали return render
if
заявление внутри, поэтому Django
предположили, что return render
это часть if starement
.
Правка-1
Вы передаете "year", "month" and "day"
параметр для get
сообщений в соответствии с year
? Я понятия не имею, почему вы передаете их в качестве параметра.
Вы пытаетесь показать конкретное сообщение на post_detail
странице, но не передаете , какое сообщение вы пытаетесь открыть, я имею в виду, что вы не передаете Post's id
, поэтому Django никогда не узнает, какое сообщение вы хотите увидеть.
Вы можете сделать это так :-
urls.py
views.py
И попробуйте удалить parameters
"год", "месяц" и "день".
Комментарии:
1. Я изменил отступ, но вышла другая ошибка. "127.0.0.1:8000/блог/поиск" или "localhost:8000/блог/поиск" сообщает, что в " post_detail() отсутствуют 3 обязательных позиционных аргумента:" год"," месяц "и"день ""Нет ошибки в" 127.0.0.1:8000/блог " или "localhost:8000/блог".
2. Загрузите свой
urls.py
иview
, в котором вы указываете параметры -"year" , "month" and "day"
.3. Я загрузил его! Вы можете это проверить?
4. @ecrire06, Обновил ответ, Проверьте отредактированный ответ
Ответ №2:
Я внимательно изучил свой код и обнаружил, что ключом к устранению ошибки было добавление возврата еще раз.
добавив "возврат рендеринга(запрос, 'blog/post/search.html', {'форма': форма})" после окончания if.
, views.post_search, name='post_search'),
]
```
- blog/views.py
```python
from django.shortcuts import render, get_object_or_404
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.mail import send_mail
from django.views.generic import ListView
from django.db.models import Count
from taggit.models import Tag
from .models import Post, Comment
from .forms import EmailPostForm, CommentForm, SearchForm
from haystack.query import SearchQuerySet
def post_list(request, tag_slug=None):
object_list = Post.published.all()
tag = None
if tag_slug:
tag = get_object_or_404(Tag, slug=tag_slug)
object_list = object_list.filter(tags__in=[tag])
paginator = Paginator(object_list, 3) # 3 posts in each page
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer deliver the first page
posts = paginator.page(1)
except EmptyPage:
# If page is out of range deliver last page of results
posts = paginator.page(paginator.num_pages)
return render(request, 'blog/post/list.html', {'page': page, 'posts': posts, 'tag': tag})
def post_detail(request, year, month, day, slug):
post = get_object_or_404(Post, slug=slug, status='published', publish__year=year, publish__month=month, publish__day=day)
# List of active comments for this post
comments = post.comments.filter(active=True)
new_comment = None
# Comment posted
if request.method == 'POST':
# A comment was posted
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object but don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
# List of similar posts
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags', '-publish')[:4]
return render(request, 'blog/post/detail.html', {'post': post, 'comments': comments, 'comment_form': comment_form, 'similar_posts': similar_posts})
def post_share(request, post_id):
# Retrieve post by id
post = get_object_or_404(Post, id=post_id, status='published')
sent = False
if request.method == 'POST':
# Form was submitted
form = EmailPostForm(request.POST)
if form.is_valid():
# Form fields passed validation
cd = form.cleaned_data
post_url = request.build_absolute_uri(post.get_absolute_url())
subject = '{} ({}) recommends you reading "{}"'.format(cd['name'], cd['email'], post.title)
message = 'Read "{}" at {}nn{}'s comments: {}'.format(post.title, post_url, cd['name'], cd['comments'])
send_mail(subject, message, 'ecrire06@korea.ac.kr', [cd['to']])
sent = True
else:
form = EmailPostForm()
return render(request, 'blog/post/share.html', {'post': post, 'form': form, 'sent': sent})
def post_search(request):
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
return render(request, 'blog/post/search.html', {'form': form, 'cd': cd, 'results': results, 'total_results': total_results})
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 3
template_name = 'blog/post/list.html'
```
# Edit 2
- views.py
```python
from django.shortcuts import render, get_object_or_404
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.mail import send_mail
from django.views.generic import ListView
from django.db.models import Count
from taggit.models import Tag
from .models import Post, Comment
from .forms import EmailPostForm, CommentForm, SearchForm
from haystack.query import SearchQuerySet
def post_list(request, tag_slug=None):
object_list = Post.published.all()
tag = None
if tag_slug:
tag = get_object_or_404(Tag, slug=tag_slug)
object_list = object_list.filter(tags__in=[tag])
paginator = Paginator(object_list, 3) # 3 posts in each page
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer deliver the first page
posts = paginator.page(1)
except EmptyPage:
# If page is out of range deliver last page of results
posts = paginator.page(paginator.num_pages)
return render(request, 'blog/post/list.html', {'page': page, 'posts': posts, 'tag': tag})
def post_detail(request, year, month, day, slug):
post = get_object_or_404(Post, slug=slug, status='published', publish__year=year, publish__month=month, publish__day=day)
# List of active comments for this post
comments = post.comments.filter(active=True)
new_comment = None
# Comment posted
if request.method == 'POST':
# A comment was posted
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object but don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
# List of similar posts
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags', '-publish')[:4]
return render(request, 'blog/post/detail.html', {'post': post, 'comments': comments, 'comment_form': comment_form, 'similar_posts': similar_posts})
def post_share(request, post_id):
# Retrieve post by id
post = get_object_or_404(Post, id=post_id, status='published')
sent = False
if request.method == 'POST':
# Form was submitted
form = EmailPostForm(request.POST)
if form.is_valid():
# Form fields passed validation
cd = form.cleaned_data
post_url = request.build_absolute_uri(post.get_absolute_url())
subject = '{} ({}) recommends you reading "{}"'.format(cd['name'], cd['email'], post.title)
message = 'Read "{}" at {}nn{}'s comments: {}'.format(post.title, post_url, cd['name'], cd['comments'])
send_mail(subject, message, 'ecrire06@korea.ac.kr', [cd['to']])
sent = True
else:
form = EmailPostForm()
return render(request, 'blog/post/share.html', {'post': post, 'form': form, 'sent': sent})
def post_search(request):
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
return render(request, 'blog/post/search.html', {'form': form, 'cd': cd, 'results': results, 'total_results': total_results})
return render(request, 'blog/post/search.html', {'form': form})
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 3
template_name = 'blog/post/list.html'
- urls.py
Ответ №1:
Попробуй сделать это так :-
Что я изменил :-
Вы передавали return render
if
заявление внутри, поэтому Django
предположили, что return render
это часть if starement
.
Правка-1
Вы передаете "year", "month" and "day"
параметр для get
сообщений в соответствии с year
? Я понятия не имею, почему вы передаете их в качестве параметра.
Вы пытаетесь показать конкретное сообщение на post_detail
странице, но не передаете , какое сообщение вы пытаетесь открыть, я имею в виду, что вы не передаете Post's id
, поэтому Django никогда не узнает, какое сообщение вы хотите увидеть.
Вы можете сделать это так :-
urls.py
views.py
И попробуйте удалить parameters
«год», «месяц» и «день».
Комментарии:
1. Я изменил отступ, но вышла другая ошибка. «127.0.0.1:8000/блог/поиск» или «localhost:8000/блог/поиск» сообщает, что в » post_detail() отсутствуют 3 обязательных позиционных аргумента:» год»,» месяц «и»день «»Нет ошибки в» 127.0.0.1:8000/блог » или «localhost:8000/блог».
2. Загрузите свой
urls.py
иview
, в котором вы указываете параметры —"year" , "month" and "day"
.3. Я загрузил его! Вы можете это проверить?
4. @ecrire06, Обновил ответ, Проверьте отредактированный ответ
Ответ №2:
Я внимательно изучил свой код и обнаружил, что ключом к устранению ошибки было добавление возврата еще раз.
добавив «возврат рендеринга(запрос, ‘blog/post/search.html’, {‘форма’: форма})» после окончания if.