Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
rock
committed
Dec 11, 2008
0 parents
commit 6301f82
Showing
19 changed files
with
494 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.pyc | ||
*.bak | ||
*.db | ||
local_settings.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
|
||
Djangop-FAQ v.1.0 | ||
============ | ||
|
||
An extremely simple faq application for your Django powered site. I also made note to provide this app as an example of creating | ||
a reusable app following best practices - allowing for template overrides, extra_context arguments, etc. So | ||
in theory you should be able to drop it on your Python path and get going pretty easy. I noted where appropriate some of the details. Search for '#NOTE' to see where I left those tidbits of info that provide some more details within the code. | ||
|
||
Installation | ||
============ | ||
|
||
1. add 'faq' directory to your Python path. | ||
2. add 'faq' to your INSTALLED_APPS tuple found in your settings file. | ||
3. If you want to customize the templates then either create an 'faq' directory in your projects templates location, or you can also pass along custom 'template_name' arguments by creating your own view wrappers around the 'faq' app views. I show how to do the latter in the 'example' project included - look at the views.py file to see the details. | ||
|
||
Example Site | ||
============ | ||
|
||
I included an example site in the /example directory. You should be able to simply execute './manage.py syncdb' and then './manage.py runserver' and have the example site up and running. I assume your system has sqlite3 available - it is set as the default database with the DATABASE_NAME = 'faq.db' |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#!/usr/bin/env python | ||
|
||
#add faq app to python path | ||
import sys | ||
from os.path import abspath, dirname, join | ||
sys.path.append(abspath(join(dirname(__file__), '..'))) | ||
|
||
from django.core.management import execute_manager | ||
try: | ||
import settings # Assumed to be in the same directory. | ||
except ImportError: | ||
import sys | ||
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) | ||
sys.exit(1) | ||
|
||
if __name__ == "__main__": | ||
execute_manager(settings) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Django settings for [name] project. | ||
import os, os.path, sys | ||
|
||
#set DEBUG = False and django will send exception emails | ||
DEBUG = True | ||
TEMPLATE_DEBUG = DEBUG | ||
PROJECT_DIR = os.path.dirname(__file__) | ||
|
||
DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. | ||
DATABASE_NAME = 'faq.db' # Or path to database file if using sqlite3. | ||
DATABASE_USER = '' # Not used with sqlite3. | ||
DATABASE_PASSWORD = '' # Not used with sqlite3. | ||
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. | ||
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. | ||
|
||
# Local time zone for this installation. Choices can be found here: | ||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name | ||
# although not all choices may be avilable on all operating systems. | ||
# If running in a Windows environment this must be set to the same as your | ||
# system time zone. | ||
TIME_ZONE = 'America/New_York' | ||
|
||
# Language code for this installation. All choices can be found here: | ||
# http://www.i18nguy.com/unicode/language-identifiers.html | ||
LANGUAGE_CODE = 'en-us' | ||
|
||
SITE_ID = 1 | ||
|
||
# If you set this to False, Django will make some optimizations so as not | ||
# to load the internationalization machinery. | ||
USE_I18N = True | ||
|
||
# Absolute path to the directory that holds media. | ||
# Example: "/home/media/media.lawrence.com/" | ||
MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media') | ||
|
||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a | ||
# trailing slash if there is a path component (optional in other cases). | ||
# Examples: "http://media.lawrence.com", "http://example.com/media/" | ||
#MEDIA_URL = 'http://127.0.0.1:8000/site_media/' | ||
MEDIA_URL = '/media/' # | ||
|
||
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a | ||
# trailing slash. | ||
# Examples: "http://foo.com/media/", "/media/". | ||
ADMIN_MEDIA_PREFIX = '/admin_media/' | ||
|
||
# Make this unique, and don't share it with anybody. | ||
SECRET_KEY = 'c#zi(mv^n+4te_sy$hpb*zdo7#f7ccmp9ro84yz9bmmfqj9y*c' | ||
|
||
# List of callables that know how to import templates from various sources. | ||
TEMPLATE_LOADERS = ( | ||
'django.template.loaders.filesystem.load_template_source', | ||
'django.template.loaders.app_directories.load_template_source', | ||
) | ||
|
||
TEMPLATE_CONTEXT_PROCESSORS = ( | ||
'django.core.context_processors.auth', | ||
'django.core.context_processors.media', | ||
) | ||
|
||
MIDDLEWARE_CLASSES = ( | ||
#'django.middleware.cache.CacheMiddleware', | ||
'django.middleware.common.CommonMiddleware', | ||
'django.contrib.sessions.middleware.SessionMiddleware', | ||
'django.contrib.auth.middleware.AuthenticationMiddleware', | ||
'django.middleware.doc.XViewMiddleware', | ||
) | ||
|
||
ROOT_URLCONF = 'example.urls' | ||
|
||
INTERNAL_IPS = ( | ||
'127.0.0.1', | ||
) | ||
|
||
TEMPLATE_DIRS = ( | ||
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". | ||
# Always use forward slashes, even on Windows. | ||
# Don't forget to use absolute paths, not relative paths. | ||
[os.path.join(PROJECT_DIR, "templates")] | ||
) | ||
|
||
INSTALLED_APPS = ( | ||
'django.contrib.auth', | ||
'django.contrib.contenttypes', | ||
'django.contrib.sessions', | ||
'django.contrib.sites', | ||
'django.contrib.admin', | ||
'faq', | ||
) | ||
|
||
|
||
try: | ||
from local_settings import * | ||
except ImportError: | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<html> | ||
<head> | ||
<title>{% block title %}Django FAQ {% endblock %}</title> | ||
|
||
<style> | ||
|
||
.answer | ||
{ | ||
color: #CC0000; | ||
} | ||
|
||
body | ||
{ | ||
background-color: #CCC; | ||
} | ||
|
||
</style> | ||
|
||
</head> | ||
<body> | ||
|
||
{% block content %} | ||
{% endblock %} | ||
|
||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
{% extends "faq/base.html" %} | ||
|
||
{% block title %}{{ block.super }}: Example {% endblock %} | ||
|
||
{% block content %} | ||
<h1>{{ page_title }}</h1> | ||
|
||
<p> | ||
Demo typical faq page. Created on: {{ created_on|date:"M d, Y" }} | ||
</p> | ||
|
||
<h3>Questions</h3> | ||
|
||
<ol> | ||
{% for question in object_list %} | ||
|
||
<li> | ||
<a href="#{{ question.slug }}">{{ question.text }}</a> | ||
<br> | ||
<span class="answer">answer: {{ question.answer }}</span> | ||
</li> | ||
|
||
{% endfor %} | ||
</ol> | ||
|
||
|
||
<h3 style="margin-top: 1000px">Answers</h3> | ||
|
||
<ol style="margin-bottom: 1000px"> | ||
{% for question in object_list %} | ||
<li> | ||
<a id="{{ question.slug }}"> | ||
<h3>{{ question.text }}</h3> | ||
{{ question.answer }} | ||
</li> | ||
{% endfor %} | ||
</ol> | ||
|
||
|
||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from django.conf.urls.defaults import * | ||
from django.contrib import admin | ||
from django.conf import settings | ||
from views import faq_list | ||
|
||
admin.autodiscover() | ||
|
||
urlpatterns = patterns('', | ||
|
||
(r'^admin/(.*)', admin.site.root), | ||
url ( | ||
regex = r'^faq/$', | ||
view = faq_list, | ||
name = 'faq_list', | ||
), | ||
|
||
(r'^faq/(.*)', include('faq.urls')) | ||
|
||
) | ||
|
||
|
||
urlpatterns += patterns('', | ||
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from django.views.generic.list_detail import object_detail, object_list | ||
from faq.views import question_list | ||
|
||
def faq_list( request ): | ||
''' | ||
Display a typical FAQ view but more importantly an example of a basic way to "extend" or | ||
"override" an existing view from a "reusable apps". | ||
''' | ||
|
||
#NOTE: | ||
#Again just for example - we pass along a custom extra_context dict so even if the view we're reusing sets it's own | ||
#we are still allowed to provide further details we may need by passing along this argument. | ||
extra = { 'page_title': 'FAQ Details' } | ||
|
||
#NOTE: | ||
#we also pass along our own custom template_name to override the existing one that's set. | ||
return question_list(request, template_name='faq/faq_list.html', extra_context=extra) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from django.contrib import admin | ||
from models import Question | ||
from datetime import datetime | ||
|
||
|
||
class QuestionAdmin(admin.ModelAdmin): | ||
|
||
list_display = ['text', 'sort_order', 'created_by', 'created_on', 'updated_by', 'updated_on', 'status'] | ||
|
||
def save_model(self, request, obj, form, change): | ||
''' | ||
Overrided because I want to also set who created this instance. | ||
''' | ||
instance = form.save( commit=False ) | ||
if instance.id is None: | ||
new = True | ||
instance.created_by = request.user | ||
|
||
instance.updated_by = request.user | ||
instance.save() | ||
|
||
return instance | ||
|
||
admin.site.register(Question, QuestionAdmin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
|
||
""" | ||
Home base for all application enums. | ||
""" | ||
|
||
STATUS_ACTIVE = 1 | ||
STATUS_INACTIVE = 0 | ||
|
||
QUESTION_STATUS_CHOICES = ( | ||
(STATUS_ACTIVE, 'Active'), | ||
(STATUS_INACTIVE, 'Inactive') | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from django.db import models | ||
from django.db.models.query import QuerySet | ||
import datetime | ||
import enums | ||
|
||
|
||
class QuestionQuerySet(QuerySet): | ||
""" | ||
A basic ''QuerySet'' subclass, provides query functionality and some helper methods for an intuitive interface. | ||
""" | ||
|
||
def active(self, **kwargs): | ||
""" | ||
A utility method that filters results based on ''Question'' models that are only ''Active''. | ||
""" | ||
|
||
if kwargs.get('slug'): | ||
slug = kwargs['slug'] | ||
return self.filter(status__exact=enums.STATUS_ACTIVE, slug__exact=slug) | ||
else: | ||
return self.filter(status__exact=enums.STATUS_ACTIVE,) | ||
|
||
|
||
class QuestionManager(models.Manager): | ||
""" | ||
A basic ''Manager'' subclass which returns a ''QuestionQuerySet''. It provides simple access | ||
to helpful utility methods. | ||
""" | ||
|
||
def get_query_set(self): | ||
return QuestionQuerySet(self.model) | ||
|
||
def active(self, slug=None): | ||
return self.get_query_set().active(slug=slug) | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from django.db import models | ||
from datetime import datetime | ||
from django.utils.translation import ugettext_lazy as _ | ||
from django.contrib.auth.models import User | ||
from managers import QuestionManager | ||
import enums | ||
|
||
class FaqBase(models.Model): | ||
''' | ||
Base class for models. | ||
''' | ||
created_by = models.ForeignKey(User, null=True, editable=False, related_name="%(class)s_created_by" ) | ||
created_on = models.DateTimeField( _('created on'), default=datetime.now, editable=False, ) | ||
updated_on = models.DateTimeField( _('updated on'), editable=False ) | ||
updated_by = models.ForeignKey(User, null=True, editable=False ) | ||
|
||
class Meta: | ||
abstract = True | ||
|
||
class Question(FaqBase): | ||
""" | ||
Represents a frequently asked question. | ||
""" | ||
|
||
slug = models.SlugField( max_length=100, help_text="This is a unique identifier that allows your questions to display its detail view, ex 'how-can-i-contribute'", ) | ||
text = models.TextField(_('question'), help_text='The actual question itself.') | ||
answer = models.TextField( _('answer'), help_text='The answer text.' ) | ||
status = models.IntegerField( choices=enums.QUESTION_STATUS_CHOICES, default=enums.STATUS_INACTIVE, help_text="Only questions with their status set to 'Active' will be displayed. " ) | ||
sort_order = models.IntegerField(_('sort order'), default=0, help_text='The order you would like the question to be displayed.') | ||
|
||
objects = QuestionManager() | ||
|
||
class Meta: | ||
ordering = ['sort_order', 'created_on', ] | ||
|
||
def __unicode__(self): | ||
return self.text | ||
|
||
def save(self): | ||
self.updated_on = datetime.now() | ||
super(Question, self).save() | ||
|
Oops, something went wrong.