mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
multi-auth: Merged to [3051]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multi-auth@3052 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
aeb807989f
commit
0c341d780e
1
AUTHORS
1
AUTHORS
@ -45,6 +45,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
andy@jadedplanet.net
|
||||
Antonio Cavedoni <http://cavedoni.com/>
|
||||
C8E
|
||||
Chris Chamberlin <dja@cdc.msbx.net>
|
||||
Amit Chakradeo <http://amit.chakradeo.net/>
|
||||
ChaosKCW
|
||||
Ian Clelland <clelland@gmail.com>
|
||||
|
@ -235,6 +235,7 @@ SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever yo
|
||||
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
|
||||
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
|
||||
SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request.
|
||||
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser.
|
||||
|
||||
#########
|
||||
# CACHE #
|
||||
|
Binary file not shown.
@ -13,7 +13,7 @@ msgstr ""
|
||||
"Last-Translator: panos laganakos <panos.laganakos@gmail.com>\n"
|
||||
"Language-Team: Greek\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=iso-8859-1\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@ try:
|
||||
import settings # Assumed to be in the same directory.
|
||||
except ImportError:
|
||||
import sys
|
||||
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
|
||||
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -7,7 +7,7 @@ body.login { background:#eee; }
|
||||
.login #content-main { width:100%; }
|
||||
.login form { margin-top:1em; }
|
||||
.login .form-row { padding:4px 0; float:left; width:100%; }
|
||||
.login .form-row label { float:left; width:7em; padding-right:0.5em; line-height:2em; text-align:right; font-size:1em; color:#333; }
|
||||
.login .form-row #id_username, .login .form-row #id_password { width:16em; }
|
||||
.login .form-row label { float:left; width:9em; padding-right:0.5em; line-height:2em; text-align:right; font-size:1em; color:#333; }
|
||||
.login .form-row #id_username, .login .form-row #id_password { width:14em; }
|
||||
.login span.help { font-size:10px; display:block; }
|
||||
.login .submit-row { clear:both; padding:1em 0 0 7.4em; }
|
||||
.login .submit-row { clear:both; padding:1em 0 0 9.4em; }
|
BIN
django/contrib/admin/media/img/admin/icon-unknown.gif
Normal file
BIN
django/contrib/admin/media/img/admin/icon-unknown.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 130 B |
@ -12,7 +12,7 @@
|
||||
<div class="breadcrumbs">
|
||||
<a href="../../../">{% trans "Home" %}</a> ›
|
||||
<a href="../">{{ opts.verbose_name_plural|capfirst }}</a> ›
|
||||
{% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|striptags|truncatewords:"18" }}{% endif %}
|
||||
{% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %}
|
||||
</div>
|
||||
{% endif %}{% endblock %}
|
||||
{% block content %}<div id="content-main">
|
||||
|
@ -2,13 +2,9 @@
|
||||
<div class="{{ class_names }}" >
|
||||
{% for bound_field in bound_fields %}{{ bound_field.html_error_list }}{% endfor %}
|
||||
{% for bound_field in bound_fields %}
|
||||
{% if bound_field.has_label_first %}
|
||||
{% field_label bound_field %}
|
||||
{% endif %}
|
||||
{% if bound_field.has_label_first %}{% field_label bound_field %}{% endif %}
|
||||
{% field_widget bound_field %}
|
||||
{% if not bound_field.has_label_first %}
|
||||
{% field_label bound_field %}
|
||||
{% endif %}
|
||||
{% if not bound_field.has_label_first %}{% field_label bound_field %}{% endif %}
|
||||
{% if bound_field.field.help_text %}<p class="help">{{ bound_field.field.help_text }}</p>{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -3,6 +3,6 @@
|
||||
<ul>
|
||||
{% for choice in choices %}
|
||||
<li{% if choice.selected %} class="selected"{% endif %}>
|
||||
<a href="{{ choice.query_string }}">{{ choice.display }}</a></li>
|
||||
<a href="{{ choice.query_string }}">{{ choice.display|escape }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
10
django/contrib/admin/templates/admin/invalid_setup.html
Normal file
10
django/contrib/admin/templates/admin/invalid_setup.html
Normal file
@ -0,0 +1,10 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {{ title }}</div>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<p>{% trans "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." %}</p>
|
||||
|
||||
{% endblock %}
|
@ -24,8 +24,8 @@
|
||||
{% for action in action_list %}
|
||||
<tr>
|
||||
<th scope="row">{{ action.action_time|date:_("DATE_WITH_TIME_FULL") }}</th>
|
||||
<td>{{ action.user.username }}{% if action.user.first_name %} ({{ action.user.first_name }} {{ action.user.last_name }}){% endif %}</td>
|
||||
<td>{{ action.change_message}}</td>
|
||||
<td>{{ action.user.username }}{% if action.user.first_name %} ({{ action.user.first_name|escape }} {{ action.user.last_name|escape }}){% endif %}</td>
|
||||
<td>{{ action.change_message|escape }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -42,7 +42,12 @@ class AdminApplistNode(template.Node):
|
||||
})
|
||||
|
||||
if model_list:
|
||||
model_list.sort()
|
||||
# Sort using verbose decorate-sort-undecorate pattern
|
||||
# instead of key argument to sort() for python 2.3 compatibility
|
||||
decorated = [(x['name'], x) for x in model_list]
|
||||
decorated.sort()
|
||||
model_list = [x for key, x in decorated]
|
||||
|
||||
app_list.append({
|
||||
'name': app_label.title(),
|
||||
'has_module_perms': has_module_perms,
|
||||
|
@ -2,7 +2,7 @@ from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('',
|
||||
('^$', 'django.contrib.admin.views.main.index'),
|
||||
('^r/(\d+)/(\d+)/$', 'django.views.defaults.shortcut'),
|
||||
('^r/(\d+)/(.*)/$', 'django.views.defaults.shortcut'),
|
||||
('^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': 'django.conf'}),
|
||||
('^logout/$', 'django.contrib.auth.views.logout'),
|
||||
('^password_change/$', 'django.contrib.auth.views.password_change'),
|
||||
|
@ -35,6 +35,7 @@ ORDER_TYPE_VAR = 'ot'
|
||||
PAGE_VAR = 'p'
|
||||
SEARCH_VAR = 'q'
|
||||
IS_POPUP_VAR = 'pop'
|
||||
ERROR_FLAG = 'e'
|
||||
|
||||
# Text to display within change-list table cells if the value is blank.
|
||||
EMPTY_CHANGELIST_VALUE = '(None)'
|
||||
@ -73,8 +74,7 @@ def unquote(s):
|
||||
for item in list:
|
||||
if item[1:2]:
|
||||
try:
|
||||
myappend(mychr(myatoi(item[:2], 16))
|
||||
+ item[2:])
|
||||
myappend(mychr(myatoi(item[:2], 16)) + item[2:])
|
||||
except ValueError:
|
||||
myappend('_' + item)
|
||||
else:
|
||||
@ -143,9 +143,9 @@ class AdminBoundField(object):
|
||||
return self._display
|
||||
except AttributeError:
|
||||
if isinstance(self.field.rel, models.ManyToOneRel):
|
||||
self._display = getattr(self.original, self.field.attname)
|
||||
self._display = getattr(self.original, self.field.name)
|
||||
elif isinstance(self.field.rel, models.ManyToManyRel):
|
||||
self._display = ", ".join([str(obj) for obj in getattr(self.original, self.field.attname).all()])
|
||||
self._display = ", ".join([str(obj) for obj in getattr(self.original, self.field.name).all()])
|
||||
return self._display
|
||||
|
||||
def __repr__(self):
|
||||
@ -557,6 +557,8 @@ class ChangeList(object):
|
||||
self.params = dict(request.GET.items())
|
||||
if self.params.has_key(PAGE_VAR):
|
||||
del self.params[PAGE_VAR]
|
||||
if self.params.has_key(ERROR_FLAG):
|
||||
del self.params[ERROR_FLAG]
|
||||
|
||||
self.order_field, self.order_type = self.get_ordering()
|
||||
self.query = request.GET.get(SEARCH_VAR, '')
|
||||
@ -730,7 +732,14 @@ def change_list(request, app_label, model_name):
|
||||
try:
|
||||
cl = ChangeList(request, model)
|
||||
except IncorrectLookupParameters:
|
||||
return HttpResponseRedirect(request.path)
|
||||
# Wacky lookup parameters were given, so redirect to the main
|
||||
# changelist page, without parameters, and pass an 'invalid=1'
|
||||
# parameter via the query string. If wacky parameters were given and
|
||||
# the 'invalid=1' parameter was already in the query string, something
|
||||
# is screwed up with the database, so display an error page.
|
||||
if ERROR_FLAG in request.GET.keys():
|
||||
return render_to_response('admin/invalid_setup.html', {'title': _('Database error')})
|
||||
return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')
|
||||
c = template.RequestContext(request, {
|
||||
'title': cl.title,
|
||||
'is_popup': cl.is_popup,
|
||||
|
@ -10,8 +10,6 @@ def authenhandler(req, **kwargs):
|
||||
# that so that the following import works
|
||||
os.environ.update(req.subprocess_env)
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
# check for PythonOptions
|
||||
_str_to_bool = lambda s: s.lower() in ('1', 'true', 'on', 'yes')
|
||||
|
||||
@ -19,6 +17,11 @@ def authenhandler(req, **kwargs):
|
||||
permission_name = options.get('DjangoPermissionName', None)
|
||||
staff_only = _str_to_bool(options.get('DjangoRequireStaffStatus', "on"))
|
||||
superuser_only = _str_to_bool(options.get('DjangoRequireSuperuserStatus', "off"))
|
||||
settings_module = options.get('DJANGO_SETTINGS_MODULE', None)
|
||||
if settings_module:
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
# check that the username is valid
|
||||
kwargs = {'username': req.user, 'is_active': True}
|
||||
|
@ -32,7 +32,7 @@ class Permission(models.Model):
|
||||
ordering = ('content_type', 'codename')
|
||||
|
||||
def __str__(self):
|
||||
return "%r | %s" % (self.content_type, self.name)
|
||||
return "%s | %s" % (self.content_type, self.name)
|
||||
|
||||
class Group(models.Model):
|
||||
name = models.CharField(_('name'), maxlength=80, unique=True)
|
||||
|
@ -79,9 +79,14 @@ class SessionMiddleware:
|
||||
else:
|
||||
if modified or settings.SESSION_SAVE_EVERY_REQUEST:
|
||||
session_key = request.session.session_key or Session.objects.get_new_session_key()
|
||||
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
|
||||
max_age = None
|
||||
expires = None
|
||||
else:
|
||||
max_age = settings.SESSION_COOKIE_AGE
|
||||
expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT")
|
||||
new_session = Session.objects.save(session_key, request.session._session,
|
||||
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
|
||||
expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT")
|
||||
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
|
||||
max_age=settings.SESSION_COOKIE_AGE, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN)
|
||||
max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN)
|
||||
return response
|
||||
|
@ -334,8 +334,8 @@ def get_sql_initial_data_for_model(model):
|
||||
r"""( # each statement is...
|
||||
(?: # one or more chunks of ...
|
||||
(?:[^;'"]+) # not the end of a statement or start of a quote
|
||||
| (?:'[^']+') # something in single quotes
|
||||
| (?:"[^"]+") # something in double quotes
|
||||
| (?:'[^']*') # something in single quotes
|
||||
| (?:"[^"]*") # something in double quotes
|
||||
)+)""", re.VERBOSE)
|
||||
|
||||
# Find custom SQL, if it's available.
|
||||
|
@ -54,6 +54,26 @@ class ObjectPaginator:
|
||||
def has_previous_page(self, page_number):
|
||||
return page_number > 0
|
||||
|
||||
def first_on_page(self, page_number):
|
||||
"""
|
||||
Returns the 1-based index of the first object on the given page,
|
||||
relative to total objects found (hits).
|
||||
"""
|
||||
if page_number == 0:
|
||||
return 1
|
||||
return (self.num_per_page * page_number) + 1
|
||||
|
||||
def last_on_page(self, page_number):
|
||||
"""
|
||||
Returns the 1-based index of the last object on the given page,
|
||||
relative to total objects found (hits).
|
||||
"""
|
||||
if page_number == 0 and self.num_per_page >= self._hits:
|
||||
return self._hits
|
||||
elif page_number == (self._pages - 1) and (page_number + 1) * self.num_per_page > self._hits:
|
||||
return self._hits
|
||||
return (page_number + 1) * self.num_per_page
|
||||
|
||||
def _get_hits(self):
|
||||
if self._hits is None:
|
||||
self._hits = self.query_set.count()
|
||||
|
@ -20,7 +20,10 @@ alnumurl_re = re.compile(r'^[-\w/]+$')
|
||||
ansi_date_re = re.compile('^%s$' % _datere)
|
||||
ansi_time_re = re.compile('^%s$' % _timere)
|
||||
ansi_datetime_re = re.compile('^%s %s$' % (_datere, _timere))
|
||||
email_re = re.compile(r'^[A-Z0-9._%-][+A-Z0-9._%-]*@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$', re.IGNORECASE)
|
||||
email_re = re.compile(
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
|
||||
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$', re.IGNORECASE) # domain
|
||||
integer_re = re.compile(r'^-?\d+$')
|
||||
ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
|
||||
phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)
|
||||
@ -143,7 +146,11 @@ def isValidImage(field_data, all_data):
|
||||
from PIL import Image
|
||||
from cStringIO import StringIO
|
||||
try:
|
||||
Image.open(StringIO(field_data['content']))
|
||||
content = field_data['content']
|
||||
except TypeError:
|
||||
raise ValidationError, gettext("No file was submitted. Check the encoding type on the form.")
|
||||
try:
|
||||
Image.open(StringIO(content))
|
||||
except IOError: # Python Imaging Library doesn't recognize it as an image
|
||||
raise ValidationError, gettext("Upload a valid image. The file you uploaded was either not an image or a corrupted image.")
|
||||
|
||||
@ -363,9 +370,13 @@ class HasAllowableSize:
|
||||
self.max_error_message = max_error_message or lazy_inter(gettext_lazy("Make sure your uploaded file is at most %s bytes big."), max_size)
|
||||
|
||||
def __call__(self, field_data, all_data):
|
||||
if self.min_size is not None and len(field_data['content']) < self.min_size:
|
||||
try:
|
||||
content = field_data['content']
|
||||
except TypeError:
|
||||
raise ValidationError, gettext_lazy("No file was submitted. Check the encoding type on the form.")
|
||||
if self.min_size is not None and len(content) < self.min_size:
|
||||
raise ValidationError, self.min_error_message
|
||||
if self.max_size is not None and len(field_data['content']) > self.max_size:
|
||||
if self.max_size is not None and len(content) > self.max_size:
|
||||
raise ValidationError, self.max_error_message
|
||||
|
||||
class MatchesRegularExpression:
|
||||
|
@ -45,27 +45,26 @@ def get_indexes(cursor, table_name):
|
||||
{'primary_key': boolean representing whether it's the primary key,
|
||||
'unique': boolean representing whether it's a unique index}
|
||||
"""
|
||||
# Get the table description because we only have the column indexes, and we
|
||||
# need the column names.
|
||||
desc = get_table_description(cursor, table_name)
|
||||
# This query retrieves each index on the given table.
|
||||
# This query retrieves each index on the given table, including the
|
||||
# first associated field name
|
||||
cursor.execute("""
|
||||
SELECT idx.indkey, idx.indisunique, idx.indisprimary
|
||||
SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
|
||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
|
||||
pg_catalog.pg_index idx
|
||||
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
|
||||
WHERE c.oid = idx.indrelid
|
||||
AND idx.indexrelid = c2.oid
|
||||
AND attr.attrelid = c.oid
|
||||
AND attr.attnum = idx.indkey[0]
|
||||
AND c.relname = %s""", [table_name])
|
||||
indexes = {}
|
||||
for row in cursor.fetchall():
|
||||
# row[0] (idx.indkey) is stored in the DB as an array. It comes out as
|
||||
# row[1] (idx.indkey) is stored in the DB as an array. It comes out as
|
||||
# a string of space-separated integers. This designates the field
|
||||
# indexes (1-based) of the fields that have indexes on the table.
|
||||
# Here, we skip any indexes across multiple fields.
|
||||
if ' ' in row[0]:
|
||||
if ' ' in row[1]:
|
||||
continue
|
||||
col_name = desc[int(row[0])-1][0]
|
||||
indexes[col_name] = {'primary_key': row[2], 'unique': row[1]}
|
||||
indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]}
|
||||
return indexes
|
||||
|
||||
# Maps type codes to Django Field types.
|
||||
|
@ -45,27 +45,26 @@ def get_indexes(cursor, table_name):
|
||||
{'primary_key': boolean representing whether it's the primary key,
|
||||
'unique': boolean representing whether it's a unique index}
|
||||
"""
|
||||
# Get the table description because we only have the column indexes, and we
|
||||
# need the column names.
|
||||
desc = get_table_description(cursor, table_name)
|
||||
# This query retrieves each index on the given table.
|
||||
# This query retrieves each index on the given table, including the
|
||||
# first associated field name
|
||||
cursor.execute("""
|
||||
SELECT idx.indkey, idx.indisunique, idx.indisprimary
|
||||
SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary
|
||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
|
||||
pg_catalog.pg_index idx
|
||||
pg_catalog.pg_index idx, pg_catalog.pg_attribute attr
|
||||
WHERE c.oid = idx.indrelid
|
||||
AND idx.indexrelid = c2.oid
|
||||
AND attr.attrelid = c.oid
|
||||
AND attr.attnum = idx.indkey[0]
|
||||
AND c.relname = %s""", [table_name])
|
||||
indexes = {}
|
||||
for row in cursor.fetchall():
|
||||
# row[0] (idx.indkey) is stored in the DB as an array. It comes out as
|
||||
# row[1] (idx.indkey) is stored in the DB as an array. It comes out as
|
||||
# a string of space-separated integers. This designates the field
|
||||
# indexes (1-based) of the fields that have indexes on the table.
|
||||
# Here, we skip any indexes across multiple fields.
|
||||
if ' ' in row[0]:
|
||||
if ' ' in row[1]:
|
||||
continue
|
||||
col_name = desc[int(row[0])-1][0]
|
||||
indexes[col_name] = {'primary_key': row[2], 'unique': row[1]}
|
||||
indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]}
|
||||
return indexes
|
||||
|
||||
# Maps type codes to Django Field types.
|
||||
|
@ -12,6 +12,10 @@ class CursorDebugWrapper:
|
||||
return self.cursor.execute(sql, params)
|
||||
finally:
|
||||
stop = time()
|
||||
# If params was a list, convert it to a tuple, because string
|
||||
# formatting with '%' only works with tuples or dicts.
|
||||
if not isinstance(params, (tuple, dict)):
|
||||
params = tuple(params)
|
||||
self.db.queries.append({
|
||||
'sql': sql % tuple(params),
|
||||
'time': "%.3f" % (stop - start),
|
||||
|
@ -161,7 +161,7 @@ class Model(object):
|
||||
(backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val])
|
||||
# If it does already exist, do an UPDATE.
|
||||
if cursor.fetchone():
|
||||
db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), False)) for f in non_pks]
|
||||
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
|
||||
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
||||
(backend.quote_name(self._meta.db_table),
|
||||
','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
|
||||
@ -171,11 +171,11 @@ class Model(object):
|
||||
record_exists = False
|
||||
if not pk_set or not record_exists:
|
||||
field_names = [backend.quote_name(f.column) for f in self._meta.fields if not isinstance(f, AutoField)]
|
||||
db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), True)) for f in self._meta.fields if not isinstance(f, AutoField)]
|
||||
db_values = [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)]
|
||||
# If the PK has been manually set, respect that.
|
||||
if pk_set:
|
||||
field_names += [f.column for f in self._meta.fields if isinstance(f, AutoField)]
|
||||
db_values += [f.get_db_prep_save(f.pre_save(getattr(self, f.column), True)) for f in self._meta.fields if isinstance(f, AutoField)]
|
||||
db_values += [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)]
|
||||
placeholders = ['%s'] * len(field_names)
|
||||
if self._meta.order_with_respect_to:
|
||||
field_names.append(backend.quote_name('_order'))
|
||||
@ -279,7 +279,7 @@ class Model(object):
|
||||
order_field = self._meta.order_with_respect_to
|
||||
where = ['%s %s (SELECT %s FROM %s WHERE %s=%%s)' % \
|
||||
(backend.quote_name('_order'), op, backend.quote_name('_order'),
|
||||
backend.quote_name(opts.db_table), backend.quote_name(opts.pk.column)),
|
||||
backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)),
|
||||
'%s=%%s' % backend.quote_name(order_field.column)]
|
||||
params = [self._get_pk_val(), getattr(self, order_field.attname)]
|
||||
obj = self._default_manager.order_by('_order').extra(where=where, params=params)[:1].get()
|
||||
|
@ -152,9 +152,9 @@ class Field(object):
|
||||
def get_internal_type(self):
|
||||
return self.__class__.__name__
|
||||
|
||||
def pre_save(self, value, add):
|
||||
def pre_save(self, model_instance, add):
|
||||
"Returns field's value just before saving."
|
||||
return value
|
||||
return getattr(model_instance, self.attname)
|
||||
|
||||
def get_db_prep_save(self, value):
|
||||
"Returns field's value prepared for saving into a database."
|
||||
@ -417,10 +417,13 @@ class DateField(Field):
|
||||
value = str(value)
|
||||
return Field.get_db_prep_lookup(self, lookup_type, value)
|
||||
|
||||
def pre_save(self, value, add):
|
||||
def pre_save(self, model_instance, add):
|
||||
if self.auto_now or (self.auto_now_add and add):
|
||||
return datetime.datetime.now()
|
||||
value = datetime.datetime.now()
|
||||
setattr(model_instance, self.attname, value)
|
||||
return value
|
||||
else:
|
||||
return super(DateField, self).pre_save(model_instance, add)
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
super(DateField,self).contribute_to_class(cls, name)
|
||||
@ -723,10 +726,13 @@ class TimeField(Field):
|
||||
value = str(value)
|
||||
return Field.get_db_prep_lookup(self, lookup_type, value)
|
||||
|
||||
def pre_save(self, value, add):
|
||||
def pre_save(self, model_instance, add):
|
||||
if self.auto_now or (self.auto_now_add and add):
|
||||
return datetime.datetime.now().time()
|
||||
value = datetime.datetime.now().time()
|
||||
setattr(model_instance, self.attname, value)
|
||||
return value
|
||||
else:
|
||||
return super(TimeField, self).pre_save(model_instance, add)
|
||||
|
||||
def get_db_prep_save(self, value):
|
||||
# Casts dates into string format for entry into database.
|
||||
|
@ -3,8 +3,8 @@ from django.db.models.fields import DateField, FieldDoesNotExist
|
||||
from django.db.models import signals
|
||||
from django.dispatch import dispatcher
|
||||
from django.utils.datastructures import SortedDict
|
||||
|
||||
import operator
|
||||
import re
|
||||
|
||||
# For Python 2.3
|
||||
if not hasattr(__builtins__, 'set'):
|
||||
@ -59,7 +59,7 @@ def orderlist2sql(order_list, opts, prefix=''):
|
||||
return ', '.join(output)
|
||||
|
||||
def quote_only_if_word(word):
|
||||
if ' ' in word:
|
||||
if re.search('\W', word): # Don't quote if there are spaces or non-word chars.
|
||||
return word
|
||||
else:
|
||||
return backend.quote_name(word)
|
||||
@ -380,6 +380,10 @@ class QuerySet(object):
|
||||
# (so that A.filter(args1) & A.filter(args2) does the same as
|
||||
# A.filter(args1).filter(args2)
|
||||
combined = other._clone()
|
||||
if self._select: combined._select.update(self._select)
|
||||
if self._where: combined._where.extend(self._where)
|
||||
if self._params: combined._params.extend(self._params)
|
||||
if self._tables: combined._tables.extend(self._tables)
|
||||
# If 'self' is ordered and 'other' isn't, propagate 'self's ordering
|
||||
if (self._order_by is not None and len(self._order_by) > 0) and \
|
||||
(combined._order_by is None or len(combined._order_by) == 0):
|
||||
|
@ -12,7 +12,10 @@ Managed transactions don't do those commits, but will need some kind of manual
|
||||
or implicit commits or rollbacks.
|
||||
"""
|
||||
|
||||
import thread
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
import dummy_thread as thread
|
||||
from django.db import connection
|
||||
from django.conf import settings
|
||||
|
||||
|
@ -577,7 +577,7 @@ class SelectMultipleField(SelectField):
|
||||
selected_html = ''
|
||||
if str(value) in str_data_list:
|
||||
selected_html = ' selected="selected"'
|
||||
output.append(' <option value="%s"%s>%s</option>' % (escape(value), selected_html, choice))
|
||||
output.append(' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(choice)))
|
||||
output.append(' </select>')
|
||||
return '\n'.join(output)
|
||||
|
||||
@ -641,7 +641,11 @@ class FileUploadField(FormField):
|
||||
self.validator_list = [self.isNonEmptyFile] + validator_list
|
||||
|
||||
def isNonEmptyFile(self, field_data, all_data):
|
||||
if not field_data['content']:
|
||||
try:
|
||||
content = field_data['content']
|
||||
except TypeError:
|
||||
raise validators.CriticalValidationError, gettext("No file was submitted. Check the encoding type on the form.")
|
||||
if not content:
|
||||
raise validators.CriticalValidationError, gettext("The submitted file is empty.")
|
||||
|
||||
def render(self, data):
|
||||
|
@ -10,14 +10,14 @@ def render_to_response(*args, **kwargs):
|
||||
return HttpResponse(loader.render_to_string(*args, **kwargs))
|
||||
load_and_render = render_to_response # For backwards compatibility.
|
||||
|
||||
def get_object_or_404(klass, **kwargs):
|
||||
def get_object_or_404(klass, *args, **kwargs):
|
||||
try:
|
||||
return klass._default_manager.get(**kwargs)
|
||||
return klass._default_manager.get(*args, **kwargs)
|
||||
except klass.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
def get_list_or_404(klass, **kwargs):
|
||||
obj_list = list(klass._default_manager.filter(**kwargs))
|
||||
def get_list_or_404(klass, *args, **kwargs):
|
||||
obj_list = list(klass._default_manager.filter(*args, **kwargs))
|
||||
if not obj_list:
|
||||
raise Http404
|
||||
return obj_list
|
||||
|
@ -234,4 +234,7 @@ class local(_localbase):
|
||||
return __del__
|
||||
__del__ = __del__()
|
||||
|
||||
from threading import currentThread, enumerate, RLock
|
||||
try:
|
||||
from threading import currentThread, enumerate, RLock
|
||||
except ImportError:
|
||||
from dummy_threading import currentThread, enumerate, RLock
|
||||
|
@ -28,7 +28,12 @@
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os, sys, thread, time
|
||||
import os, sys, time
|
||||
|
||||
try:
|
||||
import thread
|
||||
except ImportError:
|
||||
import dummy_thread as thread
|
||||
|
||||
RUN_RELOADER = True
|
||||
|
||||
|
@ -217,7 +217,7 @@ class Atom1Feed(SyndicationFeed):
|
||||
for item in self.items:
|
||||
handler.startElement(u"entry", {})
|
||||
handler.addQuickElement(u"title", item['title'])
|
||||
handler.addQuickElement(u"link", u"", {u"href": item['link']})
|
||||
handler.addQuickElement(u"link", u"", {u"href": item['link'], u"rel": u"alternate"})
|
||||
if item['pubdate'] is not None:
|
||||
handler.addQuickElement(u"updated", rfc3339_date(item['pubdate']).decode('ascii'))
|
||||
|
||||
|
@ -6,7 +6,8 @@ import datetime, time
|
||||
|
||||
def archive_index(request, queryset, date_field, num_latest=15,
|
||||
template_name=None, template_loader=loader,
|
||||
extra_context={}, allow_empty=False, context_processors=None):
|
||||
extra_context={}, allow_empty=False, context_processors=None,
|
||||
mimetype=None):
|
||||
"""
|
||||
Generic top-level archive of date-based objects.
|
||||
|
||||
@ -40,11 +41,12 @@ def archive_index(request, queryset, date_field, num_latest=15,
|
||||
c[key] = value()
|
||||
else:
|
||||
c[key] = value
|
||||
return HttpResponse(t.render(c))
|
||||
return HttpResponse(t.render(c), mimetype=mimetype)
|
||||
|
||||
def archive_year(request, year, queryset, date_field, template_name=None,
|
||||
template_loader=loader, extra_context={}, allow_empty=False,
|
||||
context_processors=None):
|
||||
context_processors=None, template_object_name='object', mimetype=None,
|
||||
make_object_list=False):
|
||||
"""
|
||||
Generic yearly archive view.
|
||||
|
||||
@ -54,6 +56,9 @@ def archive_year(request, year, queryset, date_field, template_name=None,
|
||||
List of months in this year with objects
|
||||
year
|
||||
This year
|
||||
object_list
|
||||
List of objects published in the given month
|
||||
(Only available if make_object_list argument is True)
|
||||
"""
|
||||
model = queryset.model
|
||||
now = datetime.datetime.now()
|
||||
@ -66,24 +71,29 @@ def archive_year(request, year, queryset, date_field, template_name=None,
|
||||
date_list = queryset.filter(**lookup_kwargs).dates(date_field, 'month')
|
||||
if not date_list and not allow_empty:
|
||||
raise Http404
|
||||
if make_object_list:
|
||||
object_list = queryset.filter(**lookup_kwargs).order_by(date_field)
|
||||
else:
|
||||
object_list = []
|
||||
if not template_name:
|
||||
template_name = "%s/%s_archive_year.html" % (model._meta.app_label, model._meta.object_name.lower())
|
||||
t = template_loader.get_template(template_name)
|
||||
c = RequestContext(request, {
|
||||
'date_list': date_list,
|
||||
'year': year,
|
||||
'%s_list' % template_object_name: object_list,
|
||||
}, context_processors)
|
||||
for key, value in extra_context.items():
|
||||
if callable(value):
|
||||
c[key] = value()
|
||||
else:
|
||||
c[key] = value
|
||||
return HttpResponse(t.render(c))
|
||||
return HttpResponse(t.render(c), mimetype=mimetype)
|
||||
|
||||
def archive_month(request, year, month, queryset, date_field,
|
||||
month_format='%b', template_name=None, template_loader=loader,
|
||||
extra_context={}, allow_empty=False, context_processors=None,
|
||||
template_object_name='object'):
|
||||
template_object_name='object', mimetype=None):
|
||||
"""
|
||||
Generic monthly archive view.
|
||||
|
||||
@ -134,12 +144,12 @@ def archive_month(request, year, month, queryset, date_field,
|
||||
c[key] = value()
|
||||
else:
|
||||
c[key] = value
|
||||
return HttpResponse(t.render(c))
|
||||
return HttpResponse(t.render(c), mimetype=mimetype)
|
||||
|
||||
def archive_week(request, year, week, queryset, date_field,
|
||||
template_name=None, template_loader=loader,
|
||||
extra_context={}, allow_empty=True, context_processors=None,
|
||||
template_object_name='object'):
|
||||
template_object_name='object', mimetype=None):
|
||||
"""
|
||||
Generic weekly archive view.
|
||||
|
||||
@ -181,12 +191,13 @@ def archive_week(request, year, week, queryset, date_field,
|
||||
c[key] = value()
|
||||
else:
|
||||
c[key] = value
|
||||
return HttpResponse(t.render(c))
|
||||
return HttpResponse(t.render(c), mimetype=mimetype)
|
||||
|
||||
def archive_day(request, year, month, day, queryset, date_field,
|
||||
month_format='%b', day_format='%d', template_name=None,
|
||||
template_loader=loader, extra_context={}, allow_empty=False,
|
||||
context_processors=None, template_object_name='object'):
|
||||
context_processors=None, template_object_name='object',
|
||||
mimetype=None):
|
||||
"""
|
||||
Generic daily archive view.
|
||||
|
||||
@ -233,7 +244,7 @@ def archive_day(request, year, month, day, queryset, date_field,
|
||||
c[key] = value()
|
||||
else:
|
||||
c[key] = value
|
||||
return HttpResponse(t.render(c))
|
||||
return HttpResponse(t.render(c), mimetype=mimetype)
|
||||
|
||||
def archive_today(request, **kwargs):
|
||||
"""
|
||||
@ -251,7 +262,7 @@ def object_detail(request, year, month, day, queryset, date_field,
|
||||
month_format='%b', day_format='%d', object_id=None, slug=None,
|
||||
slug_field=None, template_name=None, template_name_field=None,
|
||||
template_loader=loader, extra_context={}, context_processors=None,
|
||||
template_object_name='object'):
|
||||
template_object_name='object', mimetype=None):
|
||||
"""
|
||||
Generic detail view from year/month/day/slug or year/month/day/id structure.
|
||||
|
||||
@ -300,6 +311,6 @@ def object_detail(request, year, month, day, queryset, date_field,
|
||||
c[key] = value()
|
||||
else:
|
||||
c[key] = value
|
||||
response = HttpResponse(t.render(c))
|
||||
response = HttpResponse(t.render(c), mimetype=mimetype)
|
||||
populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
|
||||
return response
|
||||
|
@ -6,7 +6,8 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
def object_list(request, queryset, paginate_by=None, allow_empty=False,
|
||||
template_name=None, template_loader=loader,
|
||||
extra_context={}, context_processors=None, template_object_name='object'):
|
||||
extra_context={}, context_processors=None, template_object_name='object',
|
||||
mimetype=None):
|
||||
"""
|
||||
Generic list of objects.
|
||||
|
||||
@ -73,12 +74,13 @@ def object_list(request, queryset, paginate_by=None, allow_empty=False,
|
||||
model = queryset.model
|
||||
template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
|
||||
t = template_loader.get_template(template_name)
|
||||
return HttpResponse(t.render(c))
|
||||
return HttpResponse(t.render(c), mimetype=mimetype)
|
||||
|
||||
def object_detail(request, queryset, object_id=None, slug=None,
|
||||
slug_field=None, template_name=None, template_name_field=None,
|
||||
template_loader=loader, extra_context={},
|
||||
context_processors=None, template_object_name='object'):
|
||||
context_processors=None, template_object_name='object',
|
||||
mimetype=None):
|
||||
"""
|
||||
Generic list of objects.
|
||||
|
||||
@ -113,6 +115,6 @@ def object_detail(request, queryset, object_id=None, slug=None,
|
||||
c[key] = value()
|
||||
else:
|
||||
c[key] = value
|
||||
response = HttpResponse(t.render(c))
|
||||
response = HttpResponse(t.render(c), mimetype=mimetype)
|
||||
populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
|
||||
return response
|
||||
|
@ -56,6 +56,15 @@ location to users marked as staff members. You can use a set of
|
||||
required.
|
||||
================================ =========================================
|
||||
|
||||
Note that sometimes ``SetEnv`` doesn't play well in this mod_python
|
||||
configuration, for reasons unknown. If you're having problems getting
|
||||
mod_python to recognize your ``DJANGO_SETTINGS_MODULE``, you can set it using
|
||||
``PythonOption`` instead of ``SetEnv``. Therefore, these two Apache directives
|
||||
are equivalent::
|
||||
|
||||
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
|
||||
PythonOption DJANGO_SETTINGS_MODULE mysite.settings
|
||||
|
||||
.. _authentication system: http://www.djangoproject.com/documentation/authentication/
|
||||
.. _Subversion: http://subversion.tigris.org/
|
||||
.. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
|
||||
|
@ -182,6 +182,9 @@ a date in the *future* are not included.
|
||||
* ``context_processors``: A list of template-context processors to apply to
|
||||
the view's template. See the `RequestContext docs`_.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -247,6 +250,21 @@ with a date in the *future* are not displayed.
|
||||
* ``context_processors``: A list of template-context processors to apply to
|
||||
the view's template. See the `RequestContext docs`_.
|
||||
|
||||
* ``template_object_name``: Designates the name of the template variable
|
||||
to use in the template context. By default, this is ``'object'``. The
|
||||
view will append ``'_list'`` to the value of this parameter in
|
||||
determining the variable's name.
|
||||
|
||||
* ``make_object_list``: A boolean specifying whether to retrieve the full
|
||||
list of objects for this year and pass those to the template. If ``True``,
|
||||
this list of objects will be made available to the template as
|
||||
``object_list``. (The name ``object_list`` may be different; see the docs
|
||||
for ``object_list`` in the "Template context" section below.) By default,
|
||||
this is ``False``.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -259,8 +277,19 @@ In addition to ``extra_context``, the template's context will be:
|
||||
* ``date_list``: A list of ``datetime.date`` objects representing all
|
||||
months that have objects available in the given year, according to
|
||||
``queryset``, in ascending order.
|
||||
|
||||
* ``year``: The given year, as a four-character string.
|
||||
|
||||
* ``object_list``: If the ``make_object_list`` parameter is ``True``, this
|
||||
will be set to a list of objects available for the given year, ordered by
|
||||
the date field. This variable's name depends on the
|
||||
``template_object_name`` parameter, which is ``'object'`` by default. If
|
||||
``template_object_name`` is ``'foo'``, this variable's name will be
|
||||
``foo_list``.
|
||||
|
||||
If ``make_object_list`` is ``False``, ``object_list`` will be passed to
|
||||
the template as an empty list.
|
||||
|
||||
``django.views.generic.date_based.archive_month``
|
||||
-------------------------------------------------
|
||||
|
||||
@ -314,6 +343,9 @@ date in the *future* are not displayed.
|
||||
view will append ``'_list'`` to the value of this parameter in
|
||||
determining the variable's name.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -387,6 +419,9 @@ in the *future* are not displayed.
|
||||
view will append ``'_list'`` to the value of this parameter in
|
||||
determining the variable's name.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -463,6 +498,9 @@ a 404 error, regardless of whether any objects exist for future days.
|
||||
view will append ``'_list'`` to the value of this parameter in
|
||||
determining the variable's name.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -563,6 +601,9 @@ A page representing an individual object.
|
||||
* ``template_object_name``: Designates the name of the template variable
|
||||
to use in the template context. By default, this is ``'object'``.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -627,6 +668,9 @@ A page representing a list of objects.
|
||||
view will append ``'_list'`` to the value of this parameter in
|
||||
determining the variable's name.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
@ -717,6 +761,9 @@ A page representing an individual object.
|
||||
* ``template_object_name``: Designates the name of the template variable
|
||||
to use in the template context. By default, this is ``'object'``.
|
||||
|
||||
* ``mimetype``: The MIME type to use for the resulting document. Defaults
|
||||
to the value of the ``DEFAULT_MIME_TYPE`` setting.
|
||||
|
||||
**Template name:**
|
||||
|
||||
If ``template_name`` isn't specified, this view will use the template
|
||||
|
@ -162,11 +162,15 @@ A date field. Has a few extra optional arguments:
|
||||
====================== ===================================================
|
||||
``auto_now`` Automatically set the field to now every time the
|
||||
object is saved. Useful for "last-modified"
|
||||
timestamps.
|
||||
timestamps. Note that the current date is *always*
|
||||
used; it's not just a default value that you can
|
||||
override.
|
||||
|
||||
``auto_now_add`` Automatically set the field to now when the object
|
||||
is first created. Useful for creation of
|
||||
timestamps.
|
||||
timestamps. Note that the current date is *always*
|
||||
used; it's not just a default value that you can
|
||||
override.
|
||||
====================== ===================================================
|
||||
|
||||
The admin represents this as an ``<input type="text">`` with a JavaScript
|
||||
@ -488,6 +492,10 @@ cleared, the object will be deleted.
|
||||
It is an error to have an inline-editable relation without at least one
|
||||
``core=True`` field.
|
||||
|
||||
Please note that each field marked "core" is treated as a required field by the
|
||||
Django admin site. Essentially, this means you should put ``core=True`` on all
|
||||
required fields in your related object that is being edited inline.
|
||||
|
||||
``db_column``
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -197,6 +197,22 @@ will be sent on every request.
|
||||
Similarly, the ``expires`` part of a session cookie is updated each time the
|
||||
session cookie is sent.
|
||||
|
||||
Browser-length sessions vs. persistent sessions
|
||||
===============================================
|
||||
|
||||
You can control whether the session framework uses browser-length sessions vs.
|
||||
persistent sessions with the ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` setting.
|
||||
|
||||
By default, ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``False``, which
|
||||
means session cookies will be stored in users' browsers for as long as
|
||||
``SESSION_COOKIE_AGE``. Use this if you don't want people to have to log in
|
||||
every time they open a browser.
|
||||
|
||||
If ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``True``, Django will use
|
||||
browser-length cookies -- cookies that expire as soon as the user closes his or
|
||||
her browser. Use this if you want people to have to log in every time they open
|
||||
a browser.
|
||||
|
||||
Settings
|
||||
========
|
||||
|
||||
@ -225,6 +241,14 @@ Default: ``'sessionid'``
|
||||
|
||||
The name of the cookie to use for sessions. This can be whatever you want.
|
||||
|
||||
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
||||
-------------------------------
|
||||
|
||||
Default: ``False``
|
||||
|
||||
Whether to expire the session when the user closes his or her browser. See
|
||||
"Browser-length sessions vs. persistent sessions" above.
|
||||
|
||||
SESSION_SAVE_EVERY_REQUEST
|
||||
--------------------------
|
||||
|
||||
|
@ -603,6 +603,14 @@ Default: ``'sessionid'``
|
||||
The name of the cookie to use for sessions. This can be whatever you want.
|
||||
See the `session docs`_.
|
||||
|
||||
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
||||
-------------------------------
|
||||
|
||||
Default: ``False``
|
||||
|
||||
Whether to expire the session when the user closes his or her browser.
|
||||
See the `session docs`_.
|
||||
|
||||
SESSION_SAVE_EVERY_REQUEST
|
||||
--------------------------
|
||||
|
||||
|
@ -85,7 +85,7 @@ creating an empty class means "give this object an admin interface using
|
||||
all the default options."
|
||||
|
||||
Now reload the Django admin page to see your changes. Note that you don't have
|
||||
to restart the development server -- the server will auto-reloads your project,
|
||||
to restart the development server -- the server will auto-reload your project,
|
||||
so any modifications code will be seen immediately in your browser.
|
||||
|
||||
Explore the free admin functionality
|
||||
|
@ -209,13 +209,13 @@ So let's use Django's template system to separate the design from Python::
|
||||
})
|
||||
return HttpResponse(t.render(c))
|
||||
|
||||
That code loads the template called "polls/index" and passes it a context. The
|
||||
That code loads the template called "polls/index.html" and passes it a context. The
|
||||
context is a dictionary mapping template variable names to Python objects.
|
||||
|
||||
Reload the page. Now you'll see an error::
|
||||
|
||||
TemplateDoesNotExist: Your TEMPLATE_DIRS settings is empty.
|
||||
Change it to point to at least one template directory.
|
||||
TemplateDoesNotExist at /polls/
|
||||
polls/index.html
|
||||
|
||||
Ah. There's no template yet. First, create a directory, somewhere on your
|
||||
filesystem, whose contents Django can access. (Django runs as whatever user
|
||||
|
@ -1,5 +1,12 @@
|
||||
"""
|
||||
23. Giving models a custom manager
|
||||
|
||||
You can use a custom ``Manager`` in a particular model by extending the base
|
||||
``Manager`` class and instantiating your custom ``Manager`` in your model.
|
||||
|
||||
There are two reasons you might want to customize a ``Manager``: to add extra
|
||||
``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager``
|
||||
returns.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
@ -19,7 +26,7 @@ class Person(models.Model):
|
||||
def __repr__(self):
|
||||
return "%s %s" % (self.first_name, self.last_name)
|
||||
|
||||
# An example of a custom manager that sets a core_filter on its lookups.
|
||||
# An example of a custom manager that sets get_query_set().
|
||||
|
||||
class PublishedBookManager(models.Manager):
|
||||
def get_query_set(self):
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
3. Giving models custom methods and custom managers
|
||||
3. Giving models custom methods
|
||||
|
||||
Any method you add to a model will be available to instances.
|
||||
"""
|
||||
|
@ -1,7 +1,12 @@
|
||||
"""
|
||||
XXX. Callable defaults
|
||||
31. Callable defaults
|
||||
|
||||
???
|
||||
You can pass callable objects as the ``default`` parameter to a field. When
|
||||
the object is created without an explicit value passed in, Django will call
|
||||
the method to determine the default value.
|
||||
|
||||
This example uses ``datetime.datetime.now`` as the default for the ``pub_date``
|
||||
field.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
@ -9,9 +14,9 @@ from datetime import datetime
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(maxlength=100, default='Default headline')
|
||||
pub_date = models.DateTimeField(default = datetime.now)
|
||||
pub_date = models.DateTimeField(default=datetime.now)
|
||||
|
||||
def __repr__(self):
|
||||
def __str__(self):
|
||||
return self.headline
|
||||
|
||||
API_TESTS = """
|
||||
@ -43,6 +48,4 @@ API_TESTS = """
|
||||
>>> d = now - a.pub_date
|
||||
>>> d.seconds < 5
|
||||
True
|
||||
|
||||
|
||||
"""
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""
|
||||
26. A test to check that the model validator works can correctly identify errors in a model.
|
||||
26. Invalid models
|
||||
|
||||
This example exists purely to point out errors in models.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
@ -1,8 +1,7 @@
|
||||
"""
|
||||
27. Many-to-many and many-to-one relationships to the same table.
|
||||
|
||||
This is a response to bug #1535
|
||||
28. Many-to-many and many-to-one relationships to the same table
|
||||
|
||||
Make sure to set ``related_name`` if you use relationships to the same table.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
@ -14,8 +13,9 @@ class Issue(models.Model):
|
||||
num = models.IntegerField()
|
||||
cc = models.ManyToManyField(User, blank=True, related_name='test_issue_cc')
|
||||
client = models.ForeignKey(User, related_name='test_issue_client')
|
||||
def __repr__(self):
|
||||
return "<Issue %d>" % (self.num,)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.num)
|
||||
|
||||
class Meta:
|
||||
ordering = ('num',)
|
||||
@ -47,20 +47,20 @@ API_TESTS = """
|
||||
>>> i3.cc.add(r)
|
||||
>>> from django.db.models.query import Q
|
||||
>>> Issue.objects.filter(client=r.id)
|
||||
[<Issue 1>, <Issue 2>]
|
||||
[<Issue: 1>, <Issue: 2>]
|
||||
>>> Issue.objects.filter(client=g.id)
|
||||
[<Issue 3>]
|
||||
[<Issue: 3>]
|
||||
>>> Issue.objects.filter(cc__id__exact=g.id)
|
||||
[]
|
||||
>>> Issue.objects.filter(cc__id__exact=r.id)
|
||||
[<Issue 2>, <Issue 3>]
|
||||
[<Issue: 2>, <Issue: 3>]
|
||||
|
||||
# Queries that combine results from the m2m and the m2o relationship.
|
||||
# 3 ways of saying the same thing:
|
||||
>>> Issue.objects.filter(Q(cc__id__exact=r.id) | Q(client=r.id))
|
||||
[<Issue 1>, <Issue 2>, <Issue 3>]
|
||||
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
|
||||
>>> Issue.objects.filter(cc__id__exact=r.id) | Issue.objects.filter(client=r.id)
|
||||
[<Issue 1>, <Issue 2>, <Issue 3>]
|
||||
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
|
||||
>>> Issue.objects.filter(Q(client=r.id) | Q(cc__id__exact=r.id))
|
||||
[<Issue 1>, <Issue 2>, <Issue 3>]
|
||||
[<Issue: 1>, <Issue: 2>, <Issue: 3>]
|
||||
"""
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
26. Many-to-many relationships between the same two tables
|
||||
27. Many-to-many relationships between the same two tables
|
||||
|
||||
In this example, A Person can have many friends, who are also people. Friendship is a
|
||||
symmetrical relationshiup - if I am your friend, you are my friend.
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""
|
||||
25. Default manipulators
|
||||
26. Default manipulators
|
||||
|
||||
Each model gets an AddManipulator and ChangeManipulator by default.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""
|
||||
XX. Model inheritance
|
||||
|
||||
Model inheritance isn't yet supported.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
@ -1,12 +1,11 @@
|
||||
"""
|
||||
20. Object Pagination
|
||||
|
||||
Django provides a framework for paginating a list of objects in a few.
|
||||
This is often useful for dividing search results or long lists of objects
|
||||
in to easily readable pages.
|
||||
|
||||
29. Object pagination
|
||||
|
||||
Django provides a framework for paginating a list of objects in a few lines
|
||||
of code. This is often useful for dividing search results or long lists of
|
||||
objects into easily readable pages.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
||||
class Article(models.Model):
|
||||
@ -56,4 +55,13 @@ False
|
||||
>>> paginator.has_previous_page(1)
|
||||
True
|
||||
|
||||
>>> paginator.first_on_page(0)
|
||||
1
|
||||
>>> paginator.first_on_page(1)
|
||||
6
|
||||
>>> paginator.last_on_page(0)
|
||||
5
|
||||
>>> paginator.last_on_page(1)
|
||||
9
|
||||
|
||||
"""
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""
|
||||
22. Using properties on models
|
||||
|
||||
Use properties on models just like on any other Python object.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
XXX. Transactions
|
||||
15. Transactions
|
||||
|
||||
Django handles transactions in three different ways. The default is to commit
|
||||
each transaction upon a write, but you can decorate a function to get
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""
|
||||
XX. Validation
|
||||
30. Validation
|
||||
|
||||
This is an experimental feature!
|
||||
|
||||
Each model instance has a validate() method that returns a dictionary of
|
||||
validation errors in the instance's fields. This method has a side effect
|
||||
|
Loading…
x
Reference in New Issue
Block a user