Anonymous avatar Anonymous committed 30b0144

- fixed change title breaks permanent link
- fixed punctuation on title break permanent link
- fixed only admin can edit post
- add mobile interface

Comments (0)

Files changed (24)

Binary file modified.

context/context_processors.py

             
     if settings.BLOG_TITLE != '':
         blog_title = settings.BLOG_TITLE
+            
+    return {'context_pages':context_pages, 'blog_title':blog_title}
+    
+    
+def addon(request):
+    # dont turn on all of this when on development
+    if settings.DEBUG == False:
+        if settings.DISQUS == True:
+            disqus=True
+        else:
+            disqus=False
 
-    if settings.DISQUSS == 'True':
-        discuss=True
+        if settings.ANALYTICS == True:
+            ga=True
+        else:
+            ga=False
+    
+        if settings.FBLIKE == True:
+            fblike=True
+        else:
+            fblike=False
     else:
-        discuss=False
+        disqus = ga = fblike = False
+        
+    return {'disqus':disqus, 'ga':ga, 'fblike':fblike}
+    
+    
 
-    if settings.ANALYTICS == 'True':
-        ga=True
-    else:
-        ga=False
-
-    return {'context_pages':context_pages, 'blog_title':blog_title, 'discuss':discuss, 'ga':ga}
-    
 def daily_quote(request):
     if memcache.get('today_quote'):
         todayquote = memcache.get('today_quote')
 
 
 import urllib
-import logging
 
 from appengine_django.models import BaseModel
 from google.appengine.ext import db
 
 
     def get_absolute_url(self):
-        #domain = Site.objects.get_current()
         return settings.SITE_URL+'/media/serve/%s' % self.key()
 
     def get_download_url(self):
 
 
 import urllib
-import logging
 
 from django.http import HttpResponseRedirect, Http404, HttpResponse
 from django.shortcuts import render_to_response
 from django.conf import settings
+from django.views.decorators.csrf import csrf_exempt
 
 from google.appengine.ext import blobstore
 from google.appengine.api import memcache
 @login_required
 def delMedia(request, key):
     blob_key = str(urllib.unquote(key))
-    logging.info(key)
-    logging.info(blobstore.BlobKey(key))
-    logging.info(blobstore.BlobKey(blob_key))
-
-
     blobstore.delete(blob_key)
     memcache.delete('mediapage-1')
     return HttpResponseRedirect('/media/')
 
 
+@csrf_exempt
 @login_required
 def upload(request):
     form = None
     template = db.StringProperty()
     navbar = db.BooleanProperty()
     publish = db.BooleanProperty()
+    widgets = db.StringListProperty()
     created = db.DateTimeProperty(auto_now_add=True)
+    last_update = db.DateTimeProperty(auto_now=True)
     author = db.UserProperty(auto_current_user_add=True)
 
     def get_absolute_url(self):
-        return "/%s" % self.name
+        return "/%s" % self.key().name()
 
     def get_delete_url(self):
         return "/page/delete/%s" % (self.key())

pages/pageform.py

 #    You should have received a copy of the GNU General Public License
 #    along with MeBlog.  If not, see <http://www.gnu.org/licenses/>.
 
+import os
+
+from django.conf import settings
+from django import forms
+
 import models
-from django import forms
+from widgets.models import Widget
+
+from google.appengine.api import memcache
+
+# this utils used to construct keyname from post or page title by removing unallowed char
+from utilities.utils import construct_keyname
 
 
 class PageForm(forms.Form):
     name = forms.CharField(max_length=100,widget=forms.TextInput(attrs={'class':'textInput'}))
     description = forms.CharField(max_length=300, required=False,widget=forms.TextInput(attrs={'class':'textInput'}))
     body = forms.CharField(widget=forms.Textarea)
