Changeset - 843dbaebdae4
[Not reviewed]
default
0 4 1
Branko Majic (branko) - 10 years ago 2013-10-19 12:57:09
branko@majic.rs
CONNT-19: Implemented search over names and descriptions.
5 files changed with 138 insertions and 0 deletions:
0 comments (0 inline, 0 general)
conntrackt/models.py
Show inline comments
 
@@ -23,6 +23,28 @@
 
from django.core.exceptions import ValidationError
 
from django.core.urlresolvers import reverse
 
from django.db import models
 
from django.db.models.query_utils import Q
 

	
 

	
 
class SearchManager(models.Manager):
 
    """
 
    Custom model manager that implements search for model instances that contain
 
    a specific string (search term) in fields "name" or "description".
 
    """
 

	
 
    def search(self, search_term):
 
        """
 
        Performs a search for model instances that contain the provided search
 
        term in fields "name" or "description". The search is case-insensitive.
 

	
 
        Arguments:
 
          search_term - String to search the name and description for.
 

	
 
        Returns:
 
          Query set with model instances that matched the search.
 
        """
 

	
 
        return self.filter(Q(name__icontains=search_term) | Q(description__icontains=search_term))
 

	
 

	
 
class Project(models.Model):
 
@@ -39,6 +61,7 @@ class Project(models.Model):
 

	
 
    name = models.CharField(max_length=100, unique=True)
 
    description = models.TextField(blank=True)
 
    objects = SearchManager()
 

	
 
    class Meta:
 
        permissions = (("view", "Can view information"),)
 
@@ -119,6 +142,7 @@ class Entity(models.Model):
 
    description = models.TextField(blank=True)
 
    project = models.ForeignKey(Project)
 
    location = models.ForeignKey(Location)
 
    objects = SearchManager()
 

	
 
    class Meta:
 
        # Fix the plural form used by Django.
conntrackt/templates/conntrackt/base.html
Show inline comments
 
@@ -34,6 +34,14 @@
 
              <li class="{% active_link 'admin' %}"><a href="{% url "admin:app_list" "conntrackt" %}"><i class="icon-wrench icon-white"></i> Administration</a></li>
 
            </ul>
 
            <ul class="nav pull-right">
 
              <li>
 
                <form action="{% url "search" %}" class="navbar-search pull-left" method="GET">
 
                  <div class="input-prepend">
 
                    <button type="submit" class="btn btn-link"><span class="icon-search icon-white"></span></button>
 
                    <input class="span2 search-query" type="text" name="q"  placeholder="Search">
 
                  </div>
 
                </form>
 
              </li>
 
              {% if user.is_anonymous %}
 
              <li>{% html_link '<i class="icon-user icon-white"></i> Log-in' 'login' get="next="|add:request.path %}</li>
 
              {% else %}
conntrackt/templates/conntrackt/search.html
Show inline comments
 
new file 100644
 
{% extends "conntrackt/base.html" %}
 

	
 
{% block content %}
 

	
 
<div class="row">
 
  <div class="span12">
 
    {% if search_term %}
 
      <h1>Search results for: <strong>{{ search_term }}</strong></h1>
 
    {% else %}
 
      <h1>Search</h1>
 
    {% endif %}
 
  </div>
 

	
 
  <div class="span12">
 
    <hr>
 
    <form action="{% url "search" %}" class="form-search" method="GET">
 
      <input class="search-query" type="text" name="q"  placeholder="Search" value="{{ search_term }}"/>
 
      <button type="submit" class="btn"><span class="icon-search"></span> Search</button>
 
    </form>
 
    <hr>
 

	
 
    {% if projects %}
 
      <h2><small>Matched projects</small></h2>
 
      <ul class="unstyled">
 
        {% for project in projects %}
 
          <li><a href="{{ project.get_absolute_url }}">{{ project.name }}</a></li>
 
        {% endfor %}
 
      </ul>
 
      <hr>
 
    {% elif search_term %}
 
      <p>There are no projects matching your query.</p>
 
      <hr>
 
    {% endif %}
 

	
 
    {% if entities %}
 
      <h2><small>Matched Entities</small></h2>
 
      <ul class="unstyled">
 
        {% for entity in entities %}
 
          <li><a href="{{ entity.get_absolute_url }}">{{ entity.name }}</a> (from {{ entity.project.name }})</li>
 
        {% endfor %}
 
      </ul>
 
      <hr>
 
    {% elif search_term %}
 
      <p>There are no entities matching your query.</p>
 
      <hr>
 
    {% endif %}
 

	
 
  </div>
 
