Changeset 854
- Timestamp:
- 10/13/05 13:28:44 (3 years ago)
- Files:
-
- django/branches/new-admin/django/conf/admin_media/css/global.css (modified) (2 diffs)
- django/branches/new-admin/django/conf/admin_templates/admin_change_form.html (modified) (2 diffs)
- django/branches/new-admin/django/conf/admin_templates/admin_field_line.html (modified) (1 diff)
- django/branches/new-admin/django/core/cache.py (modified) (19 diffs)
- django/branches/new-admin/django/core/db/backends/mysql.py (modified) (1 diff)
- django/branches/new-admin/django/core/db/backends/postgresql.py (modified) (1 diff)
- django/branches/new-admin/django/core/db/backends/sqlite3.py (modified) (1 diff)
- django/branches/new-admin/django/core/formfields.py (modified) (1 diff)
- django/branches/new-admin/django/core/management.py (modified) (2 diffs)
- django/branches/new-admin/django/core/meta/fields.py (modified) (2 diffs)
- django/branches/new-admin/django/core/meta/__init__.py (modified) (3 diffs)
- django/branches/new-admin/django/middleware/cache.py (modified) (2 diffs)
- django/branches/new-admin/django/templatetags/admin_modify.py (modified) (3 diffs)
- django/branches/new-admin/django/utils/decorators.py (modified) (1 diff)
- django/branches/new-admin/django/views/admin/main.py (modified) (5 diffs)
- django/branches/new-admin/django/views/generic/list_detail.py (modified) (2 diffs)
- django/branches/new-admin/docs/db-api.txt (modified) (2 diffs)
- django/branches/new-admin/docs/generic_views.txt (modified) (6 diffs)
- django/branches/new-admin/docs/install.txt (modified) (3 diffs)
- django/branches/new-admin/docs/model-api.txt (modified) (6 diffs)
- django/branches/new-admin/docs/modpython.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/new-admin/django/conf/admin_media/css/global.css
r537 r854 231 231 fieldset.collapse h2 a.collapse-toggle { color:#ffc; } 232 232 fieldset.collapse h2 a.collapse-toggle:hover { text-decoration:underline; } 233 .hidden { display:none; } 233 234 234 235 /* MESSAGES & ERRORS */ … … 349 350 .timelist a { padding:2px; } 350 351 351 /* O LD ORDERING WIDGET */352 /* ORDERING WIDGET */ 352 353 353 354 ul#orderthese { padding:0; margin:0; list-style-type:none; } django/branches/new-admin/django/conf/admin_templates/admin_change_form.html
r802 r854 3 3 {% load adminmedia %} 4 4 {% block extrahead %} 5 6 5 {% for js in javascript_imports %} 7 6 {% include_admin_script js %} 8 7 {% endfor %} 9 10 8 {% endblock %} 11 12 9 {% block coltype %}{{ coltype }}{% endblock %} 13 14 10 {% block bodyclass %}{{app_label}}-{{object_name.lower}} change-form{% endblock %} 15 16 11 {% block breadcrumbs %}{% if not is_popup %} 17 12 <div class="breadcrumbs"> 18 13 <a href="../../../">Home</a> › 19 14 <a href="../">{{verbose_name_plural|capfirst}}</a> › 20 {% if add %} 21 Add {{verbose_name}} 22 {% else %} 23 {{original|striptags|truncatewords:"18"}} 24 {% endif %} 15 {% if add %}Add {{verbose_name}}{% else %}{{original|striptags|truncatewords:"18"}}{% endif %} 25 16 </div> 26 {% endif %} 27 {% endblock %} 17 {% endif %}{% endblock %} 28 18 29 19 {% block content %}<div id="content-main"> … … 83 73 84 74 {% if add %} 85 <script type="text/javascript">document.getElementById(" id_{{first_field}}").focus();</script>'75 <script type="text/javascript">document.getElementById("{{first_form_field_id}}").focus();</script> 86 76 {% endif %} 87 77 django/branches/new-admin/django/conf/admin_templates/admin_field_line.html
r802 r854 1 1 <div class="{{ class_names }}" > 2 {% for bound_field in bound_fields %} 3 {{ bound_field.html_error_list }} 4 {% endfor %} 5 6 {% for bound_field in bound_fields %} 7 {% if bound_field.has_label_first %} 8 {% field_label bound_field %} 9 {% endif %} 10 11 {% field_widget bound_field %} 12 13 {% if not bound_field.has_label_first %} 14 {% field_label bound_field %} 15 {% endif %} 16 17 {% if change %} 18 {% if bound_field.field.primary_key %} 19 {{ bound_field.original_value }} 20 {% endif %} 21 22 {% if bound_field.raw_id_admin %} 23 {% if bound_field.existing_repr %} 24 <strong>{{ bound_field.existing_repr|truncatewords:"14" }}</strong> 25 {% endif %} 26 {% endif %} 27 {% endif %} 28 29 {% if bound_field.field.help_text %} 30 <p class="help"> 31 {{bound_field.field.help_text}} 32 </p> 33 {% endif %} 34 35 {% endfor %} 2 {% for bound_field in bound_fields %}{{ bound_field.html_error_list }}{% endfor %} 3 {% for bound_field in bound_fields %} 4 {% if bound_field.has_label_first %} 5 {% field_label bound_field %} 6 {% endif %} 7 {% field_widget bound_field %} 8 {% if not bound_field.has_label_first %} 9 {% field_label bound_field %} 10 {% endif %} 11 {% if change %} 12 {% if bound_field.field.primary_key %} 13 {{ bound_field.original_value }} 14 {% endif %} 15 {% if bound_field.raw_id_admin %} 16 {% if bound_field.existing_repr %} <strong>{{ bound_field.existing_repr|truncatewords:"14" }}</strong>{% endif %} 17 {% endif %} 18 {% endif %} 19 {% if bound_field.field.help_text %}<p class="help">{{bound_field.field.help_text}}</p>{% endif %} 20 {% endfor %} 36 21 </div> django/branches/new-admin/django/core/cache.py
r701 r854 16 16 on localhost port 11211. 17 17 18 db://tablename/ A database backend in a table named 18 db://tablename/ A database backend in a table named 19 19 "tablename". This table should be created 20 20 with "django-admin createcachetable". … … 27 27 testing. Note that this cache backend is 28 28 NOT threadsafe! 29 29 30 30 locmem:/// A more sophisticaed local memory cache; 31 31 this is multi-process- and thread-safe. … … 73 73 74 74 class _Cache: 75 76 75 def __init__(self, params): 77 76 timeout = params.get('timeout', 300) … … 133 132 else: 134 133 class _MemcachedCache(_Cache): 135 """Memcached cache backend.""" 136 134 "Memcached cache backend." 137 135 def __init__(self, server, params): 138 136 _Cache.__init__(self, params) … … 162 160 163 161 class _SimpleCache(_Cache): 164 """Simple single-process in-memory cache""" 165 162 "Simple single-process in-memory cache." 166 163 def __init__(self, host, params): 167 164 _Cache.__init__(self, params) … … 231 228 except ImportError: 232 229 import pickle 230 import copy 233 231 from django.utils.synch import RWLock 234 232 235 233 class _LocMemCache(_SimpleCache): 236 """Thread-safe in-memory cache""" 237 234 "Thread-safe in-memory cache." 238 235 def __init__(self, host, params): 239 236 _SimpleCache.__init__(self, host, params) … … 251 248 should_delete = True 252 249 else: 253 return self._cache[key]250 return copy.deepcopy(self._cache[key]) 254 251 finally: 255 252 self._lock.reader_leaves() … … 262 259 finally: 263 260 self._lock.writer_leaves() 264 261 265 262 def set(self, key, value, timeout=None): 266 263 self._lock.writer_enters() … … 269 266 finally: 270 267 self._lock.writer_leaves() 271 268 272 269 def delete(self, key): 273 270 self._lock.writer_enters() … … 285 282 286 283 class _FileCache(_SimpleCache): 287 """File-based cache""" 288 284 "File-based cache." 289 285 def __init__(self, dir, params): 290 286 self._dir = dir … … 294 290 del self._cache 295 291 del self._expire_info 296 292 297 293 def get(self, key, default=None): 298 294 fname = self._key_to_file(key) … … 309 305 pass 310 306 return default 311 307 312 308 def set(self, key, value, timeout=None): 313 309 fname = self._key_to_file(key) … … 328 324 except (IOError, OSError): 329 325 raise 330 326 331 327 def delete(self, key): 332 328 try: … … 334 330 except (IOError, OSError): 335 331 pass 336 332 337 333 def has_key(self, key): 338 334 return os.path.exists(self._key_to_file(key)) 339 335 340 336 def _cull(self, filelist): 341 337 if self.cull_frequency == 0: … … 349 345 pass 350 346 351 def _createdir(self): 347 def _createdir(self): 352 348 try: 353 349 os.makedirs(self._dir) … … 367 363 368 364 class _DBCache(_Cache): 369 """SQL cache backend""" 370 365 "SQL cache backend." 371 366 def __init__(self, table, params): 372 367 _Cache.__init__(self, params) 373 368 self._table = table 374 max_entries = params.get('max_entries', 300) 375 try: 376 self._max_entries = int(max_entries) 377 except (ValueError, TypeError): 378 self._max_entries = 300 379 cull_frequency = params.get('cull_frequency', 3) 380 try: 381 self._cull_frequency = int(cull_frequency) 382 except (ValueError, TypeError): 383 self._cull_frequency = 3 384 369 max_entries = params.get('max_entries', 300) 370 try: 371 self._max_entries = int(max_entries) 372 except (ValueError, TypeError): 373 self._max_entries = 300 374 cull_frequency = params.get('cull_frequency', 3) 375 try: 376 self._cull_frequency = int(cull_frequency) 377 except (ValueError, TypeError): 378 self._cull_frequency = 3 379 385 380 def get(self, key, default=None): 386 381 cursor = db.cursor() … … 395 390 return default 396 391 return pickle.loads(base64.decodestring(row[1])) 397 392 398 393 def set(self, key, value, timeout=None): 399 394 if timeout is None: … … 418 413 else: 419 414 db.commit() 420 415 421 416 def delete(self, key): 422 417 cursor = db.cursor() 423 418 cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % self._table, [key]) 424 419 db.commit() 425 420 426 421 def has_key(self, key): 427 422 cursor = db.cursor() 428 423 cursor.execute("SELECT cache_key FROM %s WHERE cache_key = %%s" % self._table, [key]) 429 424 return cursor.fetchone() is not None 430 425 431 426 def _cull(self, cursor, now): 432 427 if self._cull_frequency == 0: … … 439 434 cursor.execute("SELECT cache_key FROM %s ORDER BY cache_key LIMIT 1 OFFSET %%s" % self._table, [num / self._cull_frequency]) 440 435 cursor.execute("DELETE FROM %s WHERE cache_key < %%s" % self._table, [cursor.fetchone()[0]]) 441 436 442 437 ########################################## 443 438 # Read settings and load a cache backend # django/branches/new-admin/django/core/db/backends/mysql.py
r819 r854 144 144 'EmailField': 'varchar(75)', 145 145 'FileField': 'varchar(100)', 146 'FilePathField': 'varchar(100)', 146 147 'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)', 147 148 'ImageField': 'varchar(100)', django/branches/new-admin/django/core/db/backends/postgresql.py
r713 r854 155 155 'EmailField': 'varchar(75)', 156 156 'FileField': 'varchar(100)', 157 'FilePathField': 'varchar(100)', 157 158 'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)', 158 159 'ImageField': 'varchar(100)', django/branches/new-admin/django/core/db/backends/sqlite3.py
r713 r854 155 155 'EmailField': 'varchar(75)', 156 156 'FileField': 'varchar(100)', 157 'FilePathField': 'varchar(100)', 157 158 'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)', 158 159 'ImageField': 'varchar(100)', django/branches/new-admin/django/core/formfields.py
r791 r854 823 823 #################### 824 824 825 class FilePathField(SelectField): 826 "A SelectField whose choices are the files in a given directory." 827 def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=[]): 828 import os 829 if match is not None: 830 import re 831 match_re = re.compile(match) 832 choices = [] 833 if recursive: 834 for root, dirs, files in os.walk(path): 835 for f in files: 836 if match is None or match_re.search(f): 837 choices.append((os.path.join(path, f), f)) 838 else: 839 try: 840 for f in os.listdir(path): 841 full_file = os.path.join(path, f) 842 if os.path.isfile(full_file) and (match is None or match_re.search(f)): 843 choices.append((full_file, f)) 844 except OSError: 845 pass 846 SelectField.__init__(self, field_name, choices, 1, is_required, validator_list) 847 825 848 class PhoneNumberField(TextField): 826 849 "A convenience FormField for validating phone numbers (e.g. '630-555-1234')" django/branches/new-admin/django/core/management.py
r791 r854 144 144 for row in cursor.fetchall(): 145 145 output.append("DELETE FROM auth_admin_log WHERE content_type_id = %s;" % row[0]) 146 147 # Close database connection explicitly, in case this output is being piped 148 # directly into a database client, to avoid locking issues. 149 db.db.close() 146 150 147 151 return output[::-1] # Reverse it, to deal with table dependencies. … … 637 641 except KeyboardInterrupt: 638 642 sys.exit(0) 639 from django.utils import autoreload 640 autoreload.main(inner_run) 643 #from django.utils import autoreload 644 #autoreload.main(inner_run) 645 inner_run() 641 646 runserver.args = '[optional port number, or ipaddr:port]' 642 647 django/branches/new-admin/django/core/meta/fields.py
r803 r854 291 291 """ 292 292 return { self.get_db_column(): self._get_val_from_obj(obj)} 293 293 294 def get_follow(self, override=None): 295 if override: 296 return override 297 else: 298 return self.editable 294 299 295 300 class AutoField(Field): … … 464 469 return os.path.normpath(f) 465 470 471 class FilePathField(Field): 472 def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): 473 self.path, self.match, self.recursive = path, match, recursive 474 Field.__init__(self, verbose_name, name, **kwargs) 475 476 def get_manipulator_field_objs(self): 477 return [curry(formfields.FilePathField, path=self.path, match=self.match, recursive=self.recursive)] 478 466 479 class FloatField(Field): 467 480 empty_strings_allowed = False django/branches/new-admin/django/core/meta/__init__.py
r803 r854 233 233 else: 234 234 count = self.field.rel.num_in_admin 235 235 236 236 fields = [] 237 238 239 237 for i in range(count): 240 238 for f in self.opts.fields + self.opts.many_to_many: … … 425 423 426 424 def get_data_holders(self, follow=None): 425 if follow == None : 426 follow = self.get_follow() 427 427 return [f for f in self.fields + self.many_to_many + self.get_all_related_objects_wrapped() if follow.get(f.name, None) ] 428 428 429 429 def get_follow(self, override=None): 430 430 follow = {} 431 432 for f in self.fields + self.many_to_many: 431 for f in self.fields + self.many_to_many + self.get_all_related_objects_wrapped(): 433 432 if override and override.has_key(f.name): 434 fol = override[f.name]433 child_override = override[f.name] 435 434 else: 436 fol = f.editable 435 child_override = None 436 fol = f.get_follow(child_override) 437 437 if fol: 438 438 follow[f.name] = fol 439 440 for f in self.get_all_related_objects_wrapped():441 if override and override.has_key(f.name):442 fol = f.get_follow(override[f.name])443 else:444 fol = f.get_follow(None)445 if fol:446 follow[f.name] = fol447 448 439 return follow 449 440 … … 479 470 field_type (e.g. FileField). 480 471 """ 472 #TODO: follow 481 473 if not hasattr(self, '_field_types'): 482 474 self._field_types = {} django/branches/new-admin/django/middleware/cache.py
r819 r854 1 import copy2 1 from django.conf import settings 3 2 from django.core.cache import cache … … 50 49 51 50 request._cache_update_cache = False 52 return copy.copy(response)51 return response 53 52 54 53 def process_response(self, request, response): django/branches/new-admin/django/templatetags/admin_modify.py
r818 r854 9 9 10 10 from django.views.admin.main import AdminBoundField 11 from django.core.meta.fields import BoundField 11 from django.core.meta.fields import BoundField, Field 12 12 import re 13 13 … … 25 25 26 26 #@inclusion_tag('admin_submit_line', takes_context=True) 27 def submit_row(context): 27 def submit_row(context): 28 28 change = context['change'] 29 29 add = context['add'] … … 69 69 70 70 class FieldWidgetNode(template.Node): 71 nodelists = {} 72 default = None 73 71 74 def __init__(self, bound_field_var): 72 75 self.bound_field_var = bound_field_var 73 self.nodelists = {} 74 t = template_loader.get_template("widget/default") 75 self.default = t.nodelist 76 76 77 def get_nodelist(cls, klass): 78 if not cls.nodelists.has_key(klass): 79 try: 80 field_class_name = klass.__name__ 81 template_name = "widget/%s" % \ 82 class_name_to_underscored(field_class_name) 83 nodelist = template_loader.get_template(template_name).nodelist 84 except template.TemplateDoesNotExist: 85 super_klass = bool(klass.__bases__) and klass.__bases__[0] or None 86 if super_klass and super_klass != Field: 87 nodelist = cls.get_nodelist(super_klass) 88 else: 89 if not cls.default: 90 cls.default = template_loader.get_template("widget/default").nodelist 91 nodelist = cls.default 92 93 cls.nodelists[klass] = nodelist 94 return nodelist 95 else: 96 return cls.nodelists[klass] 97 get_nodelist = classmethod(get_nodelist) 98 99 77 100 def render(self, context): 78 101 79 102 bound_field = template.resolve_variable(self.bound_field_var, context) 80 add = context['add']81 change = context['change']82 103 83 104 context.push() 84 105 context['bound_field'] = bound_field 85 klass = bound_field.field.__class__ 86 if not self.nodelists.has_key(klass): 87 t = None 88 while klass: 89 try: 90 field_class_name = klass.__name__ 91 template_name = "widget/%s" % \ 92 class_name_to_underscored(field_class_name) 93 t = template_loader.get_template(template_name) 94 break 95 except template.TemplateDoesNotExist: 96 klass = bool(klass.__bases__) and klass.__bases__[0] or None 97 98 if t == None: 99 nodelist = self.default 100 else: 101 nodelist = t.nodelist 102 103 self.nodelists[klass] = nodelist 104 105 output = self.nodelists[klass].render(context) 106 107 output = self.get_nodelist(bound_field.field.__class__).render(context) 106 108 context.pop() 107 109 return output django/branches/new-admin/django/utils/decorators.py
r819 r854 13 13 if result is not None: 14 14 return result 15 if hasattr(middleware, 'process_view'): 16 result = middleware.process_view(request, view_func, **kwargs) 17 if result is not None: 18 return result 15 19 response = view_func(request, *args, **kwargs) 16 20 if hasattr(middleware, 'process_response'): django/branches/new-admin/django/views/admin/main.py
r819 r854 606 606 def fill_extra_context(opts, app_label, context, add=False, change=False, show_delete=False, form_url=''): 607 607 admin_field_objs = opts.admin.get_field_objs(opts) 608 608 609 ordered_objects = opts.get_ordered_objects()[:] 609 610 auto_populated_fields = [f for f in opts.fields if f.prepopulate_from] … … 622 623 form = context['form'] 623 624 original = context['original'] 625 626 field_sets = opts.admin.get_field_sets(opts) 624 627 bound_field_sets = [field_set.bind(form, original, AdminBoundFieldSet) 625 for field_set in opts.admin.get_field_sets(opts)] 626 628 for field_set in field_sets] 629 630 first_form_field = bound_field_sets[0].bound_field_lines[0].bound_fields[0].form_fields[0]; 631 627 632 inline_related_objects = opts.get_inline_related_objects_wrapped() 628 633 … … 632 637 'add': add, 633 638 'change': change, 639 'first_form_field_id': first_form_field.get_id(), 634 640 'ordered_objects' : ordered_objects, 635 641 'ordered_object_names' : ordered_object_names, … … 644 650 'content_type_id' : opts.get_content_type_id(), 645 651 'save_on_top' : opts.admin.save_on_top, 646 'verbose_name_plural': opts.verbose_name_plural, 652 'verbose_name_plural': opts.verbose_name_plural, 653 'verbose_name': opts.verbose_name, 647 654 'save_as': opts.admin.save_as, 648 655 'app_label': app_label, … … 712 719 713 720 714 fill_extra_context(opts, app_label, c, change=False)721 fill_extra_context(opts, app_label, c, add=True) 715 722 716 723 return render_to_response("admin_change_form", context_instance=c) django/branches/new-admin/django/views/generic/list_detail.py
r741 r854 33 33 pages 34 34 number of pages, total 35 hits 36 number of objects, total 35 37 """ 36 38 mod = models.get_module(app_label, module_name) … … 57 59 'previous': page - 1, 58 60 'pages': paginator.pages, 61 'hits' : paginator.hits, 59 62 }) 60 63 else: django/branches/new-admin/docs/db-api.txt
r791 r854 450 450 4 451 451 452 Each of those ``add_choice`` methods is equivalent to (except obviously much 453 simpler than):: 452 Each of those ``add_choice`` methods is equivalent to (but much simpler than):: 454 453 455 454 >>> c = polls.Choice(poll_id=p.id, choice="Over easy", votes=0) … … 459 458 for the ``id`` field, nor do you give a value for the field that stores 460 459 the relation (``poll_id`` in this case). 460 461 The ``add_FOO()`` method always returns the newly created object. 461 462 462 463 Deleting objects django/branches/new-admin/docs/generic_views.txt
r528 r854 116 116 pattern. 117 117 118 Uses the template ``app_label/module_name_ _archive_year`` by default.118 Uses the template ``app_label/module_name_archive_year`` by default. 119 119 120 120 Has the following template context: … … 135 135 numbers, use ``"%m"``. 136 136 137 Uses the template ``app_label/module_name_ _archive_month`` by default.137 Uses the template ``app_label/module_name_archive_month`` by default. 138 138 139 139 Has the following template context: … … 152 152 decimal number, 1-31). 153 153 154 Uses the template ``app_label/module_name_ _archive_day`` by default.154 Uses the template ``app_label/module_name_archive_day`` by default. 155 155 156 156 Has the following template context: … … 247 247 ``pages`` 248 248 Number of pages total 249 ``hits`` 250 Total number of objects 249 251 250 252 ``object_detail`` … … 273 275 could use ``post_save_redirect="/polls/%(slug)s/"``. 274 276 275 Uses the template ``app_label/module_name_ _form`` by default. This is the277 Uses the template ``app_label/module_name_form`` by default. This is the 276 278 same template as the ``update_object`` view below. Your template can tell 277 279 the different by the presence or absence of ``{{ object }}`` in the … … 295 297 ``post_save_redirect`` as ``create_object`` does. 296 298 297 Uses the template ``app_label/module_name_ _form`` by default.299 Uses the template ``app_label/module_name_form`` by default. 298 300 299 301 Has the following template context: django/branches/new-admin/docs/install.txt
r484 r854 22 22 23 23 If you can't use mod_python for some reason, fear not: Django follows the WSGI_ 24 spec, which allows it to run on a variety of server platforms. As people25 experiment with different server platforms, we'll update this document to 26 give specific installation instructions foreach platform.24 spec, which allows it to run on a variety of server platforms. See the 25 `server-arrangements wiki page`_ for specific installation instructions for 26 each platform. 27 27 28 28 .. _Apache: http://httpd.apache.org/ … … 30 30 .. _WSGI: http://www.python.org/peps/pep-0333.html 31 31 .. _How to use Django with mod_python: http://www.djangoproject.com/documentation/modpython/ 32 .. _server-arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements 32 33 33 34 Get your database running … … 37 38 make sure a database server is running. Django works with PostgreSQL_ 38 39 (recommended), MySQL_ and SQLite_. 39 40 Note that support for MySQL and SQLite is a recent development, and Django41 hasn't been comprehensively tested in those environments. If you find any bugs42 in Django's MySQL or SQLite bindings, please file them in43 `Django's ticket system`_ so we can fix them immediately.44 40 45 41 Additionally, you'll need to make sure your Python database bindings are django/branches/new-admin/docs/model-api.txt
r749 r854 96 96 ) 97 97 98 The first element in each tuple is the actual value to be stored. The99 second element is the human-readable name for the option.98 The first element in each tuple is the actual value to be stored. The 99 second element is the human-readable name for the option. 100 100 101 101 ``core`` … … 249 249 250 250 The admin represents this as an ``<input type="file">`` (a file-upload widget). 251 252 Using a `FieldField` or an ``ImageField`` (see below) in a model takes a few 251 252 Using a `FieldField` or an ``ImageField`` (see below) in a model takes a few 253 253 steps: 254 254 255 255 1. In your settings file, you'll need to define ``MEDIA_ROOT``as the 256 256 full path to a directory where you'd like Django to store uploaded … … 259 259 sure that this directory is writable by the Web server's user 260 260 account. 261 262 2. Add the ``FileField`` or ``ImageField`` to your model, making sure 261 262 2. Add the ``FileField`` or ``ImageField`` to your model, making sure 263 263 to define the ``upload_to`` option to tell Django to which 264 264 subdirectory of ``MEDIA_ROOT`` it should upload files. … … 270 270 the absolute URL to your image in a template with ``{{ 271 271 object.get_mug_shot_url }}``. 272 272 273 273 .. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941 274 275 ``FilePathField`` 276 A field whose choices are limited to the filenames in a certain directory 277 on the filesystem. Has three special arguments, of which the first is 278 required: 279 280 ====================== =================================================== 281 Argument Description 282 ====================== =================================================== 283 ``path`` Required. The absolute filesystem path to a 284 directory from which this ``FilePathField`` should 285 get its choices. Example: ``"/home/images"``. 286 287 ``match`` Optional. A regular expression, as a string, that 288 ``FilePathField`` will use to filter filenames. 289 Note that the regex will be applied to the 290 base filename, not the full path. Example: 291 ``"foo.*\.txt^"``, which will match a file called 292 ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``. 293 294 ``recursive`` Optional. Either ``True`` or ``False``. Default is 295 ``False``. Specifies whether all subdirectories of 296 ``path`` should be included. 297 ====================== =================================================== 298 299 Of course, these arguments can be used together. 300 301 The one potential gotcha is that ``match`` applies to the base filename, 302 not the full path. So, this example:: 303 304 FilePathField(path="/home/images", match="foo.*", recursive=True) 305 306 ...will match ``/home/images/foo.gif`` but not ``/home/images/foo/bar.gif`` 307 because the ``match`` applies to the base filename (``foo.gif`` and 308 ``bar.gif``). 274 309 275 310 ``FloatField`` … … 303 338 304 339 Requires the `Python Imaging Library`_. 305 340 306 341 .. _Python Imaging Library: http://www.pythonware.com/products/pil/ 307 342 … … 722 757 723 758 This is a list of lists of fields that must be unique when considered 724 together. It's used in the Django admin. 759 together. It's used in the Django admin and is enforced at the database 760 level (i.e., the appropriate ``UNIQUE`` statements are included in the 761 ``CREATE TABLE`` statement). 725 762 726 763 ``verbose_name`` django/branches/new-admin/docs/modpython.txt
r642