-    template = forms.CharField(required=False,max_length=30,widget=forms.TextInput(attrs={'class':'textInput'}))
+    template = forms.ChoiceField()
+    widget = forms.ChoiceField(required=False, widget=forms.SelectMultiple())
     navbar = forms.BooleanField(required=False, widget=forms.Select(choices=(('True','True'),
                                                                              ('False', 'False'))))
     publish = forms.BooleanField(widget=forms.Select(choices=(('Published','Publish Now'),
                                                               ('Private','Private'),
                                                               ('Draft','Draft'))))
 
+    
+    def __init__(self, *args, **kwrds):
+        super(PageForm,self).__init__(*args, **kwrds)
+        
+        # read available templates
+        path = os.path.join(settings.ROOT_PATH,'templates','pages')
+        templates = os.listdir(path)
+        self.fields['template'].choices=[[x,x] for x in templates]
+        
+        # read available widget
+        if memcache.get('widgets_enabled'):
+            widgets = memcache.get('widgets_enabled')
+        else:
+            widgets = Widget.all().filter('enabled =',True)
+            memcache.set('widgets_enabled', widgets)
+        self.fields['widget'].choices = ()
+        for w in widgets:
+            self.fields['widget'].choices.append([str(w.key()), w.title])
+        
+    
     def save(self, page=None, commit=True):
         data = self.cleaned_data
-        if not page: page = models.Page(key_name=data['name'].replace(' ','-'))
+        if not page: page = models.Page(key_name=construct_keyname(data['name']))
         page.name = data['name']
         page.description = data['description']
         page.body = data['body']
         page.publish = data['publish']
         if commit: page.put()
         return page
+        
      
     
     # prevent the same page 's name
 #    You should have received a copy of the GNU General Public License
 #    along with MeBlog.  If not, see <http://www.gnu.org/licenses/>.
 
+# Python module
+import os
+
 # Django module
 from django.shortcuts import render_to_response
-from django.http import HttpResponseRedirect, Http404
+from django.http import HttpResponseRedirect, Http404, HttpResponse
 from django.template import RequestContext
 from django.conf import settings
+from django.core.context_processors import csrf
+
 
 # App module
 from pages import models
 from google.appengine.api import memcache
 from google.appengine.api import mail
 
+from django.template.loader import render_to_string
+import django_mobile 
+from gaesessions import get_current_session
+
 PAGESIZE = settings.PAGESIZE
 
 def render(request, name):
             template = page.template
         else:
             template = 'default.html'
-        return render_to_response('pages/'+template, {'page':page},
+            
+        session = get_current_session()
+        if session.is_active():
+            if request.GET.get('mobile'):
+                session['mobile'] = request.GET.get('mobile');
+
+            if session.has_key('mobile'):
+                if session['mobile'] == 'off':
+                    django_mobile.set_flavour('full');
+        else:
+            session.start()
+        rendered = render_to_string('pages/'+template, {'page':page},
                                                 context_instance=RequestContext(request))
+                                                
+        return HttpResponse(rendered);
     else:
         raise Http404
 
 
 @login_required
 def newPage(request):
+    c = {}
+    c.update(csrf(request))
     pageForm = None
     if request.method == 'POST':
         newPage = PageForm(request.POST)
 
     if pageForm is None:
         pageForm = PageForm()
+        
 
-    return render_to_response('admin/newpage.html', {
-                                                     'pageForm':pageForm})
+    return render_to_response('admin/newpage.html', {'pageForm':pageForm},
+                                                    context_instance=RequestContext(request))
 
 
 @login_required
 def editPage(request, key):
+    c = {}
+    c.update(csrf(request))
     pageForm = None
     if request.method == 'POST':
         form = PageForm(request.POST)
-        page = page = models.Page.get(key)
+        page = models.Page.get(key)
         if form.is_valid():
             form.save(page)
             memcache.flush_all()
                                          'template':page.template,
                                          'publish':page.publish})
     return render_to_response('admin/newpage.html', {'pageForm':pageForm,
-                                                     'action':page.get_edit_url()})
+                                                     'action':page.get_edit_url()},
+                                                     context_instance=RequestContext(request))
 
 @login_required
 def delPage(request, key):
 
 
 def contact(request):
