I’m making my first steps with django, at the moment im trying to apply simple search solution for my website using: http://julienphalip.com/post/2825034077/adding-search-to-a-django-site-in-a-snap
This is how code looks like:
search.py
import re
from django.db.models import Q
def normalize_query(query_string,
findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
normspace=re.compile(r'\s{2,}').sub):
''' Splits the query string in invidual keywords, getting rid of unecessary spaces
and grouping quoted words together.
Example:
>>> normalize_query(' some random words "with quotes " and spaces')
['some', 'random', 'words', 'with quotes', 'and', 'spaces']
'''
return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
def get_query(query_string, search_fields):
''' Returns a query, that is a combination of Q objects. That combination
aims to search keywords within a model by testing the given search fields.
'''
query = None # Query to search for every search term
terms = normalize_query(query_string)
for term in terms:
or_query = None # Query to search for a given term in each field
for field_name in search_fields:
q = Q(**{"%s__icontains" % field_name: term})
if or_query is None:
or_query = q
else:
or_query = or_query | q
if query is None:
query = or_query
else:
query = query & or_query
return query
views.py
from news.models import *
from news.search import *
from django.shortcuts import render_to_response
from django.template import RequestContext
def search(request):
query_string = ''
found_entries = None
search_fields=('text','title',)
if ('q' in request.GET) and request.GET['q'].strip():
query_string = request.GET['q']
entry_query = get_query(query_string, search_fields)
found_entries = News.objects.filter(entry_query).order_by('-id')
return render_to_response('search/search.html',
{ 'query_string': query_string, 'found_entries': found_entries },
context_instance=RequestContext(request))
models.py
STATUS_CHOICES = (
('d', 'Draft'),
('p', 'Published'),
('w', 'Withdrawn'),
)
class News(models.Model):
category = models.ManyToManyField(Category, verbose_name='Kategorie')
title = models.CharField(max_length=255, verbose_name='Tytuł')
slug = models.SlugField(max_length=255, unique=True, verbose_name='Odnośnik')
text = models.TextField(verbose_name='Treść')
date = models.DateTimeField(verbose_name='Data dodania')
author = models.ForeignKey(User, verbose_name='Autor')
status = models.CharField(max_length=1, choices=STATUS_CHOICES, default='d')
class Meta:
verbose_name = "Wiadomość"
verbose_name_plural = "Wiadomość"
def __str__(self):
return self.title
def __unicode__(self):
return self.title
def get_absolute_url(self):
return '/news/' + self.slug + '/'
search.html
{% if found_entries %}
<p>You searched for "{{ query_string }}".</p>
<ul>
{% for i in found_entries %}
<li><a href="{{ q.get_absolute_url }}">{{found_entries }}</a></li>
{% endfor %}
</ul>
{% endif %}
{% if query_string and not found_entries %}
<p>No results found.</p>
{% else %}
<p>Type a search query into the box above, and press "Submit" to search.</p>
{% endif %}
What im trying to do is to get a proper view for search results (searching through news model, this should return title + couple of lanes of text maybe?) This is what it looks like atm: http://dl.dropbox.com/u/26827941/ScreenShot108.png (im not allowed to post images yet)
It took atleast couple of hours for me to try to find a proper solution for how should i modify my views.py and search.html in order to get proper view results, could you help me a little bit please?
This is where your problem is
When you simply show
{{i}}, then the model’s__unicode__method is used.If you want to show more, you can use
{{i.category}},{{i.title}}, etc.