Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added blog application

  • Loading branch information...
commit e4ee22e314658bc0b582280f583b2eb0d7ad94c0 1 parent 1fe1f58
Fatih Erikli authored
4 conf/requirements.pip
View
@@ -9,4 +9,6 @@ django-debug-toolbar==0.9.4
nltk==2.0.3
numpy==1.6.2
south==0.7.6
-lettuce==0.2.12
+lettuce==0.2.12
+django-markitup==1.0.0
+markdown==2.2.0
0  web/dbpatterns/blog/__init__.py
View
No changes.
25 web/dbpatterns/blog/admin.py
View
@@ -0,0 +1,25 @@
+from django.contrib import admin
+from django.utils.translation import ugettext_lazy as _
+
+from blog.models import Post
+
+
+class PostAdmin(admin.ModelAdmin):
+ list_display = ["title", "slug", "is_published"]
+ list_filter = ["is_published"]
+ search_fields = ["title", "slug", "content"]
+ actions = ["publish", "mark_as_draft"]
+ prepopulated_fields = {
+ "slug": ("title", )
+ }
+
+ def publish(self, request, qs):
+ qs.update(is_published=True)
+ publish.short_description = _("Publish selected posts")
+
+ def mark_as_draft(self, request, qs):
+ qs.update(is_published=False)
+ mark_as_draft.short_description = _("Mark as draft selected posts")
+
+
+admin.site.register(Post, PostAdmin)
37 web/dbpatterns/blog/models.py
View
@@ -0,0 +1,37 @@
+from django.db import models
+from django.utils.encoding import smart_unicode
+from django.utils.translation import ugettext_lazy as _
+
+from markitup.fields import MarkupField
+
+class PublishedManager(models.Manager):
+ """
+ Returns published blog posts.
+ """
+ def get_query_set(self):
+ return super(PublishedManager, self).get_query_set()\
+ .filter(is_published=True)
+
+class Post(models.Model):
+ """
+ Holds blog post data.
+ """
+ title = models.CharField(_("Name"), max_length=255)
+ slug = models.SlugField(_("Slug"), max_length=255, unique=True)
+ content = MarkupField(_("Content"))
+ date_created = models.DateTimeField(auto_now_add=True)
+ date_modified = models.DateTimeField(auto_now=True, auto_now_add=True)
+ is_published = models.BooleanField(_("Published"), default=True)
+
+ objects = models.Manager()
+ published_objects = PublishedManager()
+
+ class Meta:
+ ordering = ("-date_created", )
+
+ def __unicode__(self):
+ return smart_unicode(self.title)
+
+ @models.permalink
+ def get_absolute_url(self):
+ return "blog_detail", [self.slug]
14 web/dbpatterns/blog/sitemaps.py
View
@@ -0,0 +1,14 @@
+from django.contrib.sitemaps import Sitemap
+
+from blog.models import Post
+
+
+class BlogSitemap(Sitemap):
+ changefreq = "never"
+ priority = 0.9
+
+ def items(self):
+ return Post.published_objects.all()
+
+ def lastmod(self, obj):
+ return obj.date_modified
26 web/dbpatterns/blog/urls.py
View
@@ -0,0 +1,26 @@
+from django.conf.urls import patterns, url
+
+from blog.sitemaps import BlogSitemap
+from blog.views import BlogDetailView, BlogIndexView, \
+ BlogPostsRssFeed, BlogPostsAtomFeed
+
+
+urlpatterns = patterns('',
+
+ # blog urls
+ url(r'^$', BlogIndexView.as_view(), name="blog"),
+ url(r'^(?P<slug>[-\w]+)/$', BlogDetailView.as_view(), name="blog_detail"),
+
+ # rss & atom feed
+ url(r'^feed/rss$', BlogPostsRssFeed(), name="blog_rss_feed"),
+ url(r'^feed/atom', BlogPostsAtomFeed(), name="blog_atom_feed"),
+
+ # sitemap
+ url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap',
+ {'sitemaps': {
+ "blog": BlogSitemap()
+ }}, name="blog_sitemap"),
+
+)
+
+
46 web/dbpatterns/blog/views.py
View
@@ -0,0 +1,46 @@
+from django.conf import settings
+from django.contrib.syndication.views import Feed
+from django.utils.feedgenerator import Atom1Feed
+from django.views.generic import ListView
+from django.views.generic.detail import DetailView
+
+from blog.models import Post
+
+
+class BlogIndexView(ListView):
+ template_name="blog/index.html"
+ queryset = Post.published_objects.all()
+ context_object_name = "posts"
+ paginate_by = 30
+
+class BlogDetailView(DetailView):
+ template_name= "blog/detail.html"
+ model = Post
+ context_object_name = "post"
+
+ def get_queryset(self):
+ if self.request.user.is_superuser:
+ return self.model.objects.all()
+ return self.model.published_objects.all()
+
+class BlogPostsRssFeed(Feed):
+ title = settings.BLOG_FEED_TITLE
+ link = settings.BLOG_URL
+ description = settings.BLOG_FEED_DESCRIPTION
+
+ def items(self):
+ return Post.objects.all()[:20]
+
+ def item_description(self, post):
+ return post.content
+
+ def item_pubdate(self, post):
+ return post.date_created
+
+ def item_categories(self, post):
+ return [tag.name for tag in post.tags.all()]
+
+
+class BlogPostsAtomFeed(BlogPostsRssFeed):
+ feed_type = Atom1Feed
+ subtitle = settings.BLOG_FEED_DESCRIPTION
11 web/dbpatterns/dbpatterns/settings.py
View
@@ -118,6 +118,7 @@
'profiles',
'newsfeed',
'notifications',
+ 'blog',
)
TEMPLATE_CONTEXT_PROCESSORS = (
@@ -222,10 +223,18 @@
}
# Testing
-
LETTUCE_SERVER_PORT = 7000
SOUTH_TESTS_MIGRATE = False
+# Markitup Settings
+MARKITUP_SET = 'markitup/sets/markdown'
+MARKITUP_FILTER = ('markdown.markdown', {'safe_mode': False})
+
+# Blog Settings
+BLOG_FEED_TITLE = "Dbpatterns Blog"
+BLOG_FEED_DESCRIPTION = "News about dbpatterns"
+BLOG_URL = "http://dbpatterns.com/blog/"
+
try:
from settings_local import *
except ImportError:
116 web/dbpatterns/dbpatterns/static/css/screen.css
View
@@ -1628,6 +1628,122 @@ article.tabs section {
}
+/* News */
+
+ul.news {
+ background-color: rgba(95, 245, 227, 0.22);
+ padding: 10px 10px;
+ font-size: 17px;
+}
+ .news li {
+ list-style-type: none;
+ }
+
+/* Blog */
+
+article.post {
+ margin-top: 20px;
+ padding-top: 10px;
+}
+
+ article.post aside {
+ overflow: hidden;
+ }
+
+ article.post time {
+ font-size: 25px;
+ color: #fff;
+ letter-spacing: -1px;
+ background-color: #86e497;
+ padding: 4px 10px;
+ float: left;
+ }
+
+ article.post h3 {
+ margin: -5px 0 0;
+ font-size: 35px;
+ letter-spacing: -1px;
+ background-color: #f6f6f6;
+ padding: 3px 20px;
+ display: inline-block;
+
+ }
+
+ article.post h3 a {
+ color: #5b5b5b;
+ text-decoration: none;
+ }
+
+ article.post section {
+ font-size: 20px;
+ width: 550px;
+ background-color: white;
+ padding: 0 10px;
+ margin: 0;
+
+ }
+
+ article.post section p {
+ padding: 20px 20px 10px 10px;
+ margin: 0;
+ color: #717171;
+ line-height: 28px;
+ word-spacing: -0.05em;
+ font-size: 16px;
+ }
+
+ article.comments {
+ margin-top: 20px;
+ background-color: white;
+ padding: 15px 10px;
+
+ }
+
+/* Donation */
+
+aside.donation {
+ position: absolute;
+ width: 250px;
+ padding: 20px 20px 14px;
+ background-color: white;
+ margin-left: 620px;
+ margin-top: 170px;
+ border: 3px solid #f6f6f6;
+ line-height: 23px;
+}
+
+ aside.donation h3 {
+ display: inline-block;
+ margin: -10px 0 0 0;
+ padding: 3px 2px;
+ color: #5b5b5b;
+ font-weight: bold;
+ }
+
+ aside.donation p {
+ margin: 0;
+ padding: 4px;
+ color: gray;
+ }
+
+ aside.donation form {
+ margin: 0;
+ padding: 3px;
+ }
+
+ aside.donation .donate {
+ background-color: #86e497;
+ border: none;
+ padding: 5px 10px;
+ float: right;
+ margin-top: -10px;
+ }
+
+ aside.donation .donate:hover {
+ cursor: pointer;
+ box-shadow: 0 0 10px #d3d3d3;
+ background-color: #717171;
+ }
/* jsPlumb */
2  web/dbpatterns/dbpatterns/templates/base.html
View
@@ -1,7 +1,7 @@
{% load gravatar_tags %}<!DOCTYPE html>
<html lang="en">
<head>
- <title>dbpatterns - create, share, explore database patterns</title>
+ <title>{% block title %}dbpatterns - create, share, explore database patterns{% endblock %}</title>
{% load compress %}
{% compress css %}
<link rel="stylesheet" href="{{ STATIC_URL }}css/h5bp.css" />
3  web/dbpatterns/dbpatterns/templates/blog/base.html
View
@@ -0,0 +1,3 @@
+{% extends "base.html" %}
+
+{% block footer %}{% endblock %}
27 web/dbpatterns/dbpatterns/templates/blog/detail.html
View
@@ -0,0 +1,27 @@
+{% extends 'blog/base.html' %}
+
+{% block title %}{{ post.title }}{% endblock %}
+
+{% block content %}
+ <section class="content">
+ {% include "blog/donation.html" %}
+ {% include "blog/post.html" %}
+ <article class="comments">
+ <section>
+ <div id="disqus_thread"></div>
+ <script type="text/javascript">
+ var disqus_shortname = 'dbpatterns';
+ (function() {
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
+ dsq.src = 'http://' + disqus_shortname + '.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">comments powered by Disqus.</a></noscript>
+ <a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
+
+ </section>
+ </article>
+ </section>
+
+{% endblock %}
13 web/dbpatterns/dbpatterns/templates/blog/donation.html
View
@@ -0,0 +1,13 @@
+<aside class="donation">
+ <h3>Donations</h3>
+ <p>Dbpatterns is an open-source project that doesn't have any profit or revenue model.
+ However dbpatterns needs donations to pay server expenses.</p>
+ <p>If you want to help us, you can make donation to keep running dbpatterns.</p>
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+ <input type="hidden" name="cmd" value="_s-xclick">
+ <input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----
+">
+ <input type="submit" class="donate" value="Donate">
+ <img alt="" border="0" src="https://www.paypalobjects.com/tr_TR/i/scr/pixel.gif" width="1" height="1">
+ </form>
+</aside>
11 web/dbpatterns/dbpatterns/templates/blog/index.html
View
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <section class="content">
+ {% include "blog/donation.html" %}
+ {% for post in posts %}
+ {% include "blog/post.html" %}
+ {% endfor %}
+ {% include "blog/pagination.html" %}
+ </section>
+{% endblock %}
5 web/dbpatterns/dbpatterns/templates/blog/pagination.html
View
@@ -0,0 +1,5 @@
+{% if is_paginated %}
+ {% if page_obj.has_next %}
+ <a class="more" href="?page={{ page_obj.next_page_number }}">Show more</a>
+ {% endif %}
+{% endif %}
9 web/dbpatterns/dbpatterns/templates/blog/post.html
View
@@ -0,0 +1,9 @@
+<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
+ <aside><time datetime="{{ post.date_created }}">{{ post.date_created|date }}</time></aside>
+ <header>
+ <h3><a itemprop="url" href="{{ post.get_absolute_url }}">{{ post.title }}</a></h3>
+ </header>
+ <section itemprop="articleBody">
+ {{ post.content }}
+ </section>
+</article>
3  web/dbpatterns/dbpatterns/urls.py
View
@@ -22,6 +22,9 @@
# api
url(r'^api/', include('api.urls')),
+ # blog
+ url(r'^blog/', include("blog.urls")),
+
# legacy urls
url(r'^', include('documents.legacy_urls')),
9 web/dbpatterns/terrain.py
View
@@ -6,7 +6,6 @@
from django.test.simple import DjangoTestSuiteRunner
from lettuce import *
-from south.management.commands import patch_for_test_db_setup
from documents.models import Document
from newsfeed.models import Entry
@@ -19,7 +18,13 @@ def switch_to_test_database():
Switching to the test database
"""
logging.info("Setting up a test database ...\n")
- patch_for_test_db_setup()
+
+ try:
+ from south.management.commands import patch_for_test_db_setup
+ patch_for_test_db_setup()
+ except ImportError:
+ pass
+
world.test_runner = DjangoTestSuiteRunner(interactive=False)
world.test_runner.setup_test_environment()
world.test_db = world.test_runner.setup_databases()
Please sign in to comment.
Something went wrong with that request. Please try again.