+    c = {}
+    c.update(csrf(request))
     form = None
     msg = None
     if request.method == 'POST':
             form = ContactForm(request.POST)
 
     if form is None: form = ContactForm()
+    
+    session = get_current_session()
+    if session.is_active():
+        if request.GET.get('mobile'):
+            session['mobile'] = request.GET.get('mobile');
 
-    return render_to_response('pages/contact.html', {'form':form, 'msg':msg},
-                                                   context_instance=RequestContext(request))
+        if session.has_key('mobile'):
+            if session['mobile'] == 'off':
+                django_mobile.set_flavour('full');
+    else:
+        session.start()
+
+    rendered =  render_to_string('pages/contact.html', {'form':form, 'msg':msg},
+                                                   context_instance=RequestContext(request))
+    return HttpResponse(rendered)
 from google.appengine.ext import db
 from google.appengine.api import users
 
-# Create your models here.
+from django.utils import text
+
 import datetime
 import markdown
 import re
     category = db.CategoryProperty()
     tags = db.StringListProperty()
     pub_date = db.DateTimeProperty(auto_now_add=True)
+    last_update = db.DateTimeProperty(auto_now=True)
     author = db.UserProperty(auto_current_user_add=True)
 
     def get_absolute_url(self):
         return "/post/%04d/%02d/%02d/%s" % (self.pub_date.year,
                                             self.pub_date.month,
                                             self.pub_date.day,
-                                            self.title.replace(' ','-'))
+                                            self.key().name())
 
     def get_edit_url(self):
         return "/post/edit/%04d/%02d/%02d/%s" % (self.pub_date.year,
         p = re.compile(r'<img.*?>')
         body = p.sub('', self.body_html)
         if len(body) > 500:
-            return body[:500].rsplit(' ', 1)[0]+'...'+'<a href="'+self.get_absolute_url()+'">Read More</a>'
+            return text.truncate_html_words(body, 70)+'<a href="'+self.get_absolute_url()+'">Read More</a>'
         else:
             return body
 

posts/postform.py

 #    You should have received a copy of the GNU General Public License
 #    along with MeBlog.  If not, see <http://www.gnu.org/licenses/>.
 
+
 import models
 from django import forms
 
+# this utils used to construct keyname from post or page title by removing unallowed char
+from utilities.utils import construct_keyname
+
+
 
 class PostForm(forms.Form):
     key = forms.CharField(required=False, widget=forms.HiddenInput())
 
     def save(self, post=None, commit=True):
         data = self.cleaned_data
-        if not post: post = models.Post(key_name=data['title'].replace(' ','-'))
+        if not post: post = models.Post(key_name=construct_keyname(data['title']))
         post.title = data['title']
-        post.body = data['body']
+        post.body = self.data['body']
         post.category = data['category']
         post.tags = data['tags'].split()
         if commit: post.put()
 
 from django.shortcuts import render_to_response
 from django.template import RequestContext
-from django.http import HttpResponseRedirect, Http404
-
+from django.http import HttpResponseRedirect, Http404, HttpResponse
 from django.conf import settings
+from django.core.context_processors import csrf
 
 from google.appengine.api import memcache
 
 from posts import models
-import postform
+from posts import postform
 from utilities.auth_helper import login_required
 
+from django.template.loader import render_to_string
+import django_mobile 
+from gaesessions import get_current_session
+
 PAGESIZE = settings.PAGESIZE
 
 @login_required
   if cat_list:
       for cat in sorted(cat_list):
         sorted_cat_list.append({'category': cat,
-                      'count':cat_list[cat],
-                      'url': '/posts/category/%s' % cat.replace(' ','-'),
-                      })
+                                  'count':cat_list[cat],
+                                  'url': '/posts/category/%s' % cat.replace(' ','-'),
+                                  })
 
 
   # get all tags
   paging = {'prev': page - 1, 'next':p_next}
   # get tag and categories
   cat_tag = get_tag_cat_list()
