Grigoriy Petukhov avatar Grigoriy Petukhov committed 27fb27e

Changes

Comments (0)

Files changed (13)

 ============
 
 * Install django-article's dependencies
-* Install django-article application and configure them
-* Add article to INSTALLED_APPS
-* Put ARTICLE_PAGE_SIZE setting into settings.py
-* Do syncdb
+    * Add to INSTALLED_APPS::
+
+        'sorl.thumbnail',
+        'ckeditor',
+
+    * Add to urls.py::
+
+        url(r'^ckeditor/', include('ckeditor.urls')),
+
+    * Add to settings.py::
+
+        CKEDITOR_UPLOAD_PATH = os.path.join(MEDIA_ROOT, 'upload/ckeditor')
+        CKEDITOR_CONFIGS = {
+            'default': {
+                'toolbar': 'Full',
+                'width': 840,
+                'height': 300,
+                'toolbarCanCollapse': False,
+            }
+        }
+
+* Install django-article application
+* Add to INSTALLED_APPS::
+
+    'article',
+
+* Add to settings.py::
+    
+    ARTICLE_PAGE_SIZE = 10
+
+* Add to urls.py::
+
+    url(r'^blog/', include('article.urls'), namespace='article'),
+
+* Run ./manage.py syncdb --migrate
 
 
 Templates
 from article.models import Article, Category
 
 class ArticleAdmin(admin.ModelAdmin):
-    list_display = ['title', 'category', 'created', 'live_url',
+    list_display = ['title', 'category', 'user', 'created', 'live_url',
                     'image_thumbnail']
     list_filter = ['category']
     search_fields = ['title', 'teaser', 'content']
+# coding: utf-8
+from django.contrib.syndication.views import Feed
+from django.core.urlresolvers import reverse
+from django.conf import settings
+
+from article.models import Article
+
+class ArticleFeed(Feed):
+    title = settings.ARTICLE_FEED_TITLE
+    link = settings.ARTICLE_FEED_LINK
+    description = settings.ARTICLE_FEED_DESCRIPTION
+
+    def items(self):
+        return Article.objects.order_by('-created')[:10]
+
+    def item_title(self, item):
+        return item.title
+
+    def item_description(self, item):
+        return item.teaser
+
+    def item_pubdate(self, item):
+        return item.created

article/migrations/0002_auto__del_field_article_date_published__add_field_article_user__chg_fi.py

+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Deleting field 'Article.date_published'
+        db.delete_column('article_article', 'date_published')
+
+        # Adding field 'Article.user'
+        db.add_column('article_article', 'user',
+                      self.gf('django.db.models.fields.related.ForeignKey')(default=2, to=orm['auth.User']),
+                      keep_default=False)
+
+
+        # Changing field 'Article.content'
+        db.alter_column('article_article', 'content', self.gf('ckeditor.fields.RichTextField')())
+
+        # Changing field 'Article.teaser'
+        db.alter_column('article_article', 'teaser', self.gf('ckeditor.fields.RichTextField')())
+        # Removing index on 'Article', fields ['is_starred']
+        db.delete_index('article_article', ['is_starred'])
+
+
+    def backwards(self, orm):
+        # Adding index on 'Article', fields ['is_starred']
+        db.create_index('article_article', ['is_starred'])
+
+        # Adding field 'Article.date_published'
+        db.add_column('article_article', 'date_published',
+                      self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True),
+                      keep_default=False)
+
+        # Deleting field 'Article.user'
+        db.delete_column('article_article', 'user_id')
+
+
+        # Changing field 'Article.content'
+        db.alter_column('article_article', 'content', self.gf('django.db.models.fields.TextField')())
+
+        # Changing field 'Article.teaser'
+        db.alter_column('article_article', 'teaser', self.gf('django.db.models.fields.TextField')())
+
+    models = {
+        'article.article': {
+            'Meta': {'object_name': 'Article'},
+            'category': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'articles'", 'to': "orm['article.Category']"}),
+            'content': ('ckeditor.fields.RichTextField', [], {}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
+            'is_starred': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'meta_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'meta_keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '255'}),
+            'teaser': ('ckeditor.fields.RichTextField', [], {}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+        },
+        'article.category': {
+            'Meta': {'object_name': 'Category'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'meta_description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'meta_keywords': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'meta_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+            'slug': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'})
+        },
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        }
+    }
+
+    complete_apps = ['article']

article/models.py

             upload_to='upload/article/article_image')
     meta_keywords = models.CharField(max_length=255, blank=True)
     meta_description = models.TextField(blank=True)
+    user = models.ForeignKey('auth.User')
     
     objects = models.Manager()
 
 
     def get_absolute_url(self):
         return reverse('article:article_details',
-                       args=[self.category.slug, self.pk, self.slug])
+                       args=[self.pk, self.slug])
 
     def __unicode__(self):
         return self.title

