Welcome to Pinax’s documentation¶
Pinax is an open-source platform built on the Django Web Framework.
By integrating numerous reusable Django apps to take care of the things that many sites have in common, it lets you focus on what makes your site different.
Introduction¶
Pinax is an open-source platform built on the Django Web Framework.
By integrating numerous reusable Django apps to take care of the things that many sites have in common, it lets you focus on what makes your site different.
While our initial development was focused around a demo social networking site, Pinax is suitable for a wide variety of websites. We are working on number of editions tailored to intranets, event management, learning management, software project management and more.
Features¶
At this stage, there is:
- openid support
- email verification
- password management
- site announcements
- a notification framework
- user-to-user messaging
- friend invitation (both internal and external to the site)
- a basic twitter clone
- oembed support
- gravatar support
- interest groups (called tribes)
- projects with basic task and issue management
- threaded discussions
- wikis with multiple markup support
- blogging
- bookmarks
- tagging
- contact import (from vCard, Google or Yahoo)
- photo management
and much more coming…
History and Background¶
You can learn more about the history and motivation for Pinax in an interview with James Tauber on This Week in Django as well as his talk on Pinax at DjangoCon 2008 and talk on Pinax at PyCon 2009.
Installation¶
This covers installation from a release bundle. For information on installing a development version, see http://pinaxproject.com/docs/dev/contributing.html.
The release bundle has almost everything you need to get Pinax up and running. The only things not included are Python itself, the Python Imaging Library (PIL) and a database such as SQLite (which is included in Python 2.5+).
For more information on installing PIL, see Installing PIL.
Note
If you are on Mac OS X, make sure you have the Apple developer tools installed before proceeding with Pinax installation.
Installing Pinax¶
Pinax makes use of Python virtual environments (or virtualenvs) to isolate the various packages it uses from the rest of your system. Pinax comes with a script that will create the virtualenv for you and install Django and the various applications and libraries that make up Pinax.
To run this script, extract the release bundle, cd into it and run:
$ python scripts/pinax-boot.py <path-to-virtual-env-to-create>
This will set up the virtualenv and install everything.
For example, if you wanted to create your environment in a directory parallel to where you extracted the bundle you could run:
$ python scripts/pinax-boot.py ../pinax-env
If you use virtualenvwrapper (which we recommend), this would become:
$ python scripts/pinax-boot.py $WORKON_HOME/pinax-env
Activating the virtualenv¶
Any time you work on a project involving Pinax, you will want to activate the virtualenv.
This is done with:
$ source <path-to-virtual-env-created>/bin/activate
or, in our example above using ../pinax-env
:
$ source ../pinax-env/bin/activate
On Windows you would run:
$ ..\pinax-env\Scripts\activate.bat
With virtualenvwrapper, this becomes:
$ workon pinax-env
which you can run from anywhere on your filesystem.
Note that you will develop your Pinax-based project in a directory outside your virtualenv. As long as the virtualenv is active, your project will have access to all of the apps and libraries Pinax provides.
Starting a new Pinax project¶
The recommended way to start a new Pinax-based project is to clone one of the
existing projects. This is done via the pinax-admin clone_project
command which you can run once you are in your Pinax virtual-env.
You can get a list of available projects with:
(pinax-env)$ pinax-admin clone_project -l
This will show you a list of projects that you can base your new project on.
Just as quick demonstration, let’s start with the social_project. cd into the directory you’d like to create your new project in and run:
(pinax-env)$ pinax-admin clone_project social_project mysite
This will create a new Pinax project called ‘mysite’ in your current working directory.
Note
We recommend you don’t clone projects into the pinax-env
(the virtual
environment) directory. This directory is best left for only the
environment isolated away from your project. This enables you to:
- version your project separately from your Pinax environment
- blow away / upgrade your Pinax environment / try different Pinax versions, etc without affecting your project
Lastly, let’s get it running:
(pinax-env)$ cd mysite/
(pinax-env)$ python manage.py syncdb
(pinax-env)$ python manage.py runserver
Point your browser at http://localhost:8000/ and you should see the Pinax default homepage!
Note that mail and some notifications are queued rather than delivered immediately. See Sending Mail and Notices for details.
What’s next?¶
Look at our customization documentation to learn how you might customize your cloned project. If you are ready to deploy your project check out the deployment documentation.
Customization¶
As more sites are built using Pinax, more best practices will emerge, but for now what we recommend is:
- Always work off a stable release. The most current release is 0.7beta3.
- Use the pinax-admin clone_project command.
- Make necessary changes to the
settings.py
andurls.py
files in your copied directory. - Change the domain and display name of the Site in the admin interface.
- Develop your custom apps under your new project or anywhere on Python path.
- Develop your own templates under your new project.
Choosing a Project¶
Pinax provides several projects to use as a starting point for customization. Depending on your development style, you may prefer one project over the other.
- basic_project
- This project comes with the bare minimum set of applications and templates to get you started. It includes no extra tabs, only the profile and notices tabs are included by default. From here you can add any extra functionality and applications that you would like.
- cms_project_company
A very simple CMS that lets you set up templates and then edit content, including images, right in the frontend of the site.
The sample media, templates and content including in the project demonstrate a basic company website.
- cms_project_holidayhouse
A very simple CMS that lets you set up templates and then edit content, including images, right in the frontend of the site.
The sample media, templates and content including in the project demonstrate a basic site for holiday house rentals.
- code_project
- This project demonstrates group functionality and the tasks, wiki and topics apps. It is intended to be the starting point for things like code project management where each code project gets its own wiki, task tracking system and threaded discussions.
- intranet_project
- This project demonstrates a closed site requiring an invitation to join and not exposing any information publicly. It provides a top-level task tracking system, wiki and bookmarks. It is intended to be the starting point of sites like intranets.
- private_beta_project
- This project demonstrates the use of a waiting list and signup codes for sites in private beta. Otherwise it is the same as basic_project.
- sample_group_project
- This project demonstrates group functionality with a barebones group containing no extra content apps as well as two additional group types, tribes and projects, which show different membership approaches and content apps such as topics, wiki, photos and task management.
- social_project
This project demonstrates a social networking site. It provides profiles, friends, photos, blogs, tribes, wikis, tweets, bookmarks, swaps, locations and user-to-user messaging.
In 0.5 this was called
complete_project
.
pinax-admin clone_project¶
Pinax provides you with pinax-admin
, a command line utility. With
pinax-admin
you can quickly generate a cloned project. For example, if you
wanted to clone the basic_project you could simply do the following:
(pinax-env)$ pinax-admin clone_project basic_project mysite
Settings You Will (Possibly) Want To Override¶
Pinax-specific:
PINAX_THEME
CONTACT_EMAIL
URCHIN_ID
BBAUTH_APP_ID
BBAUTH_SHARED_SECRET
SITE_NAME
MAILER_PAUSE_SEND
SERVE_MEDIA
ACCOUNT_OPEN_SIGNUP
ACCOUNT_REQUIRED_EMAIL
ACCOUNT_EMAIL_VERIFICATION
EMAIL_CONFIRMATION_DAYS
LOGIN_REDIRECT_URLNAME
General to Django:
DEBUG
TEMPLATE_DEBUG
LOGGING_OUTPUT_ENABLED
ADMINS
MANAGERS
DATABASE_ENGINE
DATABASE_NAME
DATABASE_USER
DATABASE_PASSWORD
DATABASE_HOST
TIME_ZONE
SECRET_KEY
DEFAULT_FROM_EMAIL
SERVER_EMAIL
SEND_BROKEN_LINK_EMAILS
EMAIL_HOST
EMAIL_HOST_USER
EMAIL_HOST_PASSWORD
EMAIL_SUBJECT_PREFIX
LOGIN_URL
base.html
versus site_base.html
¶
In the sample projects, templates/base.html
is intended for overall page structure
whereas templates/site_base.html
is intended for adding site-specific content that
is to be found on all pages (things like logo, navigation or footers).
If you are writing a theme to be used across multiple sites, you should modify
base.html
, not site_base.html
. If you want to keep a particular theme
but modify content for a specific site, you should modify site_base.html
.
Changing Avatar/Gravatar defaults¶
By default Pinax assigns to users the Gravatar icon and uses the Gravatar icon
system. If you want your own personal site avatar default, simply go to the
settings.py
in your project root and add these two lines of code:
# avatar controls
AVATAR_DEFAULT_URL = MEDIA_URL + '<our_custom_avatar.jpg>'
AVATAR_GRAVATAR_BACKUP = False
Adding Tabs¶
See Tab Navigation
Deployment¶
In short:
- Create a
local_settings.py
alongsidesettings.py
for your host-specific settings (like database connection, email, etc). - Configure mod_wsgi or mod_python.
- Set up
cron
job for mailer and asynchronous notifications.
Using mod_wsgi¶
If you are using mod_wsgi, which we recommend, you will need to provide a WSGI
script. All projects include a deploy/
directory which contains this
script named pinax.wsgi
. You may modify this file as it best suits you.
Here is a basic configuration for Apache (assuming you are using Python 2.5):
WSGIDaemonProcess mysite-production python-path=/path/to/virtualenvs/pinax-env/lib/python2.5/site-packages
WSGIProcessGroup mysite-production
WSGIScriptAlias / /path/to/project/deploy/pinax.wsgi
<Directory /path/to/project/deploy>
Order deny,allow
Allow from all
</Directory>
The above configuration will likely need to be modified before use. Most
specifically make sure the python-path
option points to the right Python
version. We encourage you to read about WSGIDaemonProcess to learn more
about what you can configure.
Using mod_python¶
While we highly recommend you use mod_wsgi you may need to use mod_python. In this case we have provided the correct hooks for you to use Pinax. Here is a sample Apache config that you can use:
<Location "/">
SetHandler python-program
PythonHandler social_project.deploy.modpython
SetEnv DJANGO_SETTINGS_MODULE social_project.settings
PythonDebug On
PythonPath "['/path/to/pinax/projects'] + sys.path"
</Location>
Note
It is important to note that you should pay careful attention to the
value of PythonHandler
above. It is not using
django.core.handlers.modpython
. It is using a mod_python handler
located in your project’s deploy/
directory. The reason why we have
our own mod_python handler is because we need to setup the Pinax
environment otherwise you will see failing imports.
Sending Mail and Notices¶
Both mail messages and (some) notifications are queued for asynchronous delivery. To actually deliver them you need to run:
python manage.py send_mail
and:
python manage.py emit_notices
on a frequent, regular basis.
Because failed mail will be deferred, you need an additional, less frequent, run of:
python manage.py retry_deferred
We recommend setting up some scripts to run these commands within your virtual environment. You can use the following shell script as the basis for each management command:
#!/bin/sh
WORKON_HOME=/home/user/virtualenvs
PROJECT_ROOT=/path/to/project
# activate virtual environment
. $WORKON_HOME/pinax-env/bin/activate
cd $PROJECT_ROOT
python manage.py send_mail >> $PROJECT_ROOT/logs/cron_mail.log 2>&1
Let’s assume the scripts you create from above are stored in
$PROJECT_ROOT/cron
. You can now setup the cron job similar to:
* * * * * /path/to/project/cron/send_mail.sh
* * * * * /path/to/project/cron/emit_notices.sh
0,20,40 * * * * /path/to/project/cron/retry_deferred.sh
This runs send_mail
and emit_notices
every minute and
retry_deferred
every 20 minutes.
Media files¶
Pinax makes it very easy to combine all your applications’ media files into one single location (see Media Handling for details). Serving them more or less comes down again to how you do it with Django itself.
There is an example on how to serve those files with the development server in Serving static files during development.
In a production environment you, too, have to merge those files before you can serve them. Regarding actually serving those files then, see Django’s deployment documentation for details.
Media Handling¶
This document explains how Pinax handles media files across external and internal applications and themes.
Basic media handling¶
If you want to override default media files, place yours under <project_name>/media/… with the same path. For example:
Original file:
src/pinax/media/default/pinax/images/logo.png
Your file:
<project_name>/media/pinax/images/logo.png
Locations of media files¶
If you want to use Pinax’ media handling with your own Django apps, please make sure you put the media files like JavaScript, cascading stylesheets (CSS) and images in the following directory structure:
<app_name>/media/<app_name>/(js|img|css)
Doubling your <app_name> is required to prevent name collision of media files while deploying.
Site specific media files goes to:
<project_name>/media/siteExample.js
The special static file service view should be able to serve the media files in development.
build_media management command¶
The build_media script collects the media files from Pinax and all the
installed apps and arranges them under the
<project_name>/site_media/static
folder.
The command:
<project_name>/python manage.py build_media --all
will collect the media files from Pinax and all the apps and places them in
the folder defined in the STATIC_ROOT
setting.
If you have two apps with the same file and the same relative path it’s advised
to use the --interactive
option so the script will prompt you to choose
which one to use. This is useful in case you want to overwrite default media
files with your custom app for example. Remember to remove the site_media
folder before you use this option or the script will prompt you for each file.
Please also refer to the help of the build_media management command by running:
<project_name>/python manage.py build_media --help
resolve_media management command¶
To quickly resolve the full file path of a media file on the filesystem,
you can pass its expected URL path(s) to the resolve_media
management
command, e.g.:
$ ./manage resolve_media pinax/css/base.css
Resolving css/site_tabs.css:
/Users/jtauber/virtualenvs/mysite/lib/python2.6/site-packages/Pinax-0.7beta3-py2.6.egg/pinax/media/default/pinax/css/base.css
If multiple locations are found which match the given path it will list all of them, sorted by its importance.
Serving static files during development¶
Pinax provides the static file serving view staticfiles.views.serve
to
handle the app and theme media as well as other media files found in the
MEDIA_ROOT
directory. Make sure your projects’ urls.py contains the
following snippet below the rest of the url configuration:
from django.conf import settings
if settings.SERVE_MEDIA:
urlpatterns += patterns('',
(r'^site_media/', include('staticfiles.urls')),
)
Group support¶
Group support in Pinax allows you to define any type of group. Pinax comes bundled with two types of groups:
- tribes — used in social_project
- projects — used in code_project
A group app can have any content object associated with it. Pinax includes several apps that are group aware:
- tasks
- photos
- wiki
- topics
The idea is a group aware app has the ability to work with or without a group association. This is done using a nullable generic foreign key. Pinax comes with an app to do much of the work to make this all happen.
Writing your own group aware domain objects¶
If you want to write your own domain object that is group aware start an app for it. Follow the guidelines below and you’ll be all set.
Models¶
Let’s look at a basic model that stores data for a blog:
class Blog(models.Model):
name = models.CharField(max_length=140)
To enable group support for this minimal domain object add in a nullable generic foreign key:
from django.db import models
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
class Blog(models.Model):
name = models.CharField(max_length=140)
object_id = models.IntegerField(null=True)
content_type = models.ForeignKey(ContentType, null=True)
group = generic.GenericForeignKey("object_id", "content_type")
We use a nullable generic foreign key to enable it to be optional and we don’t know what group model it will point to.
Views¶
The views you write for your app need to be aware there may be a group association. This is to ensure you properly work with the right subset of data from your models.
Let’s take a look at a view that would be a bit naive:
def blog_list(request):
blogs = Blog.objects.all()
return render_to_response("blog/blog_list.html", {
"blogs": blogs,
}, context_instance=RequestContext(request))
Assuming Blog
is the first model presented above this will work fine.
However, once you introduce the generic foriegn key you will potentially be
selecting objects that don’t belong.
To deal with situation we introduced a ContentBridge
object. This object
is passed to your view from the layer above. Let’s see how to work with it:
from django.http import Http404
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.core.exceptions import ObjectDoesNotExist
def blog_list(request, group_slug=None, bridge=None):
if bridge is not None:
try:
group = bridge.get_group(group_slug)
except ObjectDoesNotExist:
raise Http404
else:
group = None
if group:
blogs = group.content_objects(Blog)
else:
blogs = Blog.objects.all()
return render_to_response("blog/blog_list.html", {
"group": group,
"blogs": blogs,
}, context_instance=RequestContext(request))
Pretty straight-foward code to handle both group and no group association. If you are writing an app that can guarantee group association you can definitely make it simpler.
Checking for user membership¶
In many cases you might want to check if the authenticated user has membership in the group. To do this:
if not request.user.is_authenticated():
is_member = False
else:
is_member = group.user_is_member(request.user)
URLs¶
The urls.py
file of your app will not need anything special. Most of that
is handled by Pinax. However, URL reversal needs to be group aware. We have
some helpers to help you work with this easily.
Let’s say you have the following urls.py
:
from django.conf.urls.defaults import *
urlpatterns = patterns("",
url(r"^blogs/$", "blog.views.blog_list", name="blog_list"),
url(r"^blog/(?P<slug>[-\w]+)/$", "blog.views.blog_detail", name="blog_detail"),
)
To ensure URLs to blog_list
are correctly generated you will need to use
reverse
located on the ContentBridge
object:
def some_view_with_redirect(request, bridge=None):
...
return HttpResponseRedirect(bridge.reverse("blog_list", group))
The reverse
method work almost identical to Django’s reverse
. It is
essentially a wrapper. To reverse the blog_detail
URL:
blog = Blog.objects.get(pk=1)
bridge.reverse("blog_detail", group, kwargs={"slug": blog.slug})
Note
You should be aware that only kwargs
work with the bridge reverse
.
This is significant because URLs with args
mapping will fail reversal.
The reason behind this is because Django does not allow mixing of args
and kwargs
when performing URL reversal.
There are some cases when you don’t have easy access to the ContentBridge
.
You may only have access to a domain object instance. You can get access to
the ContentBridge
from the instance. For example:
blog = Blog.objects.get(pk=1)
blog.content_bridge.reverse(...)
URL reversal in templates¶
In Django you may be familiar with the {% url %}
templatetag. This is
basically a wrapper around reverse
. We provide a similar tag, but works
with our ContentBridge.reverse
. Here is how you might use it:
{% load group_tags %}
<a href="{% groupurl blog_detail group slug=blog.slug %}">{{ blog.name }}</a>
The {% groupurl %}
templatetag will fall back to normal Django URL reversal
if the value of the passed in group
is None
. This enables the ability
to work with no group association.
Settings¶
Depending on what profile and which apps out of it you’re using with your
Pinax project you have a collection of options for your settings.py
at
your disposal. This listing only includes those that are supported by the
internal applications or are used in the sample project settings (excluding
those that are already described by Django’s settings reference. If you
want to know the available settings for any of the external apps, please refer
to its docoumentation.
ACCOUNT_OPEN_SIGNUP¶
Applications: | pinax.apps.signup_codes |
---|
This setting lets you configure whether the site should allow new users to register accounts if they don’t provide any kind of signup code.
BBAUTH_APP_ID¶
Applications: | pinax.apps.bbauth |
---|
This setting is used to allow auth through Yahoo!’s Browser-Based Authentication service.
BEHIND_PROXY¶
Applications: | pinax.apps.blog |
---|
If your site is behind a proxy server, set this setting accordingly so that
the users’ real IP addresses are stored when they create blog posts. When
activated the blog takes the user’s IP addresse from
request.META['HTTP_X_FORWARDED_FOR']
instead of
request.META['REMOTE_ADDR']
.
COMBINED_INBOX_COUNT_SOURCES¶
Applications: | pinax.apps.misc |
---|
With this setting you can specify a list applications that write to the users
inbox in order to get the current inbox count for the current user. In fact
you don’t specify the application but a context processor function which you
specify here. If you for example create a project based on the
social_project
template, the messages
, notification
and
friends_app
all provide information that affects the inbox count.
Such a context processor should return a dictionary with one or more entries for the additional inbox count.
EMAIL_CONFIRMATION_DAYS¶
Applications: | emailnotification (external) |
---|
This way you can configure the number of days, confirmation email should be valid. For further details please see the documentation of the application itself.
FEEDUTIL_SUMMARY_LEN¶
Applications: | feedutil (external) |
---|---|
Default: | 150 |
Number of characters used for summary-attributes in feeds.
FORCE_LOWERCASE_TAGS¶
Applications: | tagging (external) |
---|---|
Default: | False |
If set to True
all tags will first be converted to lowercase before they
are saved to the database.
LOGIN_REDIRECT_URLNAME¶
Applications: | pinax.apps.account |
---|
This setting is used by pinax.apps.account
and allows you to specify the
name of a named URL as redirection target. If it is not set,
LOGIN_REDIRECT_URL
will get used instead.
NOTIFICATION_LANGUAGE_MODULE¶
Application: | notification (external) |
---|---|
Default: | False |
This way you can specify what model holds the language selection of a specific
user – e.g. account.Account
. The model has to have a foreign key to the
the user model (user
) and also provide a language
field, which is then
used by the notification
application.
PINAX_ITEMS_PER_FEED¶
Applications: | pinax.apps.blog |
---|---|
Default: | 20 |
With this option the number of posts that should be served in the feeds generated by Pinax’ blogging application can be configured.
PINAX_ROOT¶
Application: | pinax.apps.staticfiles |
---|
Normally you shouldn’t need to change this setting. It’s a reference to where
Pinax itself is installed so that you can easily re-use for instance templates
from that location or work with the original static files like
the build_media
command does. There this settng is used to find the
media files of those internal applications used in your project, which are
then copied into one central location.
For more on this topic take a look at Media Handling.
It is also used by default in project settings for determining a template directory.
PINAX_THEME¶
Applications: | |
---|---|
Default: | "default" |
With Pinax your site can have multiple themes available. This option now
determines, which one of these should be used. In practice the value of
PINAX_THEME
becomes part of the file-paths the build_media
command is
looking for when trying to combine all your media files into one single
location. A small example:
src/pinax/media/default/pinax/images/logo.png
is a file that is specific to the “default” theme for Pinax while:
src/pinax/media/new_hotness/pinax/images/logo.png
would only be available in the “new_hotness” theme.
This setting is also used for the core templates that are provided with Pinax
by default. The default settings.py
files provided by Pinax for instance
load templates from following locations:
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), "templates"),
os.path.join(PINAX_ROOT, "templates", PINAX_THEME),
)
Note that this setting only applies to Pinax’ core media files and templates and is not used either in the internal nor the external apps by default.
RESTRUCTUREDTEXT_FILTER_SETTINGS¶
Applications: | pinax.apps.blog |
---|---|
Default: | {} |
Using this option you can pass additional settings as dictionary through the
restructuredtext
template library to the underlying
docutils.core.publish_parts
function.
SERVE_MEDIA¶
This option is used in the standard projects’ URLconf to determine, if
django.views.static.serve
should be used to serve static files. By default
this settings is bound to the DEBUG
setting in the default
settings.py
.
STATICFILES_DIRS¶
Default: | [] |
---|
This setting defines the additional locations the staticfiles
app will
traverse when looking for media files, e.g. if you use the
build_media or
resolve_media management command or
use the static file serving view.
It should be defined as a sequence of (label, path)
tuples, e.g.:
STATICFILES_DIRS = (
('pinax', os.path.join(PINAX_ROOT, 'media', PINAX_THEME)),
('my_project', os.path.join(PROJECT_ROOT, 'media')),
)
STATICFILES_PREPEND_LABEL_APPS¶
Default: | ('django.contrib.admin',) |
---|
A sequence of app paths that have the media files in <app>/media
, not in
<app>/media/<app>
, e.g. django.contrib.admin
.
STATICFILES_MEDIA_DIRNAMES¶
Default: | ('media',) |
---|
A sequence of directory names to be used when searching for media files in
installed apps, e.g. if an app has its media files in <app>/static
use:
STATICFILES_MEDIA_DIRNAMES = (
'media',
'static',
)
URCHIN_ID¶
Applications: | pinax.apps.analytics |
---|
Used by pinax.apps.analytics
as part of your account information on Google
Analytics. Based on this setting the JavaScript is generated that is then
embedded into your website to allow Google Analytics to track your traffic.
MARKUP_CHOICES¶
Applications: | pinax.apps.blog , pinax.apps.tasks |
---|---|
Default: | (('restructuredtext', u'reStructuredText'), ('textile', u'Textile'), ('markdown', u'Markdown'), ('creole', u'Creole'),) |
The actual origin of this setting is django-wikiapp which is one of the
external applications Pinax integrates. pinax.apps.blog
uses it to
determine, how a post’s content should be converted from plain text to HTML.
Dependencies¶
This documents what apps use what other apps and what external libs.
- account
- uses apps misc, emailconfirmation, friends, profiles, timezones, microblogging
- ajax_validation
- uses library simplejson
- announcements
- uses app notification and library atomformat
- authsub
- uses library gdata
- avatar
- uses library PIL
- basic_profiles
- uses app notification
- bbauth
- uses library ybrowserauth
- blog
- uses apps friends, notification, tagging, threadedcomments and library atomformat
- bookmarks
- uses apps tagging, voting and library atomformat
- misc
- uses apps blog, bookmarks, mailer, tribes, microblogging, voting
- django_extensions
- uses a wide range of libraries depends on command
- django_openid
- uses libraries openid, yadis
- djangologging
- uses library pygments
- emailconfirmation
- uses app mailer
- friends
- uses apps emailconfirmation, mailer, notification and libraries gdata, simplejson, vobject, ybrowserauth
- friends_app
- uses apps account, friends, notification
- messages
- uses app mailer, notification
- notification
- uses app mailer and library atomformat
- oembed
- uses library simplejson
- photologue
- uses app tagging and library PIL
- photos
- uses apps photologue, projects, tagging, tribes
- profiles
- uses apps account, friends, gravatar, notification, photos, timezones, microblogging
- projects
- uses apps friends, notification, photos, tagging, things, threadedcomments, wiki
- swaps
- uses apps notification, tagging, threadedcomments
- tag_app
- uses apps blog, bookmarks, photos, projects, tagging, tribes, wiki
- timezones
- uses library pytz
- tribes
- uses apps friends, notification, photos, tagging, things, threadedcomments, wiki, microblogging
- wiki
- uses apps notification, tagging and libraries atomformat, creoleparser, diff_match_patch, docutils
- microblogging
- uses apps account, notification, tribes and libraries atomformat, twitter
Frequently asked questions¶
Does Pinax work on Django 1.1?¶
Yes. Pinax 0.7 ships with Django 1.0.4 by default. Django 1.1 came too late in our 0.7 release cycle. However, we tested it on Django 1.1 to ensure it works and it works well. To use Django 1.1 in your Pinax project simply follow our installation documentation and once you are in the virtual environment run:
pip install -U Django==1.1.1
This will install Django 1.1.1 over 1.0.4.
Does Pinax work on Django 1.2?¶
Yes and no. Our stable release 0.7.X (at 0.7.1) does not support Django 1.2. We will attempt to make 0.7.2 compatible to run on Django 1.2. Installing Django 1.2 over 1.0 that ships with 0.7 will work the same way as seen above. We hope to release 0.7.2 soon. There are no timelines.
On the other hand our development version of Pinax will ship with Django 1.2. Stay tuned for more news regarding the releases of 0.9.
How do I change the references to example.com¶
example.com
is the default value for
Site.objects.get(pk=settings.SITE_ID).domain
. This comes from the Django
contrib app named sites
. It is enabled in Pinax by default. Pinax uses
this value to construct URLs back to your site in e-mails, for example. There
are two ways to change this value. First, you can modify it in the shell
(using python manage.py shell
):
>>> from django.conf import settings
>>> from django.contrib.sites.models import Site
>>> site = Site.objects.get(pk=settings.SITE_ID)
>>> site.domain = "localhost:8000"
>>> site.name = "Development site"
>>> site.save()
Alternatively, you can perform the same action through the admin interface.
Why won’t my e-mail send?¶
Pinax queues all e-mail for delivery. This is the behavior of django-mailer. All messages are stored in the database. This enables you to view what will be sent via the admin during development.
To send the messages that are queued you should use the send_mail
management command. To invoke this you would run:
python manage.py send_mail
Be sure you have set the appropriate EMAIL_*
settings. A full list of
these settings can be found in Django settings documentation. Our
deployment documentation gives
instructions on how to set this up on a cron.
Also, some e-mail may occur as a result of notifications. Some notifications are queued. Be sure you run:
python manage.py emit_notices
to clear the notification queue and get those e-mails queued.
Contributing to Pinax¶
We are always looking for people wanting to improve Pinax itself. This document outlines the necessary bits to begin contributing to Pinax.
Getting started¶
The Pinax source code is hosted on GitHub. This means you must have git installed locally. We recommend you create an account on GitHub allowing you to watch and fork the Pinax source code.
You will want to be sure that your git configuration is set for making commits to a repository. Check the following:
git config user.name
git config user.email
If the output of any of the two commands above are not entirely correct you can easily correct them:
git config --global user.name "First Last"
git config --global user.email "email@somewhere.com"
It is critical you set this information up correctly. It helps us identify who you are when you start giving us those awesome patches.
Grabbing the source code¶
Once you have forked the Pinax source code you can now make a clone of it to your local disk. To do this:
git clone git@github.com:<username>/pinax.git
This will create new directory named pinax
which now contains the Pinax
source tree ready for you to get started.
Setting up your environment¶
Now that you’ve cloned the source code you are ready to get your environment
setup to work on Pinax. This section also applies if you are looking to just
run off the latest code. We’ll assume that your current working directory is
from within the clone (the pinax
directory):
python scripts/pinax-boot.py --development --source=. ../pinax-dev
source ../pinax-dev/bin/activate
If you use virtualenvwrapper you could alternatively do:
python scripts/pinax-boot.py --development --source=. $WORKON_HOME/pinax-dev
workon pinax-dev
Finally, you need to install the dependencies for the development version:
pip install --requirement requirements/external_apps.txt
Committing code¶
The great thing about using a distributed versioning control system like git is that everyone becomes a committer. When other people write good patches it makes it very easy to include their fixes/features and give them proper credit for the work.
We recommend that you do all your work on Pinax in a separate branch. When you are ready to work on a bug or a new feature create yourself a new branch. The reason why this is important is you can commit as often you like. When you are ready you can merge in the change. Let’s take a look at a common workflow:
git checkout -b task-1-work
... do work and git commit often ...
git push origin task-1-work
git checkout -b task-1
git merge --squash --no-commit task-1-work
git commit -m "Fixed #1 — added a great new feature"
git push origin task-1
The reason we have created two new branches is to stay off of master
.
Keeping master clean of only upstream changes makes yours and ours lives
easier. You can then send us a pull request for the fix/feature from the
“ready” branch. Then we can easily review it and even take a look at the
individual commits for why you may have done something. If we say that
you’ve done something slightly wrong you can now go back to the task-1
branch and correct it. Let’s see how we might do this:
git checkout -b task-1-work
... fix and git commit often ...
git push
git branch -D task-1
git checkout -b task-1
git merge --squash --no-commit task-1-work
git commit -m "Fixed #1 — added a great new feature"
git push
Send another pull request and we can review the fix.
Writing commit messages¶
Writing a good commit message makes it simple for us to identify what your commit does from a high-level. We are not too picky, but there are some basic guidelines we’d like to ask you to follow.
Fixed #1 — added some feature
We ask that you indicate which task you have fixed (if the commit fixes it) or if you are working something complex you may want or be asked to only commits parts:
Refs #1 — added part one of feature X
As said earlier we are not too picky (some core developers may change commit messages before pulling in your changes), but as you get the basics down you make the process of getting your patch into core faster.
Another critical part is that you keep the first line as short and sweet as possible. This line is important because when git shows commits and it has limited space or a different formatting option is used the first line becomes all someone might see. If you need to explain why you made this change or explain something in detail use this format:
Fixed #13 — added time travel
You need to be driving 88 miles per hour to generate 1.21 gigawatts of
power to properly use this feature.