+  
+  if request.GET.get('mobile'):
+    if request.GET.get('mobile') == 'full':
+        django_mobile.set_flavour('full');
+  
 
-  return render_to_response('front/stream.html', {'posts': posts,
-                            'paging':paging,
-                            'categories': cat_tag['cat_list'],
-                            'tags': cat_tag['tag_list']},
-                                           context_instance=RequestContext(request))
+  session = get_current_session()
+  if session.is_active():
+    if request.GET.get('mobile'):
+        session['mobile'] = request.GET.get('mobile');
+  
+    if session.has_key('mobile'):
+        if session['mobile'] == 'off':
+            django_mobile.set_flavour('full');
+  else:
+    session.start()
+
+  rendered  = render_to_string('front/stream.html', {'posts': posts,
+                                'paging':paging,
+                                'categories': cat_tag['cat_list'],
+                                'tags': cat_tag['tag_list']},
+                                context_instance=RequestContext(request))
+                                
+  return HttpResponse(rendered)
 
 
 
   if post:
     # get tag and categories
     cat_tag = get_tag_cat_list()
+    
+    session = get_current_session()
+    if session.is_active():
+      if request.GET.get('mobile'):
+          session['mobile'] = request.GET.get('mobile');
+  
+      if session.has_key('mobile'):
+          if session['mobile'] == 'off':
+              django_mobile.set_flavour('full');
+    else:
+      session.start()
 
     return render_to_response('front/post.html', {'post': post,
                             'categories': cat_tag['cat_list'],
                             'tags': cat_tag['tag_list']},
-                                           context_instance=RequestContext(request))
+                             context_instance=RequestContext(request))
   else:
     raise Http404
 
 
 @login_required
 def newPost(request):
+  c = {}
+  c.update(csrf(request))
   postForm = None
   if request.method == 'POST':
     newPost = postform.PostForm(request.POST)
 
   if postForm is None:
     postForm = postform.PostForm()
+
   return render_to_response('admin/newpost.html', {
-                          'postForm':postForm})
+                          'postForm':postForm},context_instance=RequestContext(request))
 
 
 
 @login_required
 def editPost(request, year, month, day, key):
+  c = {}
+  c.update(csrf(request))
   if request.method == 'POST':
     post = models.Post.get(key)
     if post:
 
     return render_to_response('admin/newpost.html', {
                              'postForm':editPostForm,
-                             'action':post.get_edit_url(),})
+                             'action':post.get_edit_url()},context_instance=RequestContext(request))
 
 
 

resources/css/admin.css

 body{
-	background-color:#2A378C;
+	background-image:url('/resources/img/small/bg.png');
 	text-shadow: 0px 1px 1px #fff;
 }
 
 	-moz-border-radius:6px;
 	-webkit-border-radius:6px;
 	border-radius:6px;
-	color:white;
+	color:blue;
 	text-shadow:none;
 }
 
 }
 
 table{
-	width: 90%;
+	width: 100%;
 	border-collapse:collapse;
 	margin-left;
 }
 
 table .menu{width:100px;}
 table .date{width:150px;}
+table .medium{width:200px;}
+table .big{width:300px;}
 
 tr.odd td {
 	background:#f7fbff;
 
 .footer, .footer a{
 	margin-top:10px;
-	color:white;
+	color:blue;
 	text-shadow:none;
 }

resources/css/codehilite.css

 table.codehilitetable{margin:0 0 0 20px;}
 .codehilitetable td{background-color:#D7F5E1; padding:5px;}
-.codehilite pre { margin-left: 1em; overflow: auto;  width:100%;padding:5px;}
+.codehilite pre { margin-left: 1em; overflow: auto;  width:90%;padding:5px;background-color:E3E6E4;}
 
 .hll { background-color: #ffffcc }
 .c { color: #408080; font-style: italic } /* Comment */

resources/css/theme.css

 body{
-	background-color:#2A378C;
+    background-image:url('/resources/img/small/bg.png');
 	text-shadow: 0px 1px 1px #fff;
 }
 
 header hgroup, hgroup a{
-    color:white;
     text-shadow:none;
     text-decoration:none;
 }
 
+header hgroup a{
+    color:blue;
+}
+
 #nav {
 	margin-top:0px;
 }
 	-moz-border-radius:6px;
 	-webkit-border-radius:6px;
 	border-radius:6px;
-	color:white;
+	color:blue;
 	text-shadow: none;
 }
 
 	text-decoration:none;
 }
 
-#main-content .date{
-}
-
 #main-content p{
 	margin-top:15px;
 }
 	font-weight:bold;
 }
 
