Skip to content

Instantly share code, notes, and snippets.

@jtauber
Last active November 19, 2015 16:15
Show Gist options
  • Save jtauber/7d6379ad640e4b560363 to your computer and use it in GitHub Desktop.
Save jtauber/7d6379ad640e4b560363 to your computer and use it in GitHub Desktop.
diff --git a/requirements.txt b/requirements.txt
index 016a56b..2685f0b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,7 @@
Django==1.8.5
pinax-theme-bootstrap==7.1.1
+django-bootstrap-form==3.2
+pinax-blog==4.2.1
+pytz==2015.4
+Markdown==2.6.2
+Pillow==2.9.0
diff --git a/project_name/urls.py b/project_name/urls.py
index aeb47f8..3af58d3 100644
--- a/project_name/urls.py
+++ b/project_name/urls.py
@@ -1,8 +1,14 @@
-from django.conf.urls import patterns, url
-from django.views.generic import TemplateView
+from django.conf import settings
+from django.conf.urls import patterns, include, url
+from django.conf.urls.static import static
+from django.contrib import admin
urlpatterns = patterns(
"",
- url(r"^$", TemplateView.as_view(template_name="homepage.html"), name="home"),
+ url(r"^admin/", include(admin.site.urls)),
+ url(r"", include("pinax.blog.urls")),
)
+
+
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/project_name/settings.py b/project_name/settings.py
index e24d9a9..267d30d 100644
--- a/project_name/settings.py
+++ b/project_name/settings.py
@@ -95,6 +95,7 @@ TEMPLATES = [
"django.core.context_processors.request",
"django.contrib.messages.context_processors.messages",
"pinax_theme_bootstrap.context_processors.theme",
+ "{{ project_name }}.context_processors.settings",
],
},
},
@@ -116,6 +117,7 @@ ROOT_URLCONF = "{{ project_name }}.urls"
WSGI_APPLICATION = "{{ project_name }}.wsgi.application"
INSTALLED_APPS = [
+ "django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.messages",
@@ -127,6 +129,9 @@ INSTALLED_APPS = [
"bootstrapform",
"pinax_theme_bootstrap",
+ # external
+ "pinax.blog",
+
# project
"{{ project_name }}",
]
diff --git a/project_name/context_processors.py b/project_name/context_processors.py
new file mode 100644
index 0000000..9251599
--- /dev/null
+++ b/project_name/context_processors.py
@@ -0,0 +1,12 @@
+from django.contrib.sites.models import Site
+
+
+def settings(request):
+ ctx = {}
+ if Site._meta.installed:
+ site = Site.objects.get_current()
+ ctx.update({
+ "SITE_NAME": site.name,
+ "SITE_DOMAIN": site.domain
+ })
+ return ctx
diff --git a/project_name/templates/admin/blog/post/change_form.html b/project_name/templates/admin/blog/post/change_form.html
new file mode 100644
index 0000000..77f2082
--- /dev/null
+++ b/project_name/templates/admin/blog/post/change_form.html
@@ -0,0 +1,44 @@
+{% extends "admin/change_form.html" %}
+{% load i18n admin_urls %}
+{% block extrahead %}
+ {{ block.super }}
+ <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
+ <script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.1.8/ace.js"></script>
+ <script>
+ $(function () {
+ var contentDiv = $("<div>").attr("id", "content-editor"),
+ teaserDiv = $("<div>").attr("id", "teaser-editor"),
+ setupEditor = function (editor, textarea) {
+ editor.setTheme("ace/theme/twilight");
+ editor.getSession().setMode("ace/mode/markdown");
+ editor.getSession().setValue(textarea.val());
+ editor.getSession().setUseWrapMode(true);
+ editor.getSession().on('change', function(){
+ textarea.val(editor.getSession().getValue());
+ });
+ editor.getSession().setTabSize(4);
+ editor.getSession().setUseSoftTabs(true);
+ };
+ $(".field-content div").append(contentDiv);
+ $(".field-teaser div").append(teaserDiv);
+ var editor1 = ace.edit("content-editor");
+ var editor2 = ace.edit("teaser-editor");
+ var textarea1 = $('textarea[name="content"]').hide();
+ var textarea2 = $('textarea[name="teaser"]').hide();
+ setupEditor(editor1, textarea1);
+ setupEditor(editor2, textarea2);
+ });
+ </script>
+ <style type="text/css" media="screen">
+ #content-editor {
+ min-height: 300px;
+ width: 80%;
+ min-width: 800px;
+ }
+ #teaser-editor {
+ min-height: 100px;
+ width: 80%;
+ min-width: 800px;
+ }
+</style>
+{% endblock %}
\ No newline at end of file
diff --git a/project_name/templates/pinax/blog/blog_base.html b/project_name/templates/pinax/blog/blog_base.html
new file mode 100644
index 0000000..f7ae532
--- /dev/null
+++ b/project_name/templates/pinax/blog/blog_base.html
@@ -0,0 +1,51 @@
+{% extends "site_base.html" %}
+
+{% load pinax_blog_tags %}
+
+{% block body_class %}blog{% endblock %}
+
+{% block body %}
+ <div class="row blog-container">
+ <div class="col-md-3 sidebar">
+ {% block sidebar %}
+ <h1>
+ <a href="{% url "blog" %}">{{ SITE_NAME }}</a>
+ </h1>
+ <p class="lead">
+ This is where you can list your bio, add links
+ etc., by editing the <code>pinax/blog/blog_base.html</code>
+ template.
+ </p>
+ <p>
+ <a href="{% url 'blog_feed' 'all' 'atom' %}"><i class="fa fa-rss"></i> Atom Feed</a>
+ </p>
+ <div class="search">
+ {% if section_slug %}
+ {% url "blog_section" section_slug as search_url %}
+ {% else %}
+ {% url "blog" as search_url %}
+ {% endif %}
+
+ <form class="form-search" action="{{ search_url }}">
+ <label><i class="fa fa-search"></i></label>
+ <input class="form-control" type="search" placeholder="Search..." name="q" value="{{ search_term|default:"" }}">
+ </form>
+ </div>
+ <ul class="">
+ <li class="{% if current_section == "all" %}active{% endif %}">
+ <a href="{% url "blog" %}">All</a>
+ </li>
+ {% blog_sections as sections %}
+ {% for section in sections %}
+ <li class="{% if current_section == section %}active{% endif %}">
+ <a href="{% url "blog_section" section.slug %}">{{ section.name }}</a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endblock %}
+ </div>
+ <div class="col-md-8 blog-content">
+ {% block content %}{% endblock %}
+ </div>
+ </div>
+{% endblock %}
diff --git a/project_name/templates/pinax/blog/blog_list.html b/project_name/templates/pinax/blog/blog_list.html
new file mode 100644
index 0000000..8bc1304
--- /dev/null
+++ b/project_name/templates/pinax/blog/blog_list.html
@@ -0,0 +1,23 @@
+{% extends "pinax/blog/blog_base.html" %}
+
+{% block head_title_base %}{{ SITE_NAME }}{% endblock %}
+
+
+{% block content %}
+ <h1>Blog Posts</h1>
+ {% if post_list %}
+ <div class="post-list">
+ {% for post in post_list %}
+ <div class="post">
+ <h2><a href="{{ post.get_absolute_url }}">{{ post.title }}</a></h2>
+ {% include "pinax/blog/dateline.html" %}
+ <div class="teaser">{{ post.teaser_html|safe }}</div>
+ <p class="more"><a href="{{ post.get_absolute_url }}" class="post-link">read more...</a></p>
+ </div>
+ {% endfor %}
+ </div>
+ {% include "pagination/builtin_pagination_reverse.html" %}
+ {% else %}
+ <p class="alert alert-info lead">No blog posts have been published.</p>
+ {% endif %}
+{% endblock %}
diff --git a/project_name/templates/pinax/blog/blog_post.html b/project_name/templates/pinax/blog/blog_post.html
new file mode 100644
index 0000000..9e2047c
--- /dev/null
+++ b/project_name/templates/pinax/blog/blog_post.html
@@ -0,0 +1,48 @@
+{% extends "pinax/blog/blog_base.html" %}
+
+{% block body_class %}blog blog-post{% endblock %}
+
+{% block head_title_base %}{{ post.title }} | {{ SITE_NAME }}{% endblock %}
+
+{% block extra_head %}
+ {{ block.super }}
+ <meta name="twitter:card" content="summary">
+ {% comment %}
+ <meta name="twitter:image" content="https://pbs.twimg.com/profile_images/62846141/pinaxproject_avatar.png">
+ {% endcomment %}
+ <meta property="og:title" content="{{ post.title }}">
+ {% if post.description %}
+ <meta name="description" content="{{ post.description }}">
+ <meta property="og:description" content="{{ post.description }}">
+ {% else %}
+ <meta name="description" content="{{ post.teaser_html|striptags }}">
+ <meta property="og:description" content="{{ post.teaser_html|striptags }}">
+ {% endif %}
+ {% if post.primary_image %}
+ <meta property="og:image" content="http://{{ SITE_DOMAIN }}{{ post.primary_image.image_path.url }}">
+ {% else %}
+ {% comment %}
+ <meta property="og:image" content="https://pbs.twimg.com/profile_images/62846141/pinaxproject_avatar.png">
+ {% endcomment %}
+ {% endif %}
+ <meta property="og:url" content="http://{{ SITE_DOMAIN }}{{ post.get_absolute_url }}">
+ <meta property="og:type" content="article">
+{% endblock %}
+
+{% block content %}
+ <div class="post-detail">
+ <div class="post">
+ <h1>{{ post.title }}</h1>
+ {% include "pinax/blog/dateline_stale.html" %}
+
+ <div class="teaser">{{ post.teaser_html|safe }}</div>
+
+ <div class="content">{{ post.content_html|safe }}</div>
+
+ <div class="twitter-button">
+ <a href="https://twitter.com/share" class="twitter-share-button" data-via="">Tweet</a>
+ <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
+ </div>
+ </div>
+ </div>
+{% endblock %}
diff --git a/project_name/templates/pinax/blog/dateline.html b/project_name/templates/pinax/blog/dateline.html
new file mode 100644
index 0000000..8fa92b6
--- /dev/null
+++ b/project_name/templates/pinax/blog/dateline.html
@@ -0,0 +1,5 @@
+<p class="post-meta">
+ <span class="date">{% if post.published %}{{ post.published|date:"jS F Y" }}{% else %}Not published yet{% endif %}</span> /
+ by <span class="author">{{ post.author.get_full_name }}</span> in
+ <a href="{% url "blog_section" post.section.slug %}"><span class="section">{{ post.section.name }}</span></a>
+</p>
diff --git a/project_name/templates/pinax/blog/dateline_stale.html b/project_name/templates/pinax/blog/dateline_stale.html
new file mode 100644
index 0000000..18f2730
--- /dev/null
+++ b/project_name/templates/pinax/blog/dateline_stale.html
@@ -0,0 +1,7 @@
+<p class="post-meta">
+ {% if not post.stale %}
+ <span class="date">{% if post.published %}{{ post.published|date:"jS F Y" }}{% else %}Not published yet{% endif %}</span> /
+ {% endif %}
+ by <span class="author">{{ post.author.get_full_name }}</span> in
+ <a href="{% url "blog_section" post.section.slug %}"><span class="section">{{ post.section.name }}</span></a>
+</p>
diff --git a/project_name/templates/site_base.html b/project_name/templates/site_base.html
index 7221602..2aad610 100644
--- a/project_name/templates/site_base.html
+++ b/project_name/templates/site_base.html
@@ -14,14 +14,18 @@
{% block extra_head_base %}
- {% block extra_head %}{% endblock %}
+ {% block extra_head %}
+ {{ block.super }}
+ {% comment %}
+ <meta name="twitter:site" content="@pinaxproject">
+ {% endcomment %}
+ <meta property="og:site_name" content="{{ SITE_NAME }}">
+ <link rel="alternate" type="application/atom+xml" href="{% url 'blog_feed' 'all' 'atom' %}" title="Atom Feed for Blog">
+ {% endblock %}
{% endblock %}
-{% block footer %}
- {% include "_footer.html" %}
-{% endblock %}
-
+{% block footer_base %}{% endblock %}
{% block scripts %}
{% include "_scripts.html" %}
diff --git a/static/src/less/custom.less b/static/src/less/custom.less
index e4e43ce..a38948b 100644
--- a/static/src/less/custom.less
+++ b/static/src/less/custom.less
@@ -1,29 +1,20 @@
-body {
- padding-top: 50px;
- position: relative;
-}
-section {
- padding: 20px 0px;
-}
-.modal form {
- margin-bottom: 0px;
-}
-footer {
- padding-bottom: 20px;
-}
-p.login-signup {
- margin-top: 20px;
+.teaser {
+ .lead;
}
-.feature-columns {
- .make-row();
+form.form-search {
+ position: relative;
+ margin-top: 20px;
+
+ input {
+ padding-left: 28px;
+ }
- > div {
- i.fa {
- margin-bottom: 0.2em;
- }
- .make-sm-column(4);
- .text-center;
- margin: 2em 0;
- }
+ label {
+ position: absolute;
+ left: 10px;
+ top: 6px;
+ color: #999;
+ font-size: 13px;
+ }
}
diff --git a/static/src/less/site.less b/static/src/less/site.less
index 37295ea..492bd33 100644
--- a/static/src/less/site.less
+++ b/static/src/less/site.less
@@ -10,6 +10,11 @@
@font-family-serif: Georgia, "Times New Roman", Times, serif;
@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
+// Theme
+@import "theme.less";
+
+// Code highlighting
+@import "tomorrow-night.less";
// Site overrides
@import "custom.less";
diff --git a/static/src/less/theme.less b/static/src/less/theme.less
new file mode 100644
index 0000000..52f6b67
--- /dev/null
+++ b/static/src/less/theme.less
@@ -0,0 +1,16 @@
+body {
+ padding-top: 50px;
+ position: relative;
+}
+section {
+ padding: 20px 0px;
+}
+.modal form {
+ margin-bottom: 0px;
+}
+footer {
+ padding-bottom: 20px;
+}
+p.login-signup {
+ margin-top: 20px;
+}
diff --git a/static/src/less/tomorrow-night.less b/static/src/less/tomorrow-night.less
new file mode 100644
index 0000000..97225aa
--- /dev/null
+++ b/static/src/less/tomorrow-night.less
@@ -0,0 +1,72 @@
+.codehilitetable,
+.codehilite {
+ .linenos {display: none;}
+ pre {
+ background: #1d1f21;
+ color: #c5c8c6;
+ }
+ .hll { background-color: #373b41 }
+ .c { color: #969896 } /* Comment */
+ .err { color: #cc6666 } /* Error */
+ .k { color: #b294bb } /* Keyword */
+ .l { color: #de935f } /* Literal */
+ .n { color: #c5c8c6 } /* Name */
+ .o { color: #8abeb7 } /* Operator */
+ .p { color: #c5c8c6 } /* Punctuation */
+ .cm { color: #969896 } /* Comment.Multiline */
+ .cp { color: #969896 } /* Comment.Preproc */
+ .c1 { color: #969896 } /* Comment.Single */
+ .cs { color: #969896 } /* Comment.Special */
+ .gd { color: #cc6666 } /* Generic.Deleted */
+ .ge { font-style: italic } /* Generic.Emph */
+ .gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */
+ .gi { color: #b5bd68 } /* Generic.Inserted */
+ .gp { color: #969896; font-weight: bold } /* Generic.Prompt */
+ .gs { font-weight: bold } /* Generic.Strong */
+ .gu { color: #8abeb7; font-weight: bold } /* Generic.Subheading */
+ .kc { color: #b294bb } /* Keyword.Constant */
+ .kd { color: #b294bb } /* Keyword.Declaration */
+ .kn { color: #8abeb7 } /* Keyword.Namespace */
+ .kp { color: #b294bb } /* Keyword.Pseudo */
+ .kr { color: #b294bb } /* Keyword.Reserved */
+ .kt { color: #f0c674 } /* Keyword.Type */
+ .ld { color: #b5bd68 } /* Literal.Date */
+ .m { color: #de935f } /* Literal.Number */
+ .s { color: #b5bd68 } /* Literal.String */
+ .na { color: #81a2be } /* Name.Attribute */
+ .nb { color: #c5c8c6 } /* Name.Builtin */
+ .nc { color: #f0c674 } /* Name.Class */
+ .no { color: #cc6666 } /* Name.Constant */
+ .nd { color: #8abeb7 } /* Name.Decorator */
+ .ni { color: #c5c8c6 } /* Name.Entity */
+ .ne { color: #cc6666 } /* Name.Exception */
+ .nf { color: #81a2be } /* Name.Function */
+ .nl { color: #c5c8c6 } /* Name.Label */
+ .nn { color: #f0c674 } /* Name.Namespace */
+ .nx { color: #81a2be } /* Name.Other */
+ .py { color: #c5c8c6 } /* Name.Property */
+ .nt { color: #8abeb7 } /* Name.Tag */
+ .nv { color: #cc6666 } /* Name.Variable */
+ .ow { color: #8abeb7 } /* Operator.Word */
+ .w { color: #c5c8c6 } /* Text.Whitespace */
+ .mf { color: #de935f } /* Literal.Number.Float */
+ .mh { color: #de935f } /* Literal.Number.Hex */
+ .mi { color: #de935f } /* Literal.Number.Integer */
+ .mo { color: #de935f } /* Literal.Number.Oct */
+ .sb { color: #b5bd68 } /* Literal.String.Backtick */
+ .sc { color: #c5c8c6 } /* Literal.String.Char */
+ .sd { color: #969896 } /* Literal.String.Doc */
+ .s2 { color: #b5bd68 } /* Literal.String.Double */
+ .se { color: #de935f } /* Literal.String.Escape */
+ .sh { color: #b5bd68 } /* Literal.String.Heredoc */
+ .si { color: #de935f } /* Literal.String.Interpol */
+ .sx { color: #b5bd68 } /* Literal.String.Other */
+ .sr { color: #b5bd68 } /* Literal.String.Regex */
+ .s1 { color: #b5bd68 } /* Literal.String.Single */
+ .ss { color: #b5bd68 } /* Literal.String.Symbol */
+ .bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */
+ .vc { color: #cc6666 } /* Name.Variable.Class */
+ .vg { color: #cc6666 } /* Name.Variable.Global */
+ .vi { color: #cc6666 } /* Name.Variable.Instance */
+ .il { color: #de935f } /* Literal.Number.Integer.Long */
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment