Skip to content

Commit

Permalink
Import OPML/CSE XML and more template buildout
Browse files Browse the repository at this point in the history
  • Loading branch information
saschwarz committed Jul 21, 2014
1 parent 6f48acd commit 3edb10e
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 10 deletions.
Empty file added gcse/management/__init__.py
Empty file.
Empty file.
16 changes: 16 additions & 0 deletions gcse/management/commands/import_cse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from lxml import etree as ET
from django.core.management.base import BaseCommand, CommandError
from gcse.models import Annotation, CustomSearchEngine, Label


class Command(BaseCommand):
args = 'url_to_cse_xml'
help = 'Import XML feed into CustomSearchEngine including Annotations'

def handle(self, *args, **options):
if len(args) != 1:
self.stderr.write("import_cse " + Command.args)
exit()
url = args[0]
cse = CustomSearchEngine.from_url(url, import_linked_annotations=True)
cse.save()
38 changes: 38 additions & 0 deletions gcse/management/commands/import_opml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from lxml import etree as ET
from django.core.management.base import BaseCommand, CommandError
from gcse.models import Annotation, CustomSearchEngine, Label


class Command(BaseCommand):
args = 'gid background_label path_to_opml.xml'
help = 'Import outline elements from the specified opml.xml into the specified CustomSearchEngine as Annotations'

def handle(self, *args, **options):
if len(args) != 3:
self.stderr.write("import_opml " + Command.args)
exit()
gid = args[0]
try:
cse = CustomSearchEngine.objects.get(gid=gid)
except CustomSearchEngine.DoesNotExist:
raise CommandError('CustomSearchEngine "%s" does not exist' % gid)

try:
label = Label.objects.get(name=args[1],
background=True)
except Label.DoesNotExist:
raise CommandError('Background Label "%s" does not exist' % gid)

tree = ET.parse(args[2])
for outline in tree.xpath('//outline'):
annotation, created = Annotation.objects.get_or_create(comment=outline.attrib['title'],
original_url=outline.attrib['xmlUrl'])
if created:
annotation.status = Annotation.STATUS.active
annotation.about = Annotation.guess_google_url(annotation.original_url)
annotation.labels.add(label)
annotation.save()

self.stdout.write('Successfully added Annotation "%s"' % annotation)
else:
self.stdout.write('Found existing Annotation "%s"' % annotation)
10 changes: 4 additions & 6 deletions gcse/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def __str__(self):
def xml(self):
return '<FacetItem title="%s">%s</FacetItem>' % (self.title, self.label.xml(complete=False))


@python_2_unicode_compatible
class CustomSearchEngine(TimeStampedModel):
"""
Hybrid representation of the Google Custom Search Engine
Expand Down Expand Up @@ -221,7 +221,7 @@ def annotation_count(self):

def facetitems_labels(self):
"""Return all the Labels for the FacetItems associated with this instance."""
labels = Label.objects.raw('SELECT * FROM gcse_label INNER JOIN gcse_facetitem ON gcse_label.id = gcse_facetitem.label_id WHERE gcse_facetitem.cse_id = %s ORDER BY gcse_label.id', [self.id])
labels = Label.objects.raw('SELECT * FROM gcse_label INNER JOIN gcse_facetitem ON gcse_label.id = gcse_facetitem.label_id WHERE gcse_facetitem.cse_id = %s ORDER BY gcse_label.name', [self.id])
return labels

def get_absolute_url(self):
Expand Down Expand Up @@ -384,6 +384,7 @@ def deleted(self):
return self.get_queryset().select_subclasses().filter(status=Annotation.STATUS.deleted)


@python_2_unicode_compatible
class Annotation(TimeStampedModel):
"""
Abstract base class upon which Annotation entries and local "Place"
Expand Down Expand Up @@ -436,9 +437,6 @@ class Annotation(TimeStampedModel):
help_text=_('Set to newer Annotation instance when user modifies this instance'))

objects = AnnotationManager()

def __unicode__(self):
return u"%s %s" % (self.comment, self.original_url)

def __str__(self):
return "%s %s" % (self.comment, self.original_url)
Expand Down Expand Up @@ -469,7 +467,7 @@ def alpha_list(cls, selection=None):
cursor = connection.cursor()
cursor.execute("SELECT distinct(substr(comment, 1, 1)) FROM "
"gcse_annotation order by substr(comment, 1, 1)")
existent = [str(i[0]) for i in cursor.fetchall()]
existent = [i[0] for i in cursor.fetchall()]
results = []
for i in ascii_letters[26:] + "0123456789":
style = ''
Expand Down
4 changes: 2 additions & 2 deletions gcse/templates/gcse/annotation_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
{% block title %}{% site "name" %} - Browse Alphabetically{% endblock %}

{% block content %}
<h1>Browse Alphabetically</h1>
<p>These <span class="annotation tip">Annotations</span> are currently in the {% site "name" %} search database. You can also <a href="{% url 'gcse_browse_labels' %}">browse Annotations by label</a>.</p>
<h1>Annotations Alphabetically</h1>
<p>There are {{count}} <span class="annotation tip">Annotations</span> are currently in the {% site "name" %} search database. You can also <a href="{% url 'gcse_browse_labels' %}">browse Annotations by label</a>.</p>
{% block alpha-nav %}
<ul class="alpha-nav pagination">
<colgroup>{% for i in index %}<col width="1*" />{%endfor%}</colgroup>
Expand Down
31 changes: 31 additions & 0 deletions gcse/templates/gcse/cse_annotation_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{% extends "gcse/base.html" %}
{% load setting %}
{% block title %}{% site "name" %} - {{ cse.title }} Annotations{% endblock %}

