Vladimir Mihailenco avatar Vladimir Mihailenco committed a14fffe

Fixes

Comments (0)

Files changed (15)

-#!/usr/bin/python
+#!/usr/bin/env python
+
 import sys, os
 from os.path import dirname
 sys.path.append(dirname(os.path.realpath(__file__)))

mcblog/__models.py

-import datetime
-
-from django.db import models
-from django.contrib.auth.models import User
-
-from markdown import markdown
-from mcblog.decorators import memoized
-
-class Category(models.Model):
-    title = models.CharField(max_length=250, help_text='Maximum 250 characters.')
-    slug = models.SlugField(unique=True,
-                            help_text='Suggested value automatically generated from title. Must be unique.')
-    description = models.TextField()
-
-    class Meta:
-        ordering = ['title']
-        verbose_name_plural = 'Categories'
-
-    @models.permalink
-    def get_absolute_url(self):
-        return ('mcblog-category-detail', (), {'slug': self.slug})
-
-    def live_entry_set(self):
-        return self.entry_set.filter(status=Entry.STATUS_LIVE)
-    
-    def __unicode__(self):
-        return self.title
-
-from taggit.managers import TaggableManager
-import pickle
-
-class LiveEntryManager(models.Manager):
-    def get_query_set(self):
-        return super(LiveEntryManager, self).get_query_set().filter(status=self.model.STATUS_LIVE)
-
-class Entry(models.Model):
-    STATUS_LIVE = 1
-    STATUS_DRAFT = 2
-    STATUS_HIDDEN = 3
-    STATUS_CHOICES = (
-        (STATUS_LIVE, 'Live'),
-        (STATUS_DRAFT, 'Draft'),
-        (STATUS_HIDDEN, 'Hidden'),
-    )
-
-    title = models.CharField(max_length=250, help_text='Maximum 250 characters.')
-    excerpt = models.TextField(blank=True)
-    body = models.TextField()
-
-    excerpt_html = models.TextField(blank=True, editable=False)
-    body_html = models.TextField(blank=True, editable=False)
-
-    slug = models.SlugField(unique_for_date='pub_date',
-                            help_text='Suggested value automatically generated from title. Must be unique.')
-    pub_date = models.DateTimeField(default=datetime.datetime.now)
-    author = models.ForeignKey(User, editable=False)
-    enable_comments = models.BooleanField(default=True)
-    featured = models.BooleanField(default=False)
-    status = models.IntegerField(choices=STATUS_CHOICES, default=STATUS_LIVE)
-
-    category = models.ForeignKey(Category)
-    tags = TaggableManager()
-    tags_cache = models.CharField(max_length=250, editable=False)
-
-    live = LiveEntryManager()
-    objects = models.Manager()
-
-    @memoized
-    def tags_list(self):
-        from django.utils.encoding import smart_str
-        tags = pickle.loads(smart_str(self.tags_cache))
-        return tags
-
-    class Meta:
-        ordering = ['-pub_date']
-        verbose_name_plural = 'Entries'
-
-    def save(self, force_insert=False, force_update=False, using=None, data_changed=True):
-        if data_changed:
-            self.body_html = markdown(self.body)
-            if self.excerpt:
-                self.excerpt_html = markdown(self.excerpt)
-        return super(Entry, self).save(force_insert, force_update, using)
-
-    @models.permalink
-    def get_absolute_url(self):
-        return ('mcblog-entry-detail', (), {'category_slug': self.category.slug,
-                                            'slug': self.slug})
-
-    @models.permalink
-    def get_arhive_year_url(self):
-        return ('mcblog-entry-archive-year', (), {'year': self.pub_date.strftime('%Y')})
-
-    @models.permalink
-    def get_arhive_month_url(self):
-        return ('mcblog-entry-archive-month', (), {'year': self.pub_date.strftime('%Y'),
-                                                  'month': self.pub_date.strftime('%b').lower()})
-
-    @models.permalink
-    def get_arhive_day_url(self):
-        return ('mcblog-entry-archive-day', (), {'year': self.pub_date.strftime('%Y'),
-                                                  'month': self.pub_date.strftime('%b').lower(),
-                                                  'day': self.pub_date.strftime('%d')})
-
-    def __unicode__(self):
-        return self.title
-
-class Link(models.Model):
-    title = models.CharField(max_length=250)
-    description = models.TextField()
-    url = models.URLField(unique=True)
-    via_name = models.CharField('Via', blank=True, max_length=250,
-                                help_text='The name of the person whose site you spotted the link on. Optional.')
-    via_url = models.URLField('Via URL', blank=True,
-                              help_text='The url of the site where you spotted the link. Optional.')
-
-    description_html = models.TextField(editable=False)
-
-    slug = models.SlugField(unique_for_date='pub_date',
-                            help_text='Suggested value automatically generated from title. Must be unique.')
-    pub_date = models.DateTimeField(default=datetime.datetime.now)
-    posted_by = models.ForeignKey(User, editable=False)
-    enable_comments = models.BooleanField(default=True)
-
-    tags = TaggableManager()
-    tags_cache = models.CharField(max_length=250, editable=False)
-
-    @memoized
-    def tags_list(self):
-        from django.utils.encoding import smart_str
-        tags = pickle.loads(smart_str(self.tags_cache))
-        return tags
-
-    class Meta:
-        ordering = ['-pub_date']
-
-    def save(self, force_insert=False, force_update=False, using=None, data_changed=True):
-        if data_changed:
-            self.description_html = markdown(self.description)
-        return super(Link, self).save(force_insert, force_update, using)
-
-    @models.permalink
-    def get_absolute_url(self):
-        return ('mcblog-link-detail', (), {'year': self.pub_date.strftime('%Y'),
-                                           'month': self.pub_date.strftime('%b').lower(),
-                                           'day': self.pub_date.strftime('%d'),
-                                           'slug': self.slug})
-
-    def __unicode__(self):
-        return self.title
-
-from django.conf import settings
-from django.contrib.comments.moderation import CommentModerator, moderator
-from django.contrib.sites.models import Site
-from akismet import Akismet
-
-class EntryModerator(CommentModerator):
-    auto_moderate_field = 'pub_date'
-    moderate_after = 30
-    email_notification = True
-    
-    def moderate(self, comment, content_object, request):
-        already_moderated = super(EntryModerator, self).moderate(comment, content_object, request)
-        if already_moderated:
-            return already_moderated
-        akismet_api = Akismet(key=settings.AKISMET_API_KEY,
-                              blog_url='http://%s/' % Site.objects.get_current().domain)
-        if akismet_api.verify_key():
-            akismet_data = {'comment_type': 'comment',
-                            'referrer': request.META['HTTP_REFERER'],
-                            'user_ip': comment.ip_address,
-                            'user_agent': request.META['HTTP_USER_AGENT']}
-            return akismet_api.comment_check(comment, akismet_data, build_data=True)
-        return False
-
-moderator.register(Entry, EntryModerator)