article/templatetags/article_tags.py

             article = None
         context[self.name] = article
         return ''
+
+
+@register.assignment_tag
+def load_popular_articles():
+    arts = Article.objects.filter(is_starred=True)\
+                  .order_by('-created')
+    arts = arts[:5]
+    return arts
+
+
+@register.assignment_tag
+def load_recent_articles(limit=5):
+    arts = Article.objects.order_by('-created')
+    arts = arts[:limit]
+    return arts
     url(r'^$', 'home_page', name='home_page'),
 
     # List of articles from certain category
-    url(r'^([-\w]+)$', 'category_details', name='category_details'),
+    url(r'^category/([-\w]+)$', 'category_details', name='category_details'),
 
     # Article's details page
     # example: ../nature/13/why-flowers-are-so-beautiful/
-    url(r'^([-\w]+)/(\d+)/([-\w]+)/$', 'article_details', name='article_details'),
+    url(r'^post/(\d+)/([-\w]+)/$', 'article_details', name='article_details'),
+
+    url(r'^([-\w]+)/(\d+)/([-\w]+)/$', 'article_redirect'),
 )
 # -*- coding: utf-8 -*-
 from django.shortcuts import redirect, get_object_or_404, render
 from django.conf import settings
+import pymongo
+from bson import ObjectId
+from grab.tools.lxml_tools import render_html, parse_html, disable_links, drop_node
+from random import sample
 
 from common.pagination import paginate
 
 from article.models import Article, Category
 
+db = pymongo.Connection()['turtips']
+
 def home_page(request):
     article_qs = Article.objects.order_by('-created')
     page = paginate(article_qs, request)
     return render(request, 'article/category_details.html', context)
 
 
-def article_details(request, category_slug, pk, article_slug):
+def article_details(request, pk, article_slug):
     article = get_object_or_404(Article, pk=pk)
-    context = {'article': article}
+
+    qs = Article.objects.all()
+    also = []
+    ids = qs.values_list('pk', flat=True)
+    also.extend(list(qs.filter(pk__lt=article.pk).order_by('-pk')[:1]))
+    also.extend(list(qs.filter(pk__lt=article.pk).order_by('-pk')[:1]))
+    also.extend(list(qs.filter(pk__in=sample(ids, 1))))
+    also = set(also)
+
+    context = {'article': article, 'also_articles': also}
     return render(request, 'article/article_details.html', context)
+
+
+def article_redirect(request, category_slug, pk, article_slug):
+    article = get_object_or_404(Article, pk=pk)
+    return redirect(article, permanent=True)

templates/_article_item.html

-{% load thumbnail %}
-
-<h2>{% if article.is_starred %}(*) {% endif %}{{ article }}</h2>
-<div>
-    {% thumbnail article.image "100x100" as thumb %}<img src="{{ thumb.url }}" alt="" />{% endthumbnail %}
-    {{ article.teaser|safe }}
-    <a href="{{ article.get_absolute_url }}">read more...</a>
-</div>
-<hr/>

templates/article_details.html

-{% extends 'article/base.html' %}
-{% load thumbnail package_tags article_tags %}
-
-{% block article_content %}
-<div class="homeBasic">
-	<div class="staticWrapp">
-    	<h2>{{ article.title }}</h2>
-    	{% thumbnail article.image "586x276" crop="center" as im %}
-		<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" alt="{{ article.title }}" />
-		{% endthumbnail %}
-		{{ article.content|truncate_links|safe }}
-	</div>
-
-	<div class="sideBar">
-		<div class="contTop">
-			<div class="cont">
-				<h4>{{ category.name }}</h4>
-                <p>{{ category.description }}</p>
-				<ul>
-				{% for article in category.get_articles %}{% if forloop.counter < 5 %}
-					<li><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></li>
-				{% endif %}{% endfor %}
-				</ul>
-				<ul>
-				{% for cat in categories %}
-					<li><a href="{{ cat.get_absolute_url }}">{{ cat.name }}</a> ({{ cat.get_articles|length }})</li>
-				{% endfor %}
-				</ul>
-			</div>
-		</div>
-      
-		{% articles_sidebar %}
-                                            
-		</div>
-</div>
-{% endblock %}

templates/base.html

-{% extends 'base.html' %}
-{% load article_tags %}
-
-{% block content %}
-	{% block categories %}{% endblock %}
-	{% block article_content %}{% endblock %}
-	{% block sidebar %}{% endblock %}
-	<div style="clear: both"></div>
-{% endblock %}

templates/category_details.html