{% block content %}
<h1>{{ cse.title }} Annotations</h1>
<p>There are {{count}} <span class="annotation tip">Annotations</span> for the <a href="{{ cse.get_absolute_url }}">{{ cse.title }} custom search engine</a> in the {% site "name" %} search database. You can also <a href="{% url 'gcse_browse_labels' %}">browse Annotations by label</a>.</p>
{% block alpha-nav %}
<ul class="alpha-nav pagination">
<colgroup>{% for i in index %}<col width="1*" />{%endfor%}</colgroup>
{% for i in index %}
<li class="{{i.style}}"><a href="?q={{i.i}}">{{i.i}}</a></li>
{% endfor%}
</ul>
{% endblock alpha-nav %}
<table class="table search-results">
<tbody>
<tr><th>Name</th><th>Labels</th><th>URL</th></tr>
{% for site in annotation_list %}
<tr class="{% cycle 'odd' 'even' %}"><td><a href="{{site.get_absolute_url}}">{{ site.comment|escape }}</a></td><td>{{site.labels_as_links|safe}}</td><td><a href="{{site.original_url}}">{{site.original_url}}</a></td></tr>
{% endfor %}
</tbody>
</table>
{% block pagination %}
<ul class="pager">
<li class="previous"> {% if page_obj.has_previous %}<a href="?page={{ page_obj.previous_page_number }}">previous</a>{% endif %}</li>
<li class="current">Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</li>
<li class="next">{% if page_obj.has_next %}<a href="?page={{ page_obj.next_page_number }}">next</a>{% endif %}</li>
</ul>
{% endblock pagination %}
{% endblock %}
18 changes: 18 additions & 0 deletions gcse/templates/gcse/cse_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "gcse/base.html" %}
{% load setting %}
{% block title %}{% site "name" %} - Custom Search Engine: {{ object.title }}{% endblock %}

{% block content %}
<h1>{{ object.title }}</h1>
<p>This Google Custom Search Engine contains {{object.annotation_count}} Annotation entries.</p>
<p><a href="{% url 'gcse_cse_annotation_list' gid=object.gid %}">View this Custom Search Engine's Annotations</a></p>
<h2>Labels</h2>
<table class="table search-results">
<tbody>
<tr><th>Name</th></tr>
{% for label in object.facetitems_labels %}
<tr class="{% cycle 'odd' 'even' %}"><td><a href="{{label.get_absolute_url}}">{{ label.name|escape }}</a></td></tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
6 changes: 5 additions & 1 deletion gcse/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.conf.urls import patterns, url
from django.views.generic import TemplateView
from .feeds import RssLatestFeed, AtomLatestFeed
from .views import (CSEAnnotations, CustomSearchEngineList,
from .views import (CSEAnnotations, CSEAnnotationList, CustomSearchEngineList,
CustomSearchEngineDetail, CustomSearchEngineDetailXML,
AnnotationList, browse_labels)

Expand Down Expand Up @@ -41,6 +41,10 @@
CustomSearchEngineList.as_view(),
name='gcse_cse_list'),

url(r'^cse/(?P<gid>[\w-]+)/annotations/$',
CSEAnnotationList.as_view(),
name='gcse_cse_annotation_list'),

url(r'^site/$',
AnnotationList.as_view(),
name='gcse_annotation_list'), # browse by site name
Expand Down
33 changes: 32 additions & 1 deletion gcse/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class CustomSearchEngineList(ListView):
class CustomSearchEngineDetail(DetailView):
model = CustomSearchEngine
slug_url_kwarg = 'gid'
slug_field = 'gid'
template_name = 'gcse/cse_detail.html'


Expand Down Expand Up @@ -70,6 +71,35 @@ def get_queryset(self):
return cse.annotations()


class CSEAnnotationList(ListView):
"""
Render all the Annotations in alphabetical order in a paged manner for a single CSE.
"""
context_object_name = 'annotation_list'
model = Annotation
paginate_by = settings.GCSE_CONFIG.get('NUM_ANNOTATIONS_PER_PAGE')
template_name = 'gcse/cse_annotation_list.html'

def get_queryset(self):
cse = get_object_or_404(CustomSearchEngine,
gid=self.kwargs['gid'])
self.cse = cse
query = self.request.GET.get('q', 'A')
qset = (
Q(comment__istartswith=query)
)
return cse.annotations().filter(qset).order_by('comment')

def get_context_data(self, *args, **kwargs):
context = super(CSEAnnotationList, self).get_context_data(**kwargs)
query = self.request.GET.get('q', 'A')
context['index'] = Annotation.alpha_list(query)
context['query'] = query
context['count'] = self.cse.annotation_count()
context['cse'] = self.cse
return context


class AnnotationList(ListView):
"""
Render all the Annotations in alphabetical order in a paged manner.
Expand All @@ -86,11 +116,12 @@ def get_queryset(self):
)
return Annotation.objects.active().filter(qset).distinct().order_by('comment')

def get_context_data(self, **kwargs):
def get_context_data(self, *args, **kwargs):
context = super(AnnotationList, self).get_context_data(**kwargs)
query = self.request.GET.get('q', 'A')
context['index'] = Annotation.alpha_list(query)
context['query'] = query
context['count'] = Annotation.objects.count()
return context


Expand Down

0 comments on commit 3edb10e

Please sign in to comment.