Fixed #627 -- BACKWARDS-INCOMPATIBLE CHANGE. Admin is now an app, not a middleware. See BackwardsIncompatibleChanges for a full list of changes and information on how to update your code.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@948 bcc190cf-cafb-0310-a4f2-bffc1f526a37
|
@ -27,22 +27,28 @@ MEDIA_ROOT = ''
|
||||||
# Example: "http://media.lawrence.com"
|
# Example: "http://media.lawrence.com"
|
||||||
MEDIA_URL = ''
|
MEDIA_URL = ''
|
||||||
|
|
||||||
|
# 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 = '/media/'
|
||||||
|
|
||||||
# Make this unique, and don't share it with anybody.
|
# Make this unique, and don't share it with anybody.
|
||||||
SECRET_KEY = ''
|
SECRET_KEY = ''
|
||||||
|
|
||||||
# List of callables that know how to import templates from various sources.
|
# List of callables that know how to import templates from various sources.
|
||||||
TEMPLATE_LOADERS = (
|
TEMPLATE_LOADERS = (
|
||||||
# 'django.core.template.loaders.app_directories.load_template_source',
|
|
||||||
'django.core.template.loaders.filesystem.load_template_source',
|
'django.core.template.loaders.filesystem.load_template_source',
|
||||||
|
'django.core.template.loaders.app_directories.load_template_source',
|
||||||
# 'django.core.template.loaders.eggs.load_template_source',
|
# 'django.core.template.loaders.eggs.load_template_source',
|
||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE_CLASSES = (
|
||||||
"django.middleware.common.CommonMiddleware",
|
"django.middleware.common.CommonMiddleware",
|
||||||
|
"django.middleware.sessions.SessionMiddleware",
|
||||||
"django.middleware.doc.XViewMiddleware",
|
"django.middleware.doc.XViewMiddleware",
|
||||||
)
|
)
|
||||||
|
|
||||||
ROOT_URLCONF = '{{ project_name }}.settings.urls.main'
|
ROOT_URLCONF = '{{ project_name }}.urls'
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = (
|
||||||
# Put strings here, like "/home/html/django_templates".
|
# Put strings here, like "/home/html/django_templates".
|
|
@ -1,18 +0,0 @@
|
||||||
# Django settings for {{ project_name }} project admin site.
|
|
||||||
|
|
||||||
from main import *
|
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
|
||||||
# Put strings here, like "/home/html/django_templates".
|
|
||||||
)
|
|
||||||
ROOT_URLCONF = '{{ project_name }}.settings.urls.admin'
|
|
||||||
MIDDLEWARE_CLASSES = (
|
|
||||||
'django.middleware.sessions.SessionMiddleware',
|
|
||||||
'django.middleware.admin.AdminUserRequired',
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
)
|
|
||||||
|
|
||||||
# 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 = '/media/'
|
|
|
@ -1,6 +0,0 @@
|
||||||
from django.conf.urls.defaults import *
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
|
||||||
(r'^admin/', include('django.conf.urls.admin')),
|
|
||||||
(r'^r/', include('django.conf.urls.shortcut')),
|
|
||||||
)
|
|
|
@ -3,4 +3,7 @@ from django.conf.urls.defaults import *
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
# Example:
|
# Example:
|
||||||
# (r'^{{ project_name }}/', include('{{ project_name }}.apps.foo.urls.foo')),
|
# (r'^{{ project_name }}/', include('{{ project_name }}.apps.foo.urls.foo')),
|
||||||
|
|
||||||
|
# Uncomment this for admin:
|
||||||
|
# (r'^admin/', include('django.contrib.admin.urls.admin')),
|
||||||
)
|
)
|
Before Width: | Height: | Size: 80 B After Width: | Height: | Size: 80 B |
Before Width: | Height: | Size: 838 B After Width: | Height: | Size: 838 B |
Before Width: | Height: | Size: 58 B After Width: | Height: | Size: 58 B |
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 199 B |
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 212 B |
Before Width: | Height: | Size: 843 B After Width: | Height: | Size: 843 B |
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 844 B |
Before Width: | Height: | Size: 176 B After Width: | Height: | Size: 176 B |
Before Width: | Height: | Size: 299 B After Width: | Height: | Size: 299 B |
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
Before Width: | Height: | Size: 145 B After Width: | Height: | Size: 145 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 390 B |
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 181 B |
Before Width: | Height: | Size: 319 B After Width: | Height: | Size: 319 B |
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 667 B |
Before Width: | Height: | Size: 341 B After Width: | Height: | Size: 341 B |
Before Width: | Height: | Size: 116 B After Width: | Height: | Size: 116 B |
Before Width: | Height: | Size: 186 B After Width: | Height: | Size: 186 B |
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
Before Width: | Height: | Size: 606 B After Width: | Height: | Size: 606 B |
Before Width: | Height: | Size: 358 B After Width: | Height: | Size: 358 B |
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 398 B |
Before Width: | Height: | Size: 355 B After Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 552 B |
Before Width: | Height: | Size: 612 B After Width: | Height: | Size: 612 B |
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 401 B |
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 200 B |
Before Width: | Height: | Size: 932 B After Width: | Height: | Size: 932 B |
Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B |
Before Width: | Height: | Size: 351 B After Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 354 B |
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block title %}Page not found{% endblock %}
|
{% block title %}Page not found{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">Home</a> › Server error</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="/">Home</a> › Server error</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base" %}
|
{% extends "admin/base" %}
|
||||||
|
|
||||||
{% block title %}{{ title }} | Django site admin{% endblock %}
|
{% block title %}{{ title }} | Django site admin{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block coltype %}colMS{% endblock %}
|
{% block coltype %}colMS{% endblock %}
|
||||||
{% block bodyclass %}dashboard{% endblock %}
|
{% block bodyclass %}dashboard{% endblock %}
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}{% endblock %}
|
{% block breadcrumbs %}{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
<div class="breadcrumbs"><a href="../../../../">Home</a> › <a href="../../">{{ module_name }}</a> › <a href="../">{{ object|truncatewords:"18" }}</a> › History</div>
|
<div class="breadcrumbs"><a href="../../../../">Home</a> › <a href="../../">{{ module_name }}</a> › <a href="../">{{ object|truncatewords:"18" }}</a> › History</div>
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Bookmarklets</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> › <a href="../">Documentation</a> › Bookmarklets</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Documentation</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block extrahead %}
|
{% block extrahead %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block coltype %}colSM{% endblock %}
|
{% block coltype %}colSM{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name }}</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name }}</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block coltype %}colSM{% endblock %}
|
{% block coltype %}colSM{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block coltype %}colSM{% endblock %}
|
{% block coltype %}colSM{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Views</a> › {{ name }}</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Views</a> › {{ name }}</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block coltype %}colSM{% endblock %}
|
{% block coltype %}colSM{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a></div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a></div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password change</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password change</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password change</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password change</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password reset</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password reset</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "base_site" %}
|
{% extends "admin/base_site" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password reset</div>{% endblock %}
|
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">Home</a> › Password reset</div>{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from django.models.auth import log
|
from django.models.admin import log
|
||||||
from django.core import template
|
from django.core import template
|
||||||
|
|
||||||
class AdminLogNode(template.Node):
|
class AdminLogNode(template.Node):
|
|
@ -6,7 +6,7 @@ from django.core.template import loader
|
||||||
from django.core.exceptions import Http404, ObjectDoesNotExist, PermissionDenied
|
from django.core.exceptions import Http404, ObjectDoesNotExist, PermissionDenied
|
||||||
from django.core.extensions import DjangoContext as Context
|
from django.core.extensions import DjangoContext as Context
|
||||||
from django.core.extensions import get_object_or_404, render_to_response
|
from django.core.extensions import get_object_or_404, render_to_response
|
||||||
from django.models.auth import log
|
from django.models.admin import log
|
||||||
from django.utils.html import strip_tags
|
from django.utils.html import strip_tags
|
||||||
from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
|
from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
|
||||||
from django.utils.text import capfirst, get_text_list
|
from django.utils.text import capfirst, get_text_list
|
||||||
|
@ -49,7 +49,7 @@ def get_query_string(original_params, new_params={}, remove=[]):
|
||||||
return '?' + '&'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
|
return '?' + '&'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return render_to_response('index', {'title': 'Site administration'}, context_instance=Context(request))
|
return render_to_response('admin/index', {'title': 'Site administration'}, context_instance=Context(request))
|
||||||
index = staff_member_required(index)
|
index = staff_member_required(index)
|
||||||
|
|
||||||
def change_list(request, app_label, module_name):
|
def change_list(request, app_label, module_name):
|
||||||
|
@ -266,7 +266,7 @@ def change_list(request, app_label, module_name):
|
||||||
else:
|
else:
|
||||||
pass # Invalid argument to "list_filter"
|
pass # Invalid argument to "list_filter"
|
||||||
|
|
||||||
raw_template = ['{% extends "base_site" %}\n']
|
raw_template = ['{% extends "admin/base_site" %}\n']
|
||||||
raw_template.append('{% block bodyclass %}change-list{% endblock %}\n')
|
raw_template.append('{% block bodyclass %}change-list{% endblock %}\n')
|
||||||
if not is_popup:
|
if not is_popup:
|
||||||
raw_template.append('{%% block breadcrumbs %%}<div class="breadcrumbs"><a href="../../">Home</a> › %s</div>{%% endblock %%}\n' % capfirst(opts.verbose_name_plural))
|
raw_template.append('{%% block breadcrumbs %%}<div class="breadcrumbs"><a href="../../">Home</a> › %s</div>{%% endblock %%}\n' % capfirst(opts.verbose_name_plural))
|
||||||
|
@ -538,7 +538,7 @@ def _get_template(opts, app_label, add=False, change=False, show_delete=False, f
|
||||||
admin_field_objs = opts.admin.get_field_objs(opts)
|
admin_field_objs = opts.admin.get_field_objs(opts)
|
||||||
ordered_objects = opts.get_ordered_objects()[:]
|
ordered_objects = opts.get_ordered_objects()[:]
|
||||||
auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
|
auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
|
||||||
t = ['{% extends "base_site" %}\n']
|
t = ['{% extends "admin/base_site" %}\n']
|
||||||
t.append('{% block extrahead %}')
|
t.append('{% block extrahead %}')
|
||||||
|
|
||||||
# Put in any necessary JavaScript imports.
|
# Put in any necessary JavaScript imports.
|
||||||
|
@ -1087,7 +1087,7 @@ def delete_stage(request, app_label, module_name, object_id):
|
||||||
log.log_action(request.user.id, opts.get_content_type_id(), object_id, obj_repr, log.DELETION)
|
log.log_action(request.user.id, opts.get_content_type_id(), object_id, obj_repr, log.DELETION)
|
||||||
request.user.add_message('The %s "%s" was deleted successfully.' % (opts.verbose_name, obj_repr))
|
request.user.add_message('The %s "%s" was deleted successfully.' % (opts.verbose_name, obj_repr))
|
||||||
return HttpResponseRedirect("../../")
|
return HttpResponseRedirect("../../")
|
||||||
return render_to_response('delete_confirmation_generic', {
|
return render_to_response('admin/delete_confirmation', {
|
||||||
"title": "Are you sure?",
|
"title": "Are you sure?",
|
||||||
"object_name": opts.verbose_name,
|
"object_name": opts.verbose_name,
|
||||||
"object": obj,
|
"object": obj,
|
||||||
|
@ -1102,7 +1102,7 @@ def history(request, app_label, module_name, object_id):
|
||||||
order_by=("action_time",), select_related=True)
|
order_by=("action_time",), select_related=True)
|
||||||
# If no history was found, see whether this object even exists.
|
# If no history was found, see whether this object even exists.
|
||||||
obj = get_object_or_404(mod, pk=object_id)
|
obj = get_object_or_404(mod, pk=object_id)
|
||||||
return render_to_response('admin_object_history', {
|
return render_to_response('admin/object_history', {
|
||||||
'title': 'Change history: %r' % obj,
|
'title': 'Change history: %r' % obj,
|
||||||
'action_list': action_list,
|
'action_list': action_list,
|
||||||
'module_name': capfirst(opts.verbose_name_plural),
|
'module_name': capfirst(opts.verbose_name_plural),
|
||||||
|
|
|
@ -23,7 +23,7 @@ def template_validator(request):
|
||||||
errors = manipulator.get_validation_errors(new_data)
|
errors = manipulator.get_validation_errors(new_data)
|
||||||
if not errors:
|
if not errors:
|
||||||
request.user.add_message('The template is valid.')
|
request.user.add_message('The template is valid.')
|
||||||
return render_to_response('template_validator', {
|
return render_to_response('admin/template_validator', {
|
||||||
'title': 'Template validator',
|
'title': 'Template validator',
|
||||||
'form': formfields.FormWrapper(manipulator, new_data, errors),
|
'form': formfields.FormWrapper(manipulator, new_data, errors),
|
||||||
}, context_instance=DjangoContext(request))
|
}, context_instance=DjangoContext(request))
|
||||||
|
|
|
@ -17,7 +17,6 @@ APP_ARGS = '[modelmodule ...]'
|
||||||
# Use django.__path__[0] because we don't know which directory django into
|
# Use django.__path__[0] because we don't know which directory django into
|
||||||
# which has been installed.
|
# which has been installed.
|
||||||
PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template')
|
PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template')
|
||||||
ADMIN_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', 'admin_templates')
|
|
||||||
|
|
||||||
def _get_packages_insert(app_label):
|
def _get_packages_insert(app_label):
|
||||||
return "INSERT INTO packages (label, name) VALUES ('%s', '%s');" % (app_label, app_label)
|
return "INSERT INTO packages (label, name) VALUES ('%s', '%s');" % (app_label, app_label)
|
||||||
|
@ -142,7 +141,7 @@ def get_sql_delete(mod):
|
||||||
if cursor is not None:
|
if cursor is not None:
|
||||||
cursor.execute("SELECT id FROM content_types WHERE package = %s", [app_label])
|
cursor.execute("SELECT id FROM content_types WHERE package = %s", [app_label])
|
||||||
for row in cursor.fetchall():
|
for row in cursor.fetchall():
|
||||||
output.append("DELETE FROM auth_admin_log WHERE content_type_id = %s;" % row[0])
|
output.append("DELETE FROM django_admin_log WHERE content_type_id = %s;" % row[0])
|
||||||
|
|
||||||
# Close database connection explicitly, in case this output is being piped
|
# Close database connection explicitly, in case this output is being piped
|
||||||
# directly into a database client, to avoid locking issues.
|
# directly into a database client, to avoid locking issues.
|
||||||
|
@ -378,16 +377,8 @@ def startproject(project_name, directory):
|
||||||
"Creates a Django project for the given project_name in the given directory."
|
"Creates a Django project for the given project_name in the given directory."
|
||||||
from random import choice
|
from random import choice
|
||||||
_start_helper('project', project_name, directory)
|
_start_helper('project', project_name, directory)
|
||||||
# Populate TEMPLATE_DIRS for the admin templates, based on where Django is
|
|
||||||
# installed.
|
|
||||||
admin_settings_file = os.path.join(directory, project_name, 'settings', 'admin.py')
|
|
||||||
settings_contents = open(admin_settings_file, 'r').read()
|
|
||||||
fp = open(admin_settings_file, 'w')
|
|
||||||
settings_contents = re.sub(r'(?s)\b(TEMPLATE_DIRS\s*=\s*\()(.*?)\)', "\\1\n r%r,\\2)" % ADMIN_TEMPLATE_DIR, settings_contents)
|
|
||||||
fp.write(settings_contents)
|
|
||||||
fp.close()
|
|
||||||
# Create a random SECRET_KEY hash, and put it in the main settings.
|
# Create a random SECRET_KEY hash, and put it in the main settings.
|
||||||
main_settings_file = os.path.join(directory, project_name, 'settings', 'main.py')
|
main_settings_file = os.path.join(directory, project_name, 'settings.py')
|
||||||
settings_contents = open(main_settings_file, 'r').read()
|
settings_contents = open(main_settings_file, 'r').read()
|
||||||
fp = open(main_settings_file, 'w')
|
fp = open(main_settings_file, 'w')
|
||||||
secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
|
secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
|
||||||
|
|
|
@ -602,7 +602,7 @@ class AdminMediaHandler:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import django
|
import django
|
||||||
self.application = application
|
self.application = application
|
||||||
self.media_dir = django.__path__[0] + '/conf/admin_media'
|
self.media_dir = django.__path__[0] + '/contrib/admin/media'
|
||||||
self.media_url = settings.ADMIN_MEDIA_PREFIX
|
self.media_url = settings.ADMIN_MEDIA_PREFIX
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
|
|
|
@ -1,126 +0,0 @@
|
||||||
from django.utils import httpwrappers
|
|
||||||
from django.core.extensions import DjangoContext
|
|
||||||
from django.core.extensions import render_to_response
|
|
||||||
from django.models.auth import users
|
|
||||||
from django.views.registration import passwords
|
|
||||||
from django.views.auth.login import logout
|
|
||||||
import base64, md5
|
|
||||||
import cPickle as pickle
|
|
||||||
from django.conf.settings import SECRET_KEY
|
|
||||||
|
|
||||||
ERROR_MESSAGE = "Please enter a correct username and password. Note that both fields are case-sensitive."
|
|
||||||
|
|
||||||
class AdminUserRequired:
|
|
||||||
"""
|
|
||||||
Admin middleware. If this is enabled, access to the site will be granted only
|
|
||||||
to valid users with the "is_staff" flag set.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def process_view(self, request, view_func, param_dict):
|
|
||||||
"""
|
|
||||||
Make sure the user is logged in and is a valid admin user before
|
|
||||||
allowing any access.
|
|
||||||
|
|
||||||
Done at the view point because we need to know if we're running the
|
|
||||||
password reset function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# If this is the password reset view, we don't want to require login
|
|
||||||
# Otherwise the password reset would need its own entry in the httpd
|
|
||||||
# conf, which is a little uglier than this. Same goes for the logout
|
|
||||||
# view.
|
|
||||||
|
|
||||||
if view_func in (passwords.password_reset, passwords.password_reset_done, logout):
|
|
||||||
return
|
|
||||||
|
|
||||||
assert hasattr(request, 'session'), "The admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.middleware.sessions.SessionMiddleware' before %r." % self.__class__.__name__
|
|
||||||
|
|
||||||
# Check for a logged in, valid user
|
|
||||||
if self.user_is_valid(request.user):
|
|
||||||
return
|
|
||||||
|
|
||||||
# If this isn't already the login page, display it
|
|
||||||
if not request.POST.has_key('this_is_the_login_form'):
|
|
||||||
if request.POST:
|
|
||||||
message = "Please log in again, because your session has expired. "\
|
|
||||||
"Don't worry: Your submission has been saved."
|
|
||||||
else:
|
|
||||||
message = ""
|
|
||||||
return self.display_login_form(request, message)
|
|
||||||
|
|
||||||
# Check that the user accepts cookies.
|
|
||||||
if not request.session.test_cookie_worked():
|
|
||||||
message = "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again."
|
|
||||||
return self.display_login_form(request, message)
|
|
||||||
|
|
||||||
# Check the password
|
|
||||||
username = request.POST.get('username', '')
|
|
||||||
try:
|
|
||||||
user = users.get_object(username__exact=username)
|
|
||||||
except users.UserDoesNotExist:
|
|
||||||
message = ERROR_MESSAGE
|
|
||||||
if '@' in username:
|
|
||||||
# Mistakenly entered e-mail address instead of username? Look it up.
|
|
||||||
try:
|
|
||||||
user = users.get_object(email__exact=username)
|
|
||||||
except users.UserDoesNotExist:
|
|
||||||
message = "Usernames cannot contain the '@' character."
|
|
||||||
else:
|
|
||||||
message = "Your e-mail address is not your username. Try '%s' instead." % user.username
|
|
||||||
return self.display_login_form(request, message)
|
|
||||||
|
|
||||||
# The user data is correct; log in the user in and continue
|
|
||||||
else:
|
|
||||||
if self.authenticate_user(user, request.POST.get('password', '')):
|
|
||||||
request.session[users.SESSION_KEY] = user.id
|
|
||||||
if request.POST.has_key('post_data'):
|
|
||||||
post_data = decode_post_data(request.POST['post_data'])
|
|
||||||
if post_data and not post_data.has_key('this_is_the_login_form'):
|
|
||||||
# overwrite request.POST with the saved post_data, and continue
|
|
||||||
request.POST = post_data
|
|
||||||
request.user = user
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
request.session.delete_test_cookie()
|
|
||||||
return httpwrappers.HttpResponseRedirect(request.path)
|
|
||||||
else:
|
|
||||||
return self.display_login_form(request, ERROR_MESSAGE)
|
|
||||||
|
|
||||||
def display_login_form(self, request, error_message=''):
|
|
||||||
request.session.set_test_cookie()
|
|
||||||
if request.POST and request.POST.has_key('post_data'):
|
|
||||||
# User has failed login BUT has previously saved 'post_data'
|
|
||||||
post_data = request.POST['post_data']
|
|
||||||
elif request.POST:
|
|
||||||
# User's session must have expired; save their post data
|
|
||||||
post_data = encode_post_data(request.POST)
|
|
||||||
else:
|
|
||||||
post_data = encode_post_data({})
|
|
||||||
return render_to_response(self.get_login_template_name(), {
|
|
||||||
'title': 'Log in',
|
|
||||||
'app_path': request.path,
|
|
||||||
'post_data': post_data,
|
|
||||||
'error_message': error_message
|
|
||||||
}, context_instance=DjangoContext(request))
|
|
||||||
|
|
||||||
def authenticate_user(self, user, password):
|
|
||||||
return user.check_password(password) and user.is_staff
|
|
||||||
|
|
||||||
def user_is_valid(self, user):
|
|
||||||
return not user.is_anonymous() and user.is_staff
|
|
||||||
|
|
||||||
def get_login_template_name(self):
|
|
||||||
return "login"
|
|
||||||
|
|
||||||
def encode_post_data(post_data):
|
|
||||||
pickled = pickle.dumps(post_data)
|
|
||||||
pickled_md5 = md5.new(pickled + SECRET_KEY).hexdigest()
|
|
||||||
return base64.encodestring(pickled + pickled_md5)
|
|
||||||
|
|
||||||
def decode_post_data(encoded_data):
|
|
||||||
encoded_data = base64.decodestring(encoded_data)
|
|
||||||
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
|
||||||
if md5.new(pickled + SECRET_KEY).hexdigest() != tamper_check:
|
|
||||||
from django.core.exceptions import SuspiciousOperation
|
|
||||||
raise SuspiciousOperation, "User may have tampered with session cookie."
|
|
||||||
return pickle.loads(pickled)
|
|
|
@ -176,49 +176,3 @@ class Message(meta.Model):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.message
|
return self.message
|
||||||
|
|
||||||
class LogEntry(meta.Model):
|
|
||||||
action_time = meta.DateTimeField(auto_now=True)
|
|
||||||
user = meta.ForeignKey(User)
|
|
||||||
content_type = meta.ForeignKey(core.ContentType, blank=True, null=True)
|
|
||||||
object_id = meta.TextField(blank=True, null=True)
|
|
||||||
object_repr = meta.CharField(maxlength=200)
|
|
||||||
action_flag = meta.PositiveSmallIntegerField()
|
|
||||||
change_message = meta.TextField(blank=True)
|
|
||||||
class META:
|
|
||||||
module_name = 'log'
|
|
||||||
verbose_name_plural = 'log entries'
|
|
||||||
db_table = 'auth_admin_log'
|
|
||||||
ordering = ('-action_time',)
|
|
||||||
module_constants = {
|
|
||||||
'ADDITION': 1,
|
|
||||||
'CHANGE': 2,
|
|
||||||
'DELETION': 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return str(self.action_time)
|
|
||||||
|
|
||||||
def is_addition(self):
|
|
||||||
return self.action_flag == ADDITION
|
|
||||||
|
|
||||||
def is_change(self):
|
|
||||||
return self.action_flag == CHANGE
|
|
||||||
|
|
||||||
def is_deletion(self):
|
|
||||||
return self.action_flag == DELETION
|
|
||||||
|
|
||||||
def get_edited_object(self):
|
|
||||||
"Returns the edited object represented by this log entry"
|
|
||||||
return self.get_content_type().get_object_for_this_type(pk=self.object_id)
|
|
||||||
|
|
||||||
def get_admin_url(self):
|
|
||||||
"""
|
|
||||||
Returns the admin URL to edit the object represented by this log entry.
|
|
||||||
This is relative to the Django admin index page.
|
|
||||||
"""
|
|
||||||
return "%s/%s/%s/" % (self.get_content_type().package, self.get_content_type().python_module_name, self.object_id)
|
|
||||||
|
|
||||||
def _module_log_action(user_id, content_type_id, object_id, object_repr, action_flag, change_message=''):
|
|
||||||
e = LogEntry(None, None, user_id, content_type_id, object_id, object_repr[:200], action_flag, change_message)
|
|
||||||
e.save()
|
|
||||||
|
|
|
@ -192,10 +192,10 @@ Available options
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
django-admin.py init --settings='myproject.settings.main'
|
django-admin.py init --settings=myproject.settings
|
||||||
|
|
||||||
Explicitly specifies the settings module to use. The settings module should be
|
Explicitly specifies the settings module to use. The settings module should be
|
||||||
in Python path syntax, e.g. "myproject.settings.main". If this isn't provided,
|
in Python path syntax, e.g. "myproject.settings". If this isn't provided,
|
||||||
``django-admin.py`` will use the DJANGO_SETTINGS_MODULE environment variable.
|
``django-admin.py`` will use the DJANGO_SETTINGS_MODULE environment variable.
|
||||||
|
|
||||||
--pythonpath
|
--pythonpath
|
||||||
|
|
|
@ -348,8 +348,7 @@ things:
|
||||||
* Set the ``SESSION_COOKIE_DOMAIN`` setting in your admin config file
|
* Set the ``SESSION_COOKIE_DOMAIN`` setting in your admin config file
|
||||||
to match your domain. For example, if you're going to
|
to match your domain. For example, if you're going to
|
||||||
"http://www.mysite.com/admin/" in your browser, in
|
"http://www.mysite.com/admin/" in your browser, in
|
||||||
"myproject.settings.admin" you should set ``SESSION_COOKIE_DOMAIN =
|
"myproject.settings" you should set ``SESSION_COOKIE_DOMAIN = 'www.mysite.com'``.
|
||||||
'www.mysite.com'``.
|
|
||||||
|
|
||||||
* Some browsers (Firefox?) don't like to accept cookies from domains that
|
* Some browsers (Firefox?) don't like to accept cookies from domains that
|
||||||
don't have dots in them. If you're running the admin site on "localhost"
|
don't have dots in them. If you're running the admin site on "localhost"
|
||||||
|
|
|
@ -27,30 +27,15 @@ name. For example, here's the default ``MIDDLEWARE_CLASSES`` created by
|
||||||
"django.middleware.doc.XViewMiddleware",
|
"django.middleware.doc.XViewMiddleware",
|
||||||
)
|
)
|
||||||
|
|
||||||
The default admin site has the following ``MIDDLEWARE_CLASSES`` set::
|
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
|
||||||
"django.middleware.sessions.SessionMiddleware",
|
|
||||||
"django.middleware.admin.AdminUserRequired",
|
|
||||||
"django.middleware.common.CommonMiddleware",
|
|
||||||
)
|
|
||||||
|
|
||||||
Django applies middleware in the order it's defined in ``MIDDLEWARE_CLASSES``.
|
Django applies middleware in the order it's defined in ``MIDDLEWARE_CLASSES``.
|
||||||
|
|
||||||
For a regular (i.e., non-admin) Django installation, no middleware is required,
|
A Django installation doesn't require any middleware -- e.g.,
|
||||||
but it's strongly suggested that you use ``CommonMiddleware``. For a Django
|
``MIDDLEWARE_CLASSES`` can be empty, if you'd like -- but it's strongly
|
||||||
admin site, ``SessionMiddleware`` and ``AdminUserRequired`` (in that order) are
|
suggested that you use ``CommonMiddleware``.
|
||||||
required.
|
|
||||||
|
|
||||||
Available middleware
|
Available middleware
|
||||||
====================
|
====================
|
||||||
|
|
||||||
django.middleware.admin.AdminUserRequired
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
Limits site access to valid users with the ``is_staff`` flag set. This is
|
|
||||||
required by Django's admin, and this middleware requires ``SessionMiddleware``.
|
|
||||||
|
|
||||||
django.middleware.cache.CacheMiddleware
|
django.middleware.cache.CacheMiddleware
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,11 @@ Then edit your ``httpd.conf`` file and add the following::
|
||||||
<Location "/mysite/">
|
<Location "/mysite/">
|
||||||
SetHandler python-program
|
SetHandler python-program
|
||||||
PythonHandler django.core.handlers.modpython
|
PythonHandler django.core.handlers.modpython
|
||||||
SetEnv DJANGO_SETTINGS_MODULE myproject.settings.main
|
SetEnv DJANGO_SETTINGS_MODULE myproject.settings
|
||||||
PythonDebug On
|
PythonDebug On
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
...and replace ``myproject.settings.main`` with the Python path to your
|
...and replace ``myproject.settings`` with the Python path to your settings file.
|
||||||
settings file.
|
|
||||||
|
|
||||||
This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
|
This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
|
||||||
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE``
|
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE``
|
||||||
|
@ -55,17 +54,6 @@ full URL.
|
||||||
When deploying Django sites on mod_python, you'll need to restart Apache each
|
When deploying Django sites on mod_python, you'll need to restart Apache each
|
||||||
time you make changes to your Python code.
|
time you make changes to your Python code.
|
||||||
|
|
||||||
Here's a template for an admin configuration::
|
|
||||||
|
|
||||||
<Location "/admin/">
|
|
||||||
SetHandler python-program
|
|
||||||
PythonHandler django.core.handlers.modpython
|
|
||||||
SetEnv DJANGO_SETTINGS_MODULE myproject.settings.admin
|
|
||||||
PythonDebug On
|
|
||||||
</Location>
|
|
||||||
|
|
||||||
The only thing different here is the ``DJANGO_SETTINGS_MODULE``.
|
|
||||||
|
|
||||||
Multiple Django installations on the same Apache
|
Multiple Django installations on the same Apache
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
|
@ -77,13 +65,13 @@ instance. Just use ``VirtualHost`` for that, like so::
|
||||||
<VirtualHost *>
|
<VirtualHost *>
|
||||||
ServerName www.example.com
|
ServerName www.example.com
|
||||||
# ...
|
# ...
|
||||||
SetEnv DJANGO_SETTINGS_MODULE myproject.settings.main
|
SetEnv DJANGO_SETTINGS_MODULE myproject.settings
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
|
||||||
<VirtualHost *>
|
<VirtualHost *>
|
||||||
ServerName admin.example.com
|
ServerName www2.example.com
|
||||||
# ...
|
# ...
|
||||||
SetEnv DJANGO_SETTINGS_MODULE myproject.settings.admin
|
SetEnv DJANGO_SETTINGS_MODULE myproject.other_settings
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
|
||||||
If you need to put two Django installations within the same ``VirtualHost``,
|
If you need to put two Django installations within the same ``VirtualHost``,
|
||||||
|
@ -95,13 +83,13 @@ mess things up. Use the ``PythonInterpreter`` directive to give different
|
||||||
ServerName www.example.com
|
ServerName www.example.com
|
||||||
# ...
|
# ...
|
||||||
<Location "/something">
|
<Location "/something">
|
||||||
SetEnv DJANGO_SETTINGS_MODULE myproject.settings.main
|
SetEnv DJANGO_SETTINGS_MODULE myproject.settings
|
||||||
PythonInterpreter myproject_main
|
PythonInterpreter myproject
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
<Location "/admin">
|
<Location "/otherthing">
|
||||||
SetEnv DJANGO_SETTINGS_MODULE myproject.settings.admin
|
SetEnv DJANGO_SETTINGS_MODULE myproject.other_settings
|
||||||
PythonInterpreter myproject_admin
|
PythonInterpreter myproject_other
|
||||||
</Location>
|
</Location>
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ When you use Django, you have to tell it which settings you're using. Do this
|
||||||
by using an environment variable, ``DJANGO_SETTINGS_MODULE``.
|
by using an environment variable, ``DJANGO_SETTINGS_MODULE``.
|
||||||
|
|
||||||
The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g.
|
The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g.
|
||||||
``"myproject.settings.main"``. Note that the settings module should be on the
|
``"myproject.settings"``. Note that the settings module should be on the
|
||||||
Python `import search path`_.
|
Python `import search path`_.
|
||||||
|
|
||||||
.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
|
.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
|
||||||
|
@ -47,17 +47,17 @@ once, or explicitly pass in the settings module each time you run the utility.
|
||||||
|
|
||||||
Example (Unix Bash shell)::
|
Example (Unix Bash shell)::
|
||||||
|
|
||||||
export DJANGO_SETTINGS_MODULE=myproject.settings.main
|
export DJANGO_SETTINGS_MODULE=myproject.settings
|
||||||
django-admin.py runserver
|
django-admin.py runserver
|
||||||
|
|
||||||
Example (Windows shell)::
|
Example (Windows shell)::
|
||||||
|
|
||||||
set DJANGO_SETTINGS_MODULE=myproject.settings.main
|
set DJANGO_SETTINGS_MODULE=myproject.settings
|
||||||
django-admin.py runserver
|
django-admin.py runserver
|
||||||
|
|
||||||
Use the ``--settings`` command-line argument to specify the settings manually::
|
Use the ``--settings`` command-line argument to specify the settings manually::
|
||||||
|
|
||||||
django-admin.py runserver --settings=myproject.settings.main
|
django-admin.py runserver --settings=myproject.settings
|
||||||
|
|
||||||
.. _django-admin.py: http://www.djangoproject.com/documentation/django_admin/
|
.. _django-admin.py: http://www.djangoproject.com/documentation/django_admin/
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ settings file to use. Do that with ``SetEnv``::
|
||||||
<Location "/mysite/">
|
<Location "/mysite/">
|
||||||
SetHandler python-program
|
SetHandler python-program
|
||||||
PythonHandler django.core.handlers.modpython
|
PythonHandler django.core.handlers.modpython
|
||||||
SetEnv DJANGO_SETTINGS_MODULE myproject.settings.main
|
SetEnv DJANGO_SETTINGS_MODULE myproject.settings
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
Read the `Django mod_python documentation`_ for more information.
|
Read the `Django mod_python documentation`_ for more information.
|
||||||
|
|
|
@ -40,16 +40,10 @@ settings. Let's look at what ``startproject`` created::
|
||||||
__init__.py
|
__init__.py
|
||||||
apps/
|
apps/
|
||||||
__init__.py
|
__init__.py
|
||||||
settings/
|
settings.py
|
||||||
__init__.py
|
urls.py
|
||||||
admin.py
|
|
||||||
main.py
|
|
||||||
urls/
|
|
||||||
__init__.py
|
|
||||||
admin.py
|
|
||||||
main.py
|
|
||||||
|
|
||||||
First, edit ``myproject/settings/main.py``. It's a normal Python module with
|
First, edit ``myproject/settings.py``. It's a normal Python module with
|
||||||
module-level variables representing Django settings. Edit the file and change
|
module-level variables representing Django settings. Edit the file and change
|
||||||
these settings to match your database's connection parameters:
|
these settings to match your database's connection parameters:
|
||||||
|
|
||||||
|
@ -69,11 +63,6 @@ these settings to match your database's connection parameters:
|
||||||
point. Do that with "``CREATE DATABASE database_name;``" within your
|
point. Do that with "``CREATE DATABASE database_name;``" within your
|
||||||
database's interactive prompt.
|
database's interactive prompt.
|
||||||
|
|
||||||
Also, note that MySQL and sqlite support is a recent development, and Django
|
|
||||||
hasn't been comprehensively tested with either database. If you find any
|
|
||||||
bugs in those bindings, please file them in `Django's ticket system`_ so we
|
|
||||||
can fix them immediately.
|
|
||||||
|
|
||||||
Now, take a second to make sure ``myproject`` is on your Python path. You
|
Now, take a second to make sure ``myproject`` is on your Python path. You
|
||||||
can do this by copying ``myproject`` to Python's ``site-packages`` directory,
|
can do this by copying ``myproject`` to Python's ``site-packages`` directory,
|
||||||
or you can do it by altering the ``PYTHONPATH`` environment variable. See the
|
or you can do it by altering the ``PYTHONPATH`` environment variable. See the
|
||||||
|
@ -84,7 +73,7 @@ or you can do it by altering the ``PYTHONPATH`` environment variable. See the
|
||||||
|
|
||||||
Run the following command::
|
Run the following command::
|
||||||
|
|
||||||
django-admin.py init --settings=myproject.settings.main
|
django-admin.py init --settings=myproject.settings
|
||||||
|
|
||||||
The ``django-admin.py`` utility generally needs to know which settings module
|
The ``django-admin.py`` utility generally needs to know which settings module
|
||||||
you're using. Here, we're doing that by specifying ``settings=`` on the command
|
you're using. Here, we're doing that by specifying ``settings=`` on the command
|
||||||
|
@ -92,11 +81,11 @@ line, but that can get tedious. If you don't want to type ``settings=`` each
|
||||||
time, you can set the ``DJANGO_SETTINGS_MODULE`` environment variable. Here's
|
time, you can set the ``DJANGO_SETTINGS_MODULE`` environment variable. Here's
|
||||||
how you do that in the Bash shell on Unix::
|
how you do that in the Bash shell on Unix::
|
||||||
|
|
||||||
export DJANGO_SETTINGS_MODULE=myproject.settings.main
|
export DJANGO_SETTINGS_MODULE=myproject.settings
|
||||||
|
|
||||||
On Windows, you'd use ``set`` instead::
|
On Windows, you'd use ``set`` instead::
|
||||||
|
|
||||||
set DJANGO_SETTINGS_MODULE=myproject.settings.main
|
set DJANGO_SETTINGS_MODULE=myproject.settings
|
||||||
|
|
||||||
If you don't see any errors after running ``django-admin.py init``, you know it
|
If you don't see any errors after running ``django-admin.py init``, you know it
|
||||||
worked. That command initialized your database with Django's core database
|
worked. That command initialized your database with Django's core database
|
||||||
|
@ -221,7 +210,7 @@ But first we need to tell our project that the ``polls`` app is installed.
|
||||||
projects, and you can distribute apps, because they don't have to be tied to
|
projects, and you can distribute apps, because they don't have to be tied to
|
||||||
a given Django installation.
|
a given Django installation.
|
||||||
|
|
||||||
Edit the myproject/settings/main.py file again, and change the ``INSTALLED_APPS``
|
Edit the myproject/settings.py file again, and change the ``INSTALLED_APPS``
|
||||||
setting to include the string "myproject.apps.polls". So it'll look like this::
|
setting to include the string "myproject.apps.polls". So it'll look like this::
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
|
|
|
@ -24,15 +24,26 @@ application and will focus on Django's automatically-generated admin site.
|
||||||
The admin isn't necessarily intended to be used by site visitors; it's for site
|
The admin isn't necessarily intended to be used by site visitors; it's for site
|
||||||
managers.
|
managers.
|
||||||
|
|
||||||
|
Activate the admin site
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The Django admin site is not activated by default -- it's an opt-in thing. To
|
||||||
|
activate the admin site for your installation, do these three things:
|
||||||
|
|
||||||
|
* Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
|
||||||
|
* Run the command ``django-admin.py install admin``. This will create an
|
||||||
|
extra database table that the admin needs.
|
||||||
|
* Edit your ``myproject.urls`` file and uncomment the line below
|
||||||
|
"Uncomment this for admin:". This file is a URLconf; we'll dig into
|
||||||
|
URLconfs in the next tutorial. For now, all you need to know is that it
|
||||||
|
maps URL roots to applications.
|
||||||
|
|
||||||
Create a user account
|
Create a user account
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Run the following command to create a superuser account for your admin site::
|
Run the following command to create a superuser account for your admin site::
|
||||||
|
|
||||||
django-admin.py createsuperuser --settings="myproject.settings.main"
|
django-admin.py createsuperuser --settings=myproject.settings
|
||||||
|
|
||||||
(Note: You can use either "myproject.settings.main" or "myproject.settings.admin"
|
|
||||||
here. They both reference the same database.)
|
|
||||||
|
|
||||||
The script will prompt you for a username, e-mail address and password (twice).
|
The script will prompt you for a username, e-mail address and password (twice).
|
||||||
|
|
||||||
|
@ -45,36 +56,26 @@ server and explore the admin site.
|
||||||
|
|
||||||
Just run the following command to start the server::
|
Just run the following command to start the server::
|
||||||
|
|
||||||
django-admin.py runserver --settings="myproject.settings.admin"
|
django-admin.py runserver --settings=myproject.settings
|
||||||
|
|
||||||
It'll start a Web server running locally -- on port 8000, by default. If you
|
It'll start a Web server running locally -- on port 8000, by default. If you
|
||||||
want to change the server's port, pass it as a command-line argument::
|
want to change the server's port, pass it as a command-line argument::
|
||||||
|
|
||||||
django-admin.py runserver 8080 --settings="myproject.settings.admin"
|
django-admin.py runserver 8080 --settings=myproject.settings
|
||||||
|
|
||||||
DON'T use this server in anything resembling a production environment. It's
|
DON'T use this server in anything resembling a production environment. It's
|
||||||
intended only for use while developing.
|
intended only for use while developing.
|
||||||
|
|
||||||
Now, open a Web browser and go to "/admin/" on your domain. You should see the
|
Now, open a Web browser and go to "/admin/" on your local domain -- e.g.,
|
||||||
admin's login screen:
|
http://127.0.0.1:8000/admin/. You should see the admin's login screen:
|
||||||
|
|
||||||
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin01.png
|
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin01.png
|
||||||
:alt: Django admin login screen
|
:alt: Django admin login screen
|
||||||
|
|
||||||
.. admonition:: Note
|
|
||||||
|
|
||||||
If you get an error telling you that the URL 'admin/' didn't match any of
|
|
||||||
your URLconf entries, you most likely used ``myproject.settings.main``
|
|
||||||
instead of ``myproject.settings.admin``.
|
|
||||||
|
|
||||||
Enter the admin site
|
Enter the admin site
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Now, try logging in.
|
Now, try logging in. You should see the Django admin index page:
|
||||||
|
|
||||||
If it didn't work, read the `"I can't log in" questions`_ in the FAQ.
|
|
||||||
|
|
||||||
If it worked, you should see the Django admin index page:
|
|
||||||
|
|
||||||
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin02t.png
|
.. image:: http://media.djangoproject.com/img/doc/tutorial/admin02t.png
|
||||||
:alt: Django admin index page
|
:alt: Django admin index page
|
||||||
|
@ -381,39 +382,47 @@ think they should.
|
||||||
Customize the admin look and feel
|
Customize the admin look and feel
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
Clearly having "Django administration" and "example.com" at the top of each
|
Clearly, having "Django administration" and "example.com" at the top of each
|
||||||
admin page is ridiculous. It's just placeholder text.
|
admin page is ridiculous. It's just placeholder text.
|
||||||
|
|
||||||
That's easy to change, though, using Django's template system.
|
That's easy to change, though, using Django's template system. The Django admin
|
||||||
|
is powered by Django itself, and its interfaces use Django's own template
|
||||||
|
system. (How meta!)
|
||||||
|
|
||||||
Open your admin settings file and look at the ``TEMPLATE_DIRS`` setting.
|
Open your settings file (``myproject/settings.py``, remember) and look at the
|
||||||
``TEMPLATE_DIRS`` is a tuple of filesystem directories to check when loading
|
``TEMPLATE_DIRS`` setting. ``TEMPLATE_DIRS`` is a tuple of filesystem
|
||||||
Django templates. It's a search path.
|
directories to check when loading Django templates. It's a search path.
|
||||||
|
|
||||||
The ``django-admin.py startproject`` command automatically prepopulated
|
By default, ``TEMPLATE_DIRS`` is empty. So, let's add a line to it, to tell
|
||||||
this setting with the location of Django's default admin templates, according
|
Django where our templates live.
|
||||||
to where you have Django installed. But let's add an extra line to
|
|
||||||
``TEMPLATE_DIRS`` so that it checks a custom directory first, before checking
|
|
||||||
the default admin template directory::
|
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = (
|
||||||
"/home/mytemplates/admin",
|
"/home/mytemplates", # Change this to your own directory.
|
||||||
"/usr/lib/python2.3/site-packages/django/conf/admin_templates",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Again, note that you should edit the admin settings file, not the main settings
|
Now copy the template ``admin/base_site.html`` from within the default Django
|
||||||
file. That's because we're dealing with admin-site templates.
|
admin template directory (``django/contrib/admin/templates``) into an ``admin``
|
||||||
|
subdirectory of whichever directory you're using in ``TEMPLATE_DIRS``. For
|
||||||
|
example, if your ``TEMPLATE_DIRS`` includes ``"/home/mytemplates"``, as above,
|
||||||
|
then copy ``django/contrib/admin/templates/admin/base_site.html`` to
|
||||||
|
``/home/mytemplates/admin/base_site.html``.
|
||||||
|
|
||||||
Now copy the template ``base_site.html`` from within the default Django admin
|
Then, just edit the file and replace the generic Django text with your own
|
||||||
template directory, into ``/home/mytemplates/admin`` (or wherever you're
|
site's name and URL as you see fit.
|
||||||
putting your custom admin templates). Edit the file and replace the generic
|
|
||||||
Django stuff with your own site's name as you see fit.
|
|
||||||
|
|
||||||
Note that any of Django's default admin templates can be overridden. To
|
Note that any of Django's default admin templates can be overridden. To
|
||||||
override a template, just do the same thing you did with ``base_site.html`` --
|
override a template, just do the same thing you did with ``base_site.html`` --
|
||||||
copy it from the default directory into your custom directory, and make
|
copy it from the default directory into your custom directory, and make
|
||||||
changes.
|
changes.
|
||||||
|
|
||||||
|
Astute readers will ask: But if ``TEMPLATE_DIRS`` was empty by default, how was
|
||||||
|
Django finding the default admin templates? The answer is that, by default,
|
||||||
|
Django automatically looks for a ``templates/`` subdirectory within each app
|
||||||
|
package, for use as a fallback. See the `loader types documentation`_ for full
|
||||||
|
information.
|
||||||
|
|
||||||
|
.. _loader types documentation: http://www.djangoproject.com/documentation/templates_python/#loader-types
|
||||||
|
|
||||||
Customize the admin index page
|
Customize the admin index page
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
@ -425,11 +434,11 @@ setting. But the order in which it displays things is random, and you may want
|
||||||
to make significant changes to the layout. After all, the index is probably the
|
to make significant changes to the layout. After all, the index is probably the
|
||||||
most important page of the admin, and it should be easy to use.
|
most important page of the admin, and it should be easy to use.
|
||||||
|
|
||||||
The template to customize is ``index.html``. (Do the same as with
|
The template to customize is ``admin/index.html``. (Do the same as with
|
||||||
``base_site.html`` in the previous section -- copy it from the default directory
|
``admin/base_site.html`` in the previous section -- copy it from the default
|
||||||
to your custom template directory.) Edit the file, and you'll see it uses a
|
directory to your custom template directory.) Edit the file, and you'll see it
|
||||||
template tag called ``{% get_admin_app_list as app_list %}``. That's the magic
|
uses a template tag called ``{% get_admin_app_list as app_list %}``. That's the
|
||||||
that retrieves every installed Django app. Instead of using that, you can
|
magic that retrieves every installed Django app. Instead of using that, you can
|
||||||
hard-code links to object-specific admin pages in whatever way you think is
|
hard-code links to object-specific admin pages in whatever way you think is
|
||||||
best.
|
best.
|
||||||
|
|
||||||
|
|