-{% extends 'article/base.html' %}
-
-{% block title %}Questions in {{ category }}{% endblock %}
-
-{% load thumbnail package_tags %}
-
-{% block article_content %}
-<div class="pageHeader">
-	<h1>{{ category }}</h1>
-    <p>{{ category.description }}</p>
-</div>
-<div class="staticWrapper">
-	<div class="staticWrapp">
-		{% with page.object_list as articles %}
-		{% if articles %}
-        <a href="{{ articles.0.get_absolute_url }}">
-        	<h2>{% if articles.0.is_starred %}(*){% endif %}{{ articles.0.title }}</h2>
-        </a>
-		{% thumbnail articles.0.image "586x276" crop="center" as im %}
-		<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" alt="{{ articles.0.title }}" />
-		{% endthumbnail %}
-		<p>{{ articles.0.teaser|safe }}</p>
-		<span class="buttonRead"><a href="{{ articles.0.get_absolute_url }}">Pročitaj</a></span>
-		<ul>
-			{% for article in articles|slice:"1:" %}
-			<li style="{% cycle '' 'padding-right:0;' %}" class="article-teaser">
-				<a href="{{ article.get_absolute_url }}">
-					<h3>{% if article.is_starred %}(*){% endif %}{{ article.title }}</h3>
-				</a>
-				{% thumbnail article.image "276x151" crop="center" as im %}
-				<div style="height: 151;">
-				<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" alt="{{ article.title }}" />
-				</div>
-				{% endthumbnail %}				
-				<p>{{ article.teaser|truncatewords_html:20|safe }}</p>
-				<span class="buttonRead"><a href="{{ article.get_absolute_url }}">Pročitaj</a></span>			
-			</li>
-			{% endfor %}
-		</ul>
-		{% endif%}
-		{% endwith %}
-	</div>
-	
-	<div class="sideBar">
-		<div class="contTop">
-			<div class="cont">
-				<h4>Saveti</h4>
-				<ul>
-					{% for cat in categories %}
-					<li><a href="{{ cat.get_absolute_url }}">{{ cat.name }}</a> ({{ cat.get_articles|length }})</li>
-					{% endfor %}
-				</ul>
-			</div>
-		</div>
-		
-	{#{% include "newsletter_form.html" %}#}
-	
-	{% articles_sidebar %}
-	
-	</div>	
-</div>
-
-{% comment %}
-<h1>Questions in {{ category }} category</h1>
-{% for article in starred_articles %}
-{% include "article/_article_item.html" %}
-{% endfor %}
-{% for article in page.object_list %}
-{% include "article/_article_item.html" %}
-{% endfor %}
-{% endcomment %}
-
-{% include "pagination.html" %}
-{% endblock %}

templates/home_page.html

-{% extends 'article/base.html' %}
-{% load meta_tags thumbnail package_tags %}
-
-{% block title %}FAQ{% endblock %}
-
-
-{% block categories %}
-	<div class="pageHeader">
-        {% with request.path|meta as meta %}
-        <h1>{% block header %}{{ meta.header }}{% endblock %}</h1>
-        <p>{% block subheader %}{{ meta.subheader }}{% endblock %}</p>
-        {% endwith %}
-    </div>
-{% endblock%}
-
-{% block article_content %}
-<div class="staticWrapper">
-	<div class="staticWrapp">
-		<a href="{{ last_article.get_absolute_url }}"><h2 class="smallerSubheadlines">{{ last_article }}</h2></a>
-		{% thumbnail last_article.image "586x276" crop="center" as im %}
-		<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" alt="" />
-		{% endthumbnail %}
-		<p>{{ last_article.teaser|safe }}</p>
-		<span class="buttonRead"><a href="{{ last_article.get_absolute_url }}">Pročitaj</a></span>
-		<ul>
-			{% for cat in categories %}
-			<li style="{% cycle '' 'padding-right:0;' 'padding-bottom:0;' %}" class="article-teaser">
-				<a href="{{ cat.get_absolute_url }}"><h4>{{ cat.name }}</h4></a>
-				<a href="{{ cat.get_articles.0.get_absolute_url }}">
-					<h3 class="smallerSubheadlines">{{ cat.get_articles.0.title }}</h3>
-				</a>
-				{% thumbnail cat.get_articles.0.image "276x151" crop="center" as im %}
-				<div style="height: 151;">
-				<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" alt="{{ cat.name }}" />
-				</div>
-				{% endthumbnail %}
-				<p>{{ cat.get_articles.0.teaser|truncatewords_html:15|safe }}</p>
-				<span class="buttonRead"><a href="{{ cat.get_articles.0.get_absolute_url }}">Pročitaj</a></span>
-				<ul>
-					{% for article in cat.get_articles %}
-					{% if forloop.counter > 1 and forloop.counter < 5 %}
-					<li><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></li>
-					{% endif %}
-					{% endfor %}
-				</ul>
-			</li>
-			{% endfor %}
-		</ul>
-	</div>
-
-	<div class="sideBar">
-		{% articles_sidebar %}
-	</div>
-	
-</div>
-{% endblock %}
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.