+#main-content .tags{
+    float:right;
+    margin: 0 20px;
+    font-weight:bold;
+}
+
 a.comment-link{
     float:right;
     margin:0 20px;
 }
 
+a.post-tag{
+    background-color:#E0EAF1;
+    border-bottom:1px solid #3E6D8E;
+    border-right:1px solid #7F9FB6;
+    color:#3E6D8E;
+    font-size:90%;
+    line-height:2.4;
+    margin:2px 2px 2px 0;
+    padding:3px 4px;
+    text-decoration:none;
+    white-space:nowrap;
+    cursor:pointer;
+    text-shadow:none;
+}
+
+a.post-tag:hover{
+    background-color:#3E6D8E;
+    border-bottom:1px solid #37607D;
+    border-right:1px solid #37607D;
+    color:#E0EAF1;
+    text-decoration:none;
+}
+
 
 #side-menu{
 	background: rgba(255,255,255,0.7);
 
 .footer, .footer a{
 	margin-top:10px;
-	color:white;
+	color:blue;
 	text-shadow:none;
 }
 
   font: italic 1.4em Georgia, "Times New Roman", Times, serif;
 }
 
-div.content img{
-    width:600px;
+div.content img.big{
+    width:80%;
+}
+div.content img.small{
+    width:40%;
 }
 
 
 import os
 
-DEBUG = False
+if os.environ['SERVER_NAME'] == 'localhost':
+    DEBUG = True
+else:
+    DEBUG = False
+    
 TEMPLATE_DEBUG = DEBUG
 
 ROOT_PATH = os.path.dirname(__file__)
 
 # List of callables that know how to import templates from various sources.
 TEMPLATE_LOADERS = (
+    'django_mobile.loader.Loader',
     'django.template.loaders.filesystem.load_template_source',
     'django.template.loaders.app_directories.load_template_source',
 #     'django.template.loaders.eggs.load_template_source',
     'django.middleware.common.CommonMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'google.appengine.ext.appstats.recording.AppStatsDjangoMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django_mobile.middleware.MobileDetectionMiddleware',
+    'django_mobile.middleware.SetFlavourMiddleware',
+    'gaesessions.DjangoSessionMiddleware',
 #    'django.contrib.auth.middleware.AuthenticationMiddleware',
 #    'django.middleware.doc.XViewMiddleware',
 )
 
 TEMPLATE_CONTEXT_PROCESSORS = (
-#   'django.core.context_processors.auth',
     'django.core.context_processors.debug',
     'django.core.context_processors.i18n',
 
     # context processor to get all pages
     'context.context_processors.pages',
     
+    # get addon settings
+    'context.context_processors.addon',
+    
     # get daily quote 
     'context.context_processors.daily_quote',
+    
+    # get mobile context
+    'django_mobile.context_processors.flavour',
 
-#    'django.core.context_processors.media',  # 0.97 only.
-#    'django.core.context_processors.request',
 )
 
 ROOT_URLCONF = 'urls'
 )
 
 INSTALLED_APPS = (
+     # External Packages
      'appengine_django',
+     'django_mobile',
+     'markdown',
+     'pygments',
+     'gaesessions',
+     
+     # Meblog Packages
 	 'posts',
      'pages',
      'context',
-     'markdown',
-     'pygments',
      'utilities',
 )
 
 PAGESIZE = 10                                       # This is how many posts will show on home page
 
 # Extension