mcblog/context_processors/__init__.py

+def base_url(request):
+    context_extras = {}
+    context_extras['base_url'] = request.build_absolute_uri('/')[:-1]
+    return context_extras
 from django.contrib.syndication.views import Feed
 from django.contrib.sites.models import Site
+from django.core.urlresolvers import reverse
+
 from mcblog.models import Entry
 
+
 current_site = Site.objects.get_current()
 
+
 class LatestEntriesFeed(Feed):
-    title = '%s: Latest entries' % current_site.domain
-    link = '/feeds/entries/'
+    title = '%s: Latest entries' % current_site.name
     description = 'Latest entries'
 
+    def link(self):
+        return reverse('mcblog-entry-list')
+
     def items(self):
         return Entry.live.order_by('-pub_date')[:10]
 
                                  item.get_absolute_url())
 
     def item_categories(self, item):
-        return [c.title for c in item.category.title]
+        return [item.category]

mcblog/mcomments/templates/comments/comment_notification_email.txt

-Tratata
+{% load context_tags %}
+
+A comment has been posted on {{ content_object }}.
+
+{% base_url %}{{ content_object.get_absolute_url }}
+
+The comment reads as follows:
+
+{{ comment }}
 import datetime
-import pickle
 
 from django.db import models
 from django.contrib.auth.models import User
+from django.core.urlresolvers import reverse
 from django.template.defaultfilters import slugify
 
+from middleware.common import get_request
+
 from markdown import markdown
 from mctaggit.managers import TaggableField
 