</div>
 
{% endblock content %}
conntrackt/urls.py
Show inline comments
 
@@ -30,6 +30,7 @@ from .views import LocationCreateView, L
 
from .views import EntityCreateView, EntityUpdateView, EntityDeleteView
 
from .views import InterfaceCreateView, InterfaceUpdateView, InterfaceDeleteView
 
from .views import CommunicationCreateView, CommunicationUpdateView, CommunicationDeleteView
 
from .views import SearchView
 

	
 

	
 
urlpatterns = patterns(
 
@@ -91,4 +92,7 @@ urlpatterns = patterns(
 
    # Views for logging-in/out the users.
 
    url(r'^login/$', login, {'template_name': 'conntrackt/login.html'}, name="login"),
 
    url(r'^logout/$', logout, name="logout"),
 

	
 
    # View for displaying the search page.
 
    url(r'^search/$', SearchView.as_view(), name="search"),
 
)
conntrackt/views.py
Show inline comments
 
@@ -27,6 +27,7 @@ from zipfile import ZipFile, ZIP_DEFLATE
 
from django.contrib.auth.decorators import permission_required
 
from django.contrib import messages
 
from django.core.urlresolvers import reverse, reverse_lazy
 
from django.db.models import Q
 
from django.http import HttpResponse
 
from django.shortcuts import render_to_response, get_object_or_404
 
from django.views.generic import TemplateView, DetailView, CreateView, UpdateView, DeleteView
 
@@ -965,3 +966,54 @@ def project_diagram(request, pk):
 

	
 
    # Return the response object.
 
    return response
 

	
 

	
 
class SearchView(MultiplePermissionsRequiredMixin, TemplateView):
 
    """
 
    Custom view used for rendering the search (results) page.
 
    """
 

	
 
    template_name = 'conntrackt/search.html'
 

	
 
    # Required permissions.
 
    permissions = {
 
        "all": ("conntrackt.view",),
 
        }
 

	
 
    # Raise authorisation denied exception for unmet permissions.
 
    raise_exception = True
 

	
 
    def get_context_data(self, **kwargs):
 
        """
 
        Returns the context data that should be used for rendering of the
 
        template.
 

	
 
        Adds context objects:
 
          - 'entities', which is a list of entities that had the search term in
 
            their name or description.
 
          - 'projects', which is a list of entities that had the search term in
 
            their name or description.
 
          - 'search_term', which is a string of previous query that brought the
 
            user to page (if any). The term will be stripped from leading and
 
            trailing spaces/tabs.
 
        """
 

	
 
        # Set the context using the parent aclass.
 
        context = super(SearchView, self).get_context_data(**kwargs)
 

	
 
        # Retrieve the search term, and strip it if it was provided.
 
        search_term = self.request.GET.get("q", None)
 
        if search_term:
 
            search_term = search_term.strip()
 

	
 
        # Do not allow empty searches.
 
        if search_term == "":
 
            messages.error(self.request, "Search query is not allowed to be empty.", extra_tags="alert alert-error")
 
        # Set-up the context objects if search was sent. Otherwise empty search
 
        # page will be shown.
 
        elif search_term is not None:
 
            context['search_term'] = search_term
 
            context['entities'] = Entity.objects.search(search_term)
 
            context['projects'] = Project.objects.search(search_term)
 

	
 
        return context
0 comments (0 inline, 0 general)