Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

glue api added. Enjoy the basic app!

  • Loading branch information...
commit 15af0c36cccc9eadeaa911f210d07fb783948a56 1 parent 0b99979
@danieleguido authored
View
23 README.md
@@ -1,10 +1,29 @@
walt
====
-a pythonical django approach for adaptation (Wander, Ask, Learn, Tell)
+a pythonical django approach for adaptation (Wander / Watch, Ask, Learn, Tell)
[install virtualenv, virtualenvwrapper](http://virtualenvwrapper.readthedocs.org/en/latest/)
cd walt
- pip install -r requirements.txt
+ pip install -r requirements.txt
+
+Let's suppose our WORKON_HOME is /path/to/Envs...
+
+Change your LOCAL local_settings.py (cfr settings.py), there is a sample local settings file you can use as base.
+
+Configure apache conf and your wsgi. We provide to sample file as well.
+
+Create admin link,
+
+ $ cd /path/to/walt/static/
+ $ ln -s /path/to/Envs/walt/lib/python2.6/site-packages/django/contrib/admin/static/admin admin
+
+and do a proper syncdb command
+
+ $ cd /path/to/walt/
+ $ python manage.py syncdb
+
+
+goto setup apge
View
0  glue/__init__.py 100644 → 100755
File mode changed
View
0  glue/admin.py 100644 → 100755
File mode changed
View
0  glue/forms.py 100644 → 100755
File mode changed
View
14 glue/models.py
@@ -1,10 +1,7 @@
-from django.db import models
+from django.conf import settings
from django.contrib.auth.models import User
+from django.db import models
-LANGUAGE_CHOICES = (
- ('EN', 'EN'),
- ('FR', 'FR')
-)
class Geo( models.Model): # geo spot, with zoom
lat = models.FloatField() # map center LAT
@@ -12,6 +9,9 @@ class Geo( models.Model): # geo spot, with zoom
zoom = models.IntegerField() # start zoom
content = models.TextField( default="", blank=True, null=True ) # textual GEO description
+# class Tag( models.Model ):
+
+
class Pin( models.Model ):
published='P'
draft='D'
@@ -22,7 +22,7 @@ class Pin( models.Model ):
title = models.CharField( max_length=160, default="", blank=True, null=True )
abstract = models.TextField( default="", blank=True, null=True )
content = models.TextField( default="", blank=True, null=True )
- language = models.CharField( max_length=2, default='EN', choices=LANGUAGE_CHOICES ) # magic admin features: create a pin for the same language
+ language = models.CharField( max_length=2, default='EN', choices=settings.LANGUAGES ) # magic admin features: create a pin for the same language
mimetype = models.CharField( max_length=255, default="", blank=True, null=True )
sort = models.IntegerField( default=0 )
@@ -65,7 +65,7 @@ class PageAbstract( models.Model ):
abstract = models.TextField( default="", blank=True, null=True )
content = models.TextField( default="", blank=True, null=True )
- language = models.CharField( max_length=2, default='EN', choices=LANGUAGE_CHOICES ) # magic admin features: create a pin for the same language
+ language = models.CharField( max_length=2, default='EN', choices=settings.LANGUAGES ) # magic admin features: create a pin for the same language
sort = models.IntegerField( default=0 )
class Meta:
View
22 glue/urls.py
@@ -5,18 +5,18 @@
url(r'^$', 'glue.api.index', name='glue_api_index'),
- url(r'^api/manage/(?P<model_name>[a-zA-Z_]+)/$', 'glue.api.manage_objects', name='glue_api_manage_objects'),
- url(r'^api/manage/(?P<model_name>[a-zA-Z_]+)/(?P<pk>\d+)$', 'glue.api.manage_single_object', name='glue_api_manage_single_object'),
+ url(r'^manage/(?P<model_name>[a-zA-Z_]+)/$', 'glue.api.manage_objects', name='glue_api_manage_objects'),
+ url(r'^manage/(?P<model_name>[a-zA-Z_]+)/(?P<pk>\d+)$', 'glue.api.manage_single_object', name='glue_api_manage_single_object'),
- url(r'^api/test/$', 'glue.api.test', name='glue_api_test'), # get list, post single page
+ url(r'^test/$', 'glue.api.test', name='glue_api_test'), # get list, post single page
- url(r'^api/page/$', 'glue.api.pages', name='glue_api_pages'), # get list, post single page
- url(r'^api/page/(?P<page_id>\d+)/$', 'glue.api.page', name='glue_api_page'),
- url(r'^api/page/(?P<page_slug>[a-zA-Z\d\-]+)/(?P<page_language>[a-zA-Z]{2})/$', 'glue.api.page_by_slug', name='glue_api_page_by_slug'),
+ url(r'^page/$', 'glue.api.pages', name='glue_api_pages'), # get list, post single page
+ url(r'^page/(?P<page_id>\d+)/$', 'glue.api.page', name='glue_api_page'),
+ url(r'^page/(?P<page_slug>[a-zA-Z\d\-]+)/(?P<page_language>[a-zA-Z]{2})/$', 'glue.api.page_by_slug', name='glue_api_page_by_slug'),
- url(r'^api/pin/$', 'glue.api.pins', name='glue_api_pins'), # get list, post single page
- url(r'^api/pin/(?P<pin_id>\d+)/$', 'glue.api.pin', name='glue_api_pin'),
- url(r'^api/pin/(?P<pin_slug>[a-zA-Z\d\-]+)/(?P<pin_language>[a-zA-Z]{2})/$', 'glue.api.pin_by_slug', name='glue_api_pin_by_slug'),
- url(r'^api/pin/(?P<pin_id>\d+)/publish/$', 'glue.api.publish_pin', name='glue_api_publish_pin'),
- url(r'^api/pin/upload/$', 'glue.api.pin_upload', name='glue_api_pin_upload'),
+ url(r'^pin/$', 'glue.api.pins', name='glue_api_pins'), # get list, post single page
+ url(r'^pin/(?P<pin_id>\d+)/$', 'glue.api.pin', name='glue_api_pin'),
+ url(r'^pin/(?P<pin_slug>[a-zA-Z\d\-]+)/(?P<pin_language>[a-zA-Z]{2})/$', 'glue.api.pin_by_slug', name='glue_api_pin_by_slug'),
+ url(r'^pin/(?P<pin_id>\d+)/publish/$', 'glue.api.publish_pin', name='glue_api_publish_pin'),
+ url(r'^pin/upload/$', 'glue.api.pin_upload', name='glue_api_pin_upload'),
)
View
66 static/less/style.less
@@ -3,13 +3,73 @@
@grid-padding: 24px;
+@red: #cc1600;
+
body{
background: white;
height: 100%;
- .sans-serif(10px);
+ .sans-serif(13px);
+ color: #383838;
+}
+h1{
+ .sans-serif(24px);
}
-
h2{
- border-bottom: 1px solid #eee;
+ border-bottom: 1px solid #ccc;
+ padding-bottom: @grid-padding;
+ .mono-caps(14px);
+ color: #000;
+ .description{
+ .mono(12px, lowercase);
+ }
+}
+
+.item{
+ margin-bottom: @grid-padding;
+
+ padding-bottom: @grid-padding;
+ border-bottom: 1px solid #ccc;
+ h3{
+ .serif-slant(17px);
+ color: #000;
+ }
+ h4{
+ .serif(17px);
+ color: #000;
+ }
+ blockquote{
+ padding: @grid-padding/2 0;
+ margin:0;
+
+ }
+}
+
+.timeline{
+ width: 100%;
+ .inner{
+ position:absolute;
+
+
+ }
+
+ .title{
+
+ }
+ .start{
+ float:left;
+
+ padding-right: 6px;
+ }
+ .end{
+ float:right;
+
+
+ }
+}
+
+.story{
+ margin-bottom: @grid-padding;
+
padding-bottom: @grid-padding;
+ border-bottom: 1px solid #ccc;
}
View
195 templates/walt/index.html
@@ -3,16 +3,191 @@
{% block page %}
- <div class="grid_3 alpha">
- <h2>watch</h2>
- </div>
- <div class="grid_3">
- <h2>ask</h2>
- </div>
- <div class="grid_3">
- <h2>learn</h2>
+ <div class="grid_12">
+ <h2 style="border-width:0px">Protocols</h2>
+
+ <div class="stories">
+ <div class="story">
+ <div class="title">Grimm fairy tale analysis. <span><a href="#">play</a></span></div>
+ <div class="timeline">
+ <div class="inner">
+ <div class="start">1867 &rarr;</div>
+
+ <div class="end">2013</div>
+
+ </div>
+ </div>
+ </div>
+
+ <div class="story">
+ <div class="title">Learn how to get more value out of metadata easily <span><a href="#">play</a></span></div>
+ <div class="timeline">
+ <div class="inner">
+ <div class="start">2005 &rarr;</div>
+
+ <div class="end">2013</div>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
- <div class="grid_3 omega">
- <h2>tell</h2>
+
+
+ <div class="grid_12">
+
+ <div class="grid_3 alpha">
+ <h2>{{ walt.wander.title }}
+ <div class="description">
+ {{ walt.wander.abstract }} ( {{ walt.wander.pins.count }} )
+ </div>
+ </h2>
+
+ <div class="items">
+ <div class="item">
+ <div class="content">
+ <img src="http://yakyakyak.fr/wp-content/uploads/2013/02/lumberjack.png" style="width: 100%"/>
+ </div>
+ <h3>Visualizing Networks: Beyond the Hairball</h3>
+ <div class="metadata"><span class="date">25 Feb. 2013</span>
+ <a href="#" class="tag">video</a>, <a href="#" class="tag">documentaire</a>, <a href="#" class="tag">ontology</a>
+ </div>
+ <blockquote>
+ Lumberjack permet la gestion des métadonnées en temps réel lors d’un tournage. Il se présente via une page internet sur un iPad par exemple, où il suffit de cocher pendant une interview les mots clés adéquats ( personnes, thèmes lieux…).
+ </blockquote>
+ <div class="comment">
+ <a href="#" class="author">b.s.</a> peut-être une idée pour mettre en place un outil d'observation...
+ </div>
+ </div>
+
+
+ <div class="item">
+ <div class="content">
+ <img src="http://yakyakyak.fr/wp-content/uploads/2013/02/lumberjack.png" style="width: 100%"/>
+ </div>
+ <h3>Lumberjack: Gérer les métadonnées pour le documentaire</h3>
+ <div class="metadata"><span class="date">22 Feb. 2013</span>
+ <a href="#" class="tag">video</a>, <a href="#" class="tag">documentaire</a>, <a href="#" class="tag">ontology</a>
+ </div>
+ <blockquote>
+ Lumberjack permet la gestion des métadonnées en temps réel lors d’un tournage. Il se présente via une page internet sur un iPad par exemple, où il suffit de cocher pendant une interview les mots clés adéquats ( personnes, thèmes lieux…).
+ </blockquote>
+ <div class="comment">
+ <a href="#" class="author">b.s.</a> peut-être une idée pour mettre en place un outil d'observation...
+ </div>
+ </div>
+
+ <div class="item">
+
+ <h3>Synchronous objects</h3>
+ <div class="metadata"><span class="date">20 Feb. 2013</span>
+ <a href="#" class="tag">video</a>, <a href="#" class="tag">documentaire</a>, <a href="#" class="tag">ontology</a>
+ </div>
+ <blockquote>
+ Lumberjack permet la gestion des métadonnées en temps réel lors d’un tournage. Il se présente via une page internet sur un iPad par exemple, où il suffit de cocher pendant une interview les mots clés adéquats ( personnes, thèmes lieux…).
+ </blockquote>
+ <div class="comment">
+ <a href="#" class="author">b.s.</a> Très bel exemple de vidéo avec graphisme intégré, dans une très belle interface interactive et dynamique...
+ </div>
+ <div class="comment">
+ <a href="#" class="author">t.c.</a>
+ oui , c'est magnifique (surtout la danse)
+ merci bertrand
+ </div>
+ <div class="comment">
+ <a href="#" class="author">d.b.</a> et magnifique aussi en vue du dessus qu'il faut sélectionner . La chorégraphie a toujours été une graphie, là elle est en plus doublement graphiée
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+ <div class="grid_3">
+ <h2>{{ walt.ask.title }}
+ <div class="description">
+ {{ walt.ask.abstract }} ( {{ walt.ask.pins.count }} )
+ </div>
+ </h2>
+ <div class="items">
+ <div class="item">
+ <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F80053791"></iframe>
+ </div>
+ </div>
+ </div>
+ <div class="grid_3">
+ <h2>{{ walt.learn.title }}
+ <div class="description">
+ {{ walt.learn.abstract }} ( {{ walt.learn.pins.count }} )
+ </div>
+ </h2>
+ <div class="items">
+ <div class="item">
+ <h4>C Dollerup</h4>
+ <h3>Tales and Translation: The Grimm Tales from Pan-Germanic narratives to shared international fairytales</h3>
+ <div class="metadata">C Dollerup - 1999 - books.google.com
+ <a href="#" class="tag">video</a>, <a href="#" class="tag">documentaire</a>, <a href="#" class="tag">ontology</a>
+ </div>
+ <blockquote>
+ Dealing with the most translated work of German literature, the Tales of the brothers Grimm
+ (1812-1815), this book discusses their history, notably in relation to Denmark and
+ subsequently other nations from 1816 to 1986. The Danish intelligentsia responded\
+ </blockquote>
+ </div>
+ <div class="item">
+ <h4>T Honkela, V Pulkki, T Kohonen</h4>
+ <h3>Contextual relations of words in Grimm tales analyzed by self-organizing map</h3>
+ <div class="metadata">Proceedings of ICANN-95, …, 1995 - users.ics.aalto.fi
+ <a href="#" class="tag">video</a>, <a href="#" class="tag">documentaire</a>, <a href="#" class="tag">ontology</a>
+ </div>
+ <blockquote>
+ Dealing with the most translated work of German literature, the Tales of the brothers Grimm
+ (1812-1815), this book discusses their history, notably in relation to Denmark and
+ subsequently other nations from 1816 to 1986. The Danish intelligentsia responded\
+ </blockquote>
+ </div>
+ </div>
+ </div>
+ <div class="grid_3 omega">
+ <h2>{{ walt.try.title }}
+ <div class="description">
+ {{ walt.try.abstract }} ( {{ walt.try.pins.count }} )
+ </div>
+ </h2>
+ <div class="items">
+ {% for pin in walt.try.pins.all|slice:":10" %}
+ <div class="item">
+
+ <h3>{{ pin.title }}</h3>
+ <div class="metadata"><span class="date">{{ pin.ref_date }}</span>
+ <a href="#" class="tag">video</a>, <a href="#" class="tag">documentaire</a>, <a href="#" class="tag">ontology</a>
+ </div>
+ <blockquote>
+ {{ pin.abstract }}
+
+ </blockquote>
+ <a class="external" href="{{ pin.permalink}}">tabletonet</a>
+ <div class="comment">
+ <a href="#" class="author">b.s.</a> Très bel exemple de vidéo avec graphisme intégré, dans une très belle interface interactive et dynamique...
+ </div>
+
+ </div>
+ {% endfor %}
+ <div class="item">
+
+ <h3>Table2Net</h3>
+ <div class="metadata"><span class="date">20 Feb. 2013</span>
+ <a href="#" class="tag">video</a>, <a href="#" class="tag">documentaire</a>, <a href="#" class="tag">ontology</a>
+ </div>
+ <blockquote>
+ Table to net permet
+
+ </blockquote>
+ <a class="external" href="#medialab tool">tabletonet</a>
+ <div class="comment">
+ <a href="#" class="author">b.s.</a> Très bel exemple de vidéo avec graphisme intégré, dans une très belle interface interactive et dynamique...
+ </div>
+
+ </div>
+ </div>
+ </div>
</div>
{% endblock %}
View
21 templates/walt/middle.html
@@ -3,11 +3,24 @@
{% block body %}
<div class="container_12">
- <div class="grid_12">
+ <div class="grid_12">
<h1>walt.</h1>
- {% block page %}
-
- {% endblock %}
</div>
+
+
+ {% block page %}
+
+ {% endblock %}
+
+ {% block footer %}
+
+ <div class="grid_12">
+ language:{{ language }} {% for language in languages %} {{ language }}{%if not forloop.last %}, {%endif%}{% endfor %}
+ {{ warnings }}
+ </div>
+
+ {% endblock %}
</div>
+
+
{% endblock %}
View
22 walt/settings.py
@@ -96,6 +96,7 @@
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.middleware.locale.LocaleMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
@@ -117,7 +118,7 @@
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
- # 'django.contrib.admin',
+ 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'glue'
@@ -136,12 +137,24 @@
'()': 'django.utils.log.RequireDebugFalse'
}
},
+ 'formatters': {
+ 'verbose': {
+ 'format': '%(levelname)s %(asctime)s %(module)s.%(funcName)s(%(lineno)d) %(message)s'
+ },
+ },
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
- }
+ },
+ 'glue':{
+ 'level': 'DEBUG',
+ 'class': 'logging.handlers.RotatingFileHandler',
+ 'filename': local_settings.GLUE_LOG_PATH,
+ 'maxBytes': '16777216', # 16 megabytes
+ 'formatter': 'verbose'
+ },
},
'loggers': {
'django.request': {
@@ -149,6 +162,11 @@
'level': 'ERROR',
'propagate': True,
},
+ 'glue':{ # glue content management app
+ 'handlers': ['glue'],
+ 'level': 'INFO',
+ 'propagate': True
+ }
}
}
View
8 walt/urls.py
@@ -2,20 +2,22 @@
from django.views.generic.simple import direct_to_template
# Uncomment the next two lines to enable the admin:
-# from django.contrib import admin
-# admin.autodiscover()
+from django.contrib import admin
+admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'walt.views.home', name='walt_home'),
+ url(r'^setup/$', 'walt.views.setup', name='walt_setup'),
url(r'^robots\.txt$', direct_to_template, {'template': 'walt/robots.txt', 'mimetype': 'text/plain'}),
url(r'^humans\.txt$', direct_to_template, {'template': 'walt/humans.txt', 'mimetype': 'text/plain'}),
url(r'^crossdomain\.xml$', direct_to_template, {'template': 'walt/crossdomain.xml', 'mimetype': 'text/xml'}),
# url(r'^walt/', include('walt.foo.urls')),
+ url(r'^api/', include('glue.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
- # url(r'^admin/', include(admin.site.urls)),
+ url(r'^admin/', include(admin.site.urls)),
)
View
64 walt/views.py
@@ -1,23 +1,42 @@
+import logging
+
+from django.db.models import Q
from django.conf import settings
+from django.contrib.admin.views.decorators import staff_member_required
+from django.contrib.auth.models import Group
+
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template import RequestContext
from django.utils.translation import ugettext as _
from django.utils.translation import get_language
+
from glue.models import Pin, Page
+
+logger = logging.getLogger('glue')
+
+# slugs of walt pages.
+WALT_PAGES = ['wander','ask','learn','try']
+
#
# SHARED, commont context (tags, language, user availability...)
#
def sc( request, tags=[], d={} ):
+
# startup
d['tags'] = tags
d['language'] = get_language()
+ d['languages'] = dict( settings.LANGUAGES )
+ d['warnings'] = {}
+ d['walt'] = dict([(p.slug,p) for p in Page.objects.filter( language=d['language'], slug__in=WALT_PAGES ) ] )
+ return d
def home( request ):
data = sc( request, tags=[ "home" ] )
+
return render_to_response( "walt/index.html", RequestContext(request, data ) )
try:
data['page'] = Page.objects.get( slug="index", language=data['language'])
@@ -36,4 +55,49 @@ def home( request ):
# get news
data['news'] = Pin.objects.filter(language=data['language'], page__isnull=True ).order_by("-id")
+ return render_to_response( "walt/index.html", RequestContext(request, data ) )
+
+# call this function once. It will check for page availability and other stories...
+@staff_member_required
+def setup( request ):
+ data = sc( request, tags=[ "home" ] )
+ logger.info('setup view called')
+
+ logger.info('check for GLUE editor group...')
+ try:
+ g = Group.objects.get( name='GLUE EDITORS' )
+ logger.info( "group name='%s' exists" % 'GLUE EDITORS' )
+ except Group.DoesNotExist, e:
+ g = Group( name='GLUE EDITORS' )
+ g.save()
+ logger.info( "group name='%s' created" % 'GLUE EDITORS' )
+ request.user.groups.add( g )
+ logger.info( "staff user name='%s' added to group '%s'" % ( request.user.username, 'GLUE EDITORS' ) )
+
+
+ if len( data['languages'] )< 2:
+ data['warnings']['languages'] = _("not enough languages")
+ logger.warning("not enough languages (at least 2). Check local_settings.py LANGUAGES tuple!")
+ return render_to_response( "walt/index.html", RequestContext(request, data ) )
+
+ if len( data['languages'] ) > 8:
+ data['warnings']['languages'] = _("too many languages")
+ logger.warning("too many languages (max 8). Check local_settings.py LANGUAGES tuple!")
+
+ return render_to_response( "walt/index.html", RequestContext(request, data ) )
+
+ logger.info('check for WALT pages...')
+
+ for slug in WALT_PAGES:
+ for l in data['languages']:
+
+ try:
+ p = Page.objects.get( slug=slug, language=l )
+ logger.info( "slug='%s', language: %s exists" % ( slug,l ) )
+ except Page.DoesNotExist, e :
+ p = Page( title=slug, language=l, slug=slug)
+ p.save()
+ logger.info( "slug='%s', language: %s created" % ( slug, l ) )
+
+ logger.info('setup completed!')
return render_to_response( "walt/index.html", RequestContext(request, data ) )
Please sign in to comment.
Something went wrong with that request. Please try again.