-DISQUSS = 'False'      #Disquss is a comment system for blog.  http://disqus.com
+DISQUSS = 'True'      #Disquss is a comment system for blog.  http://disqus.com
 ANALYTICS = 'False'    #Google analytics integration
-FBLIKE = 'False'       #Facebook Like Button. Set this to True will enable fblike automatically on every post. No additional action required.
+FBLIKE = 'True'       #Facebook Like Button. Set this to True will enable fblike automatically on every post. No additional action required.
 

templates/admin/header.html

 			<li class="top"><a href="/media/">Media</a></li>
 			<li class="item"><a href="/media/upload/">Upload</a></li>
 		</ul>
+		<ul>
+			<li class="top"><a href="/widgets/">Widgets</a></li>
+			<li class="item"><a href="/widget/new/">New Widget</a></li>
+		</ul>
 	</div>
 </div>
 </div>

templates/admin/medialist.html

 		<thead>
 			<tr>
 				<th class="first menu">Action</th>
-				<th>Title</th>
+				<th class="medium">Title</th>
 				<th>Filename</th>
-				<th>Url</th>
+				<th class="big">Url</th>
 				<th class="last date">Created</th>
 			</tr>
 		</thead>

templates/admin/newpage.html

 {% extends 'admin/base.html' %}
 
 {% block content %}
-<form class="uniform" method="POST" action="{% if action %}{{ action }}{% else %}/page/new/{% endif %}">
+<form class="uniform" method="POST" action="{% if action %}{{ action }}{% else %}/page/new/{% endif %}">{% csrf_token %}
 {% if pageForm.key %}{{ pageForm.key }}{% endif %}
 <fieldset>
 <div class="left-form">
 		<label for="id_navbar" style="display:block">Side Bar {{ pageForm.navbar.errors }}</label>
 		{{ pageForm.navbar }}
 	</div>
+    <div class="ctrlHolder">
+		<label for="id_widget" style="display:block">Widget{{ pageForm.navbar.errors }}</label>
+		{{ pageForm.widget }}
+        <span class="inlineLabels"><p class="formHint">Use Ctrl to select more than 1 widget</p></span>
+	</div>
 	<div class="ctrlHolder">
 		<label for="id_template" style="display:block">Template {{ pageForm.template.errors }}</label>
         {{ pageForm.template }}

templates/admin/newpost.html

 
 {% block content %}
 <form class="uniform" method="POST" action="{% if action %}{{ action }}{% else %}/post/new/{% endif %}">
+{% csrf_token %}
 {% if postForm.key %}{{ postForm.key }}{% endif %}
 <fieldset>
 <div class="left-form">

templates/admin/postlist.html

 				</tr>
 			{% endfor %}
 		{% else %}
-			<tr><td colspan="3" style="text-align:left;font-size:15">No Post</td></tr>
+			<tr><td colspan="5" style="text-align:left;font-size:15">No Post</td></tr>
 		{% endif %}
 		</tbody>
 	</table>

templates/admin/upload.html

 
 {% block content %}
 <div style="width:420px">
-	<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">
+	<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">{% csrf_token %}
 	{% if upload_error %}<span>{{ upload_error }}</span>{% endif %}
 
 	{{ form.as_p }}

templates/front/footer.html

 </div>
 
 <!-- Disquss -->