+
 class Category(models.Model):
     title = models.CharField(max_length=250, help_text='Maximum 250 characters.')
     slug = models.SlugField(unique=True,
             self.slug = slugify(self.title)
         return super(Category, self).save(force_insert, force_update, using)
 
-
-    @models.permalink
     def get_absolute_url(self):
-        return ('mcblog-category-detail', (), {'slug': self.slug})
+        return reverse('mcblog-category-detail', kwargs={'slug': self.slug})
 
     def live_entry_set(self):
         return self.entry_set.filter(status=Entry.STATUS_LIVE)
-    
+
     def __unicode__(self):
         return self.title
 
     def __unicode__(self):
         return self.title
 
+
 class Link(models.Model):
     title = models.CharField(max_length=250)
     description = models.TextField()
     def __unicode__(self):
         return self.title
 
+
 from django.conf import settings
 from django.contrib.comments.moderation import CommentModerator, moderator
 from django.contrib.sites.models import Site
 from akismet import Akismet
 
+
 class EntryModerator(CommentModerator):
     auto_moderate_field = 'pub_date'
     moderate_after = 30
     email_notification = True
-    
+
     def moderate(self, comment, content_object, request):
         already_moderated = super(EntryModerator, self).moderate(comment, content_object, request)
         if already_moderated:

mcblog/templates/mcblog/entry_list.html

 {% extends 'mcblog/base.html' %}
 
 {% block extrahead %}
-<link href="{% url mcblog-entry-feed %}" rel="alternate" type="application/rss+xml" title="Фриланс разработка" />
+<link href="http://feeds.feedburner.com/loutontheweb/" rel="alternate" type="application/rss+xml" title="Latest blog entries" />
 {% endblock extrahead %}
 
 {% block title %}loutontheweb{% endblock %}

mcblog/templatetags/context_tags.py

+from django.template import Library
+from django.contrib.sites.models import Site
+
+
+register = Library()
+
+
+@register.simple_tag
+def base_url():
+    base_url = 'http://%s' % Site.objects.get_current().domain
+    return base_url

mcblog/urls/entries.py

 from mcblog.models import Entry
 from mcblog.feeds import LatestEntriesFeed
 
+
 entry_info = {'queryset': Entry.objects.select_related().all()}
 entry_date_based_info = dict(entry_info, date_field='pub_date')
 

middleware/common.py

 from django.utils.thread_support import currentThread
 
+
 _requests = {}
 
+
 def get_request():
     return _requests[currentThread()]
 
+
 class GlobalRequestMiddleware(object):
     def process_request(self, request):
         _requests[currentThread()] = request

public/site_media/css/global.css

 }
 
 small {
-  ffont-size: 8pt;
+  font-size: 8pt;
 }
 
 .breadcrumbs {

public/site_media/css/layout.css

 
 .footer {
   clear: both;
+  width: 636px;
+  position: relative;
+}
+.copyright {
+  float: left;
+}
+.validators {
+  float: right;
+  padding: 20px 4px;
 }

public/site_media/css/screen.css

-@import url("/site_media/css/reset.css");
-@import url("/site_media/css/global.css");
-@import url("/site_media/css/layout.css");
-@import url("/site_media/css/content.css");
-@import url("/site_media/css/flash.css");
-@import url("/site_media/css/form.css");
-@import url("/site_media/css/menu.css");
-@import url("/site_media/css/navigation.css");
-@import url("/site_media/css/table.css");
-@import url("/site_media/css/tag-cloud.css");

templates/base.html

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head>
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
     <title>{% block title %}Main page{% endblock %}</title>
     {% compress css %}
     <link href="{{ MEDIA_URL }}css/reset.css" media="screen" rel="stylesheet" />
     <div class="wrapper">
 
       <ul class="breadcrumbs">
-        {% block breadcrumbs %}{% endblock %}
+        {% block breadcrumbs %}<li></li>{% endblock %}
       </ul>
 
       <div class="navigation">
             {% mailto 'vladimir.webdev@gmail.com' %}
           </p>
         </div>
+        <div class="validators">
+          <p>
+            <a href="http://validator.w3.org/check?uri=referer"><img
+                src="http://www.w3.org/Icons/valid-xhtml10"
+                alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
+          </p>
+        </div>
       </div><!-- footer -->
 
     </div><!-- wrapper -->
     {% endblock body %}
 
-<script>
+<script type="text/javascript">
   var _gaq = _gaq || [];
   _gaq.push(['_setAccount', 'UA-11116121-1']);
   _gaq.push(['_trackPageview']);

templates/profile.html

 {% mailto 'vladimir.webdev@gmail.com' %}<br />
 Skype: vlmich, ICQ: 9044735<br />
 Languages: Russian (first), English (fluent written, basic verbal)<br />
-<a href="http://stackoverflow.com/users/268774/vladimir">stackoverflow profile</a><br />
-<a href="http://www.odesk.com/users/~~1834eb531aff2a49">odesk profile</a><br />
+<a href="http://stackoverflow.com/users/268774/vladimir">stackoverflow</a>,
+<a href="http://www.odesk.com/users/~~1834eb531aff2a49">odesk</a>,
+<a href="http://bitbucket.org/vladimir_webdev/">bitbucket</a>,
+<a href="http://github.com/vladimir-webdev/">github</a><br />
 </p>
 
-<h2>Skills</h2>
+<h2 id="skills">Skills, experience</h2>
 
 <ul>
-  <li>Python;</li>
-  <li>Django;</li>
-  <li>SQL, MySQL;</li>
-  <li>JavaScript, jQuery/UI;</li>
+  <li>Python (2 years);</li>
+  <li>Django, Flask, Pylons (1 year);</li>
+  <li>SQL, MySQL, PostgreSQL (2 years);</li>
+  <li>JavaScript, jQuery/UI (2 years);</li>
   <li>HTML, CSS;</li>
   <li>SVN, Mercurial, Git;</li>
+  <li>Google App Engine, djangoappengine;</li>
   <li>PHP, Zend Framework, Symfony (not interested more).</li>
 </ul>
 
-<h2>Source code (Python, Django)</h2>
+<h2 id="projects">Projects (with source code available at top)</h2>
 
 <ul>
-  <li><a href="https://bitbucket.org/vladimir_webdev/manage-youtube/src">YouTube manager</a>, <a href="http://manageyoutube.appspot.com/">demo</a> (Django, gdata-python-client, Google App Engine);</li>
-  <li><a href="http://bitbucket.org/vladimir_webdev/loutontheweb.co.cc/src">This blog</a> (<a href="http://bitbucket.org/vladimir_webdev/loutontheweb.co.cc/src/tip/requirements.txt">requirements</a>);</li>
-  <li><a href="http://bitbucket.org/vladimir_webdev/sortmusic/src/tip/sortmusic.py">Script for sorting music</a>.</li>
+  <li>
+    <a href="http://manageyoutube.appspot.com/playlists/view/vladimirwebdev/favorites/">YouTube manager</a>,
+    <a href="https://bitbucket.org/vladimir_webdev/ytmanager/src">sources</a>
+    - allows retrieving, managing and playing your playlists on one page
+    (Django, gdata-python-client, Google App Engine).
+  </li>
+  <li>
+    <a href="http://needfeeder.appspot.com/">Instant CDN on Google App Engine</a>,
+    <a href="http://bitbucket.org/vladimir_webdev/appengine-cdn/src">sources</a>
+    - this web service will retrieve the resource located on your server, cache it on Google App Engine servers and serve it to your users with smart cache headers
+    (Flask, werzeug, jinja2, Google App Engine).
+  </li>
+  <li>
+    <a href="http://loutontheweb.co.cc/">Blog</a>,
+    <a href="http://bitbucket.org/vladimir_webdev/loutontheweb.co.cc/src">sources</a>
+    - posts, links, feeds (<a href="http://bitbucket.org/vladimir_webdev/loutontheweb.co.cc/src/tip/requirements.txt">pip-req.txt</a>).
+  </li>
+  <li>
+    <a href="http://bitbucket.org/vladimir_webdev/sortmusic/src/tip/sortmusic.py">sortmusic.py</a>
+    - simple Python script for sorting music.
+  </li>
+  <li>
+    <a href="http://openid-oauth-consumer.appspot.com/">OpenID and OAuth consumer</a>
+    - OpenID (Google, Yahoo) and OAuth (Facebook Connect) consumer for Google App Engine
+    (Flask, werzeug, jinja2, Google App Engine).
+  </li>
+  <li>
+    <a href="http://answersvbs.com/">AnswersVBS</a>
+    - Django programming of several apps for AnswersVBS;
+  </li>
+  <li>
+    <a href="http://www.open-e.com/">OPEN-E</a>
+    - CMS built with Django using reusable apps;
+  </li>
+  <li>...several more done working at <a href="http://onlymega.com/">OnlyMega LLC</a> (Moldova, Chisinau) for about 1 year.</li>
 </ul>
 
-<h2>Outdated sources (PHP, Zend Framework)</h2>
+<h2 id="php">Outdated sources (PHP, Zend Framework)</h2>
 
 <ul>
   <li><a href="http://bitbucket.org/vladimir_webdev/zf-form-builder/src">Form Builder based on YAML config</a> (Zend Framework, Doctrine);</li>
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.