-{% if discuss %}
-<!-- Put Disquss 'count.js' Script Here. -->
+{% if disqus %}
+<script type="text/javascript">
+var disqus_shortname = 'hudarsonosblog';
+(function () {
+  var s = document.createElement('script'); s.async = true;
+  s.src = 'http://disqus.com/forums/hudarsonosblog/count.js';
+  (document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
+}());
+</script>
+
 {% endif %}
 
 <!-- Google Analytics -->
 {% if ga %}
-<!-- Put Google Analytics Script Here. -->
+<script type="text/javascript">
+
+  var _gaq = _gaq || [];
+  _gaq.push(['_setAccount', 'UA-6599473-6']);
+  _gaq.push(['_trackPageview']);
+
+  (function() {
+    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+  })();
+
+</script>
 {% endif %}

templates/front/post.html

 
 {% block main_content %}
 	<h3 class="title">{{ post.title}}</h3>
-	<span class="date">Writen at {{ post.pub_date.year }}-{{ post.pub_date.month }}-{{ post.pub_date.day }}</span>
+	<span class="date">last updated at {{ post.last_update.year }}-{{ post.last_update.month }}-{{ post.last_update.day }}</span>
+    <span class="tags">tags: &nbsp;
+        {% for t in post.tags %}
+            <a class="post-tag" href="/posts/tag/{{ t }}">{{ t }}</a>
+        {% endfor %}
+    </span>
 	<p>
 		{% autoescape off %}
 		{{ post.body_html|safe }}
 		{% endautoescape %}
 	</p>
-	<div class="clear"  style="height:50"></div>
+    <div class="clear"  style="height:50"></div>
     {% if fblike %}
     <script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="{{ post.get_absolute_url }}"></fb:like>
     {% endif %}
     
-	{% if discuss %}
-	<!-- Put Disquss Script Here. -->
+	{% if disqus %}
+	<div id="disqus_thread"></div>
+    <script type="text/javascript">
+      /**
+        * var disqus_identifier; [Optional but recommended: Define a unique identifier (e.g. post id or slug) for this thread] 
+        */
+      (function() {
+       var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
+       dsq.src = 'http://hudarsonosblog.disqus.com/embed.js';
+       (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
+      })();
+    </script>
+    <noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript=hudarsonosblog">comments powered by Disqus.</a></noscript>
+    <a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>
 	{% endif %}
+    
 {% endblock %}
 
 

templates/front/stream.html

 {% if posts %}
 {% for p in posts %}
 	<h3 class="title"><a href="{{ p.get_absolute_url }}">{{ p.title}}</a></h3>
-	<span class="date">Writen at {{ p.pub_date.year }}-{{ p.pub_date.month }}-{{ p.pub_date.day }} by {{ p.author.nickname }}</span>
+	<span class="date">last updated at {{ p.last_update.year }}-{{ p.last_update.month }}-{{ p.last_update.day }} by {{ p.author.nickname }}</span>
+    <span class="tags">tags: &nbsp;
+        {% for t in p.tags %}
+            <a class="post-tag" href="/posts/tag/{{ t }}">{{ t }}</a>
+        {% endfor %}
+    </span>
 	<p>
 		{% autoescape off %}
 		{{ p.trunc_body }}
     <script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="{{ p.get_absolute_url }}" layout="button_count"></fb:like>	
     {% endif %}
     
-    {% if discuss %}
+    {% if disqus %}
     <a class="comment-link" href="{{ p.get_absolute_url }}#disqus_thread">Comments</a>
 	{% endif %}
     
+    <hr style="color:white">
     <div class="clear"></div>
 {% endfor %}
 
 <span class="side-title">Subscribe</span>
 <div class="nav-cat">
 	<ul>
-		<li><a href="/feeds/latest/"><img src="/resources/img/small/rssfeed.jpg"</a></li>
+		<li><a href="/feeds/latest/rss"><img src="/resources/img/small/rssfeed.jpg"</a>
+			<a href="/feeds/latest/atom"><img src="/resources/img/small/atomfeed.gif"></a></li>
 	</ul>
 </div>
 </div>

templates/pages/contact.html

 
 {% block main_content %}
 <div style="width:400px">
-	<form action="/contact/" method="POST">
+	<form action="/contact/" method="POST">{% csrf_token %}
 		<fieldset>
 			<div class="ctrlHolder">
 				<label for="id_name" style="display:block">Name {{ form.name.errors }}</label>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.