Fixed #7830 -- Removed all of the remaining, deprecated, non-oldforms features:
* Support for representing files as strings was removed. Use `django.core.files.base.ContentFile` instead. * Support for representing uploaded files as dictionaries was removed. Use `django.core.files.uploadedfile.SimpleUploadedFile` instead. * The `filename`, `file_name`, `file_size`, and `chuck` properties of `UploadedFile` were removed. Use the `name`, `name`, `size`, and `chunks` properties instead, respectively. * The `get_FIELD_filename`, `get_FIELD_url`, `get_FIELD_size`, and `save_FIELD_file` methods for Models with `FileField` fields were removed. Instead, use the `path`, `url`, and `size` attributes and `save` method on the field itself, respectively. * The `get_FIELD_width` and `get_FIELD_height` methods for Models with `ImageField` fields were removed. Use the `width` and `height` attributes on the field itself instead. * The dispatcher `connect`, `disconnect`, `send`, and `sendExact` functions were removed. Use the signal object's own `connect`, `disconnect`, `send`, and `send` methods instead, respectively. * The `form_for_model` and `form_for_instance` functions were removed. Use a `ModelForm` subclass instead. * Support for importing `django.newforms` was removed. Use `django.forms` instead. * Support for importing `django.utils.images` was removed. Use `django.core.files.images` instead. * Support for the `follow` argument in the `create_object` and `update_object` generic views was removed. Use the `django.forms` package and the new `form_class` argument instead. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8291 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
94e8f4fb35
commit
ef48a3e69c
|
@ -36,19 +36,6 @@ class Storage(object):
|
|||
Saves new content to the file specified by name. The content should be a
|
||||
proper File object, ready to be read from the beginning.
|
||||
"""
|
||||
# Check for old-style usage. Warn here first since there are multiple
|
||||
# locations where we need to support both new and old usage.
|
||||
if isinstance(content, basestring):
|
||||
import warnings
|
||||
warnings.warn(
|
||||
message = "Representing files as strings is deprecated." \
|
||||
"Use django.core.files.base.ContentFile instead.",
|
||||
category = DeprecationWarning,
|
||||
stacklevel = 2
|
||||
)
|
||||
from django.core.files.base import ContentFile
|
||||
content = ContentFile(content)
|
||||
|
||||
# Get the proper name for the file, as it will actually be saved.
|
||||
if name is None:
|
||||
name = content.name
|
||||
|
|
|
@ -3,7 +3,6 @@ Classes representing uploaded files.
|
|||
"""
|
||||
|
||||
import os
|
||||
import warnings
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
|
@ -11,34 +10,10 @@ except ImportError:
|
|||
|
||||
from django.conf import settings
|
||||
from django.core.files.base import File
|
||||
|
||||
from django.core.files import temp as tempfile
|
||||
|
||||
__all__ = ('UploadedFile', 'TemporaryUploadedFile', 'InMemoryUploadedFile', 'SimpleUploadedFile')
|
||||
|
||||
# Because we fooled around with it a bunch, UploadedFile has a bunch
|
||||
# of deprecated properties. This little shortcut helps define 'em
|
||||
# without too much code duplication.
|
||||
def deprecated_property(old, new, readonly=False):
|
||||
def issue_warning():
|
||||
warnings.warn(
|
||||
message = "UploadedFile.%s is deprecated; use UploadedFile.%s instead." % (old, new),
|
||||
category = DeprecationWarning,
|
||||
stacklevel = 3
|
||||
)
|
||||
|
||||
def getter(self):
|
||||
issue_warning()
|
||||
return getattr(self, new)
|
||||
|
||||
def setter(self, value):
|
||||
issue_warning()
|
||||
setattr(self, new, value)
|
||||
|
||||
if readonly:
|
||||
return property(getter)
|
||||
else:
|
||||
return property(getter, setter)
|
||||
__all__ = ('UploadedFile', 'TemporaryUploadedFile', 'InMemoryUploadedFile',
|
||||
'SimpleUploadedFile')
|
||||
|
||||
class UploadedFile(File):
|
||||
"""
|
||||
|
@ -77,21 +52,6 @@ class UploadedFile(File):
|
|||
|
||||
name = property(_get_name, _set_name)
|
||||
|
||||
# Deprecated properties
|
||||
filename = deprecated_property(old="filename", new="name")
|
||||
file_name = deprecated_property(old="file_name", new="name")
|
||||
file_size = deprecated_property(old="file_size", new="size")
|
||||
chunk = deprecated_property(old="chunk", new="chunks", readonly=True)
|
||||
|
||||
def _get_data(self):
|
||||
warnings.warn(
|
||||
message = "UploadedFile.data is deprecated; use UploadedFile.read() instead.",
|
||||
category = DeprecationWarning,
|
||||
stacklevel = 2
|
||||
)
|
||||
return self.read()
|
||||
data = property(_get_data)
|
||||
|
||||
# Abstract methods; subclasses *must* define read() and probably should
|
||||
# define open/close.
|
||||
def read(self, num_bytes=None):
|
||||
|
@ -103,27 +63,6 @@ class UploadedFile(File):
|
|||
def close(self):
|
||||
pass
|
||||
|
||||
# Backwards-compatible support for uploaded-files-as-dictionaries.
|
||||
def __getitem__(self, key):
|
||||
warnings.warn(
|
||||
message = "The dictionary access of uploaded file objects is deprecated. Use the new object interface instead.",
|
||||
category = DeprecationWarning,
|
||||
stacklevel = 2
|
||||
)
|
||||
backwards_translate = {
|
||||
'filename': 'name',
|
||||
'content-type': 'content_type',
|
||||
}
|
||||
|
||||
if key == 'content':
|
||||
return self.read()
|
||||
elif key == 'filename':
|
||||
return self.name
|
||||
elif key == 'content-type':
|
||||
return self.content_type
|
||||
else:
|
||||
return getattr(self, key)
|
||||
|
||||
class TemporaryUploadedFile(UploadedFile):
|
||||
"""
|
||||
A file uploaded to a temporary location (i.e. stream-to-disk).
|
||||
|
|
|
@ -3,7 +3,6 @@ import types
|
|||
import sys
|
||||
import os
|
||||
from itertools import izip
|
||||
from warnings import warn
|
||||
try:
|
||||
set
|
||||
except NameError:
|
||||
|
@ -477,43 +476,6 @@ class Model(object):
|
|||
setattr(self, cachename, obj)
|
||||
return getattr(self, cachename)
|
||||
|
||||
def _get_FIELD_filename(self, field):
|
||||
warn("instance.get_%s_filename() is deprecated. Use instance.%s.path instead." % \
|
||||
(field.attname, field.attname), DeprecationWarning, stacklevel=3)
|
||||
try:
|
||||
return getattr(self, field.attname).path
|
||||
except ValueError:
|
||||
return ''
|
||||
|
||||
def _get_FIELD_url(self, field):
|
||||
warn("instance.get_%s_url() is deprecated. Use instance.%s.url instead." % \
|
||||
(field.attname, field.attname), DeprecationWarning, stacklevel=3)
|
||||
try:
|
||||
return getattr(self, field.attname).url
|
||||
except ValueError:
|
||||
return ''
|
||||
|
||||
def _get_FIELD_size(self, field):
|
||||
warn("instance.get_%s_size() is deprecated. Use instance.%s.size instead." % \
|
||||
(field.attname, field.attname), DeprecationWarning, stacklevel=3)
|
||||
return getattr(self, field.attname).size
|
||||
|
||||
def _save_FIELD_file(self, field, filename, content, save=True):
|
||||
warn("instance.save_%s_file() is deprecated. Use instance.%s.save() instead." % \
|
||||
(field.attname, field.attname), DeprecationWarning, stacklevel=3)
|
||||
return getattr(self, field.attname).save(filename, content, save)
|
||||
|
||||
_save_FIELD_file.alters_data = True
|
||||
|
||||
def _get_FIELD_width(self, field):
|
||||
warn("instance.get_%s_width() is deprecated. Use instance.%s.width instead." % \
|
||||
(field.attname, field.attname), DeprecationWarning, stacklevel=3)
|
||||
return getattr(self, field.attname).width()
|
||||
|
||||
def _get_FIELD_height(self, field):
|
||||
warn("instance.get_%s_height() is deprecated. Use instance.%s.height instead." % \
|
||||
(field.attname, field.attname), DeprecationWarning, stacklevel=3)
|
||||
return getattr(self, field.attname).height()
|
||||
|
||||
|
||||
############################################
|
||||
|
|
|
@ -192,10 +192,6 @@ class FileField(Field):
|
|||
def contribute_to_class(self, cls, name):
|
||||
super(FileField, self).contribute_to_class(cls, name)
|
||||
setattr(cls, self.name, FileDescriptor(self))
|
||||
setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self))
|
||||
setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))
|
||||
setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))
|
||||
setattr(cls, 'save_%s_file' % self.name, lambda instance, name, content, save=True: instance._save_FIELD_file(self, name, content, save))
|
||||
signals.post_delete.connect(self.delete_file, sender=cls)
|
||||
|
||||
def delete_file(self, instance, sender, **kwargs):
|
||||
|
@ -262,17 +258,6 @@ class FileField(Field):
|
|||
|
||||
class ImageFieldFile(ImageFile, FieldFile):
|
||||
def save(self, name, content, save=True):
|
||||
|
||||
if not hasattr(content, 'read'):
|
||||
import warnings
|
||||
warnings.warn(
|
||||
message = "Representing files as strings is deprecated." \
|
||||
"Use django.core.files.base.ContentFile instead.",
|
||||
category = DeprecationWarning,
|
||||
stacklevel = 2
|
||||
)
|
||||
content = ContentFile(content)
|
||||
|
||||
# Repopulate the image dimension cache.
|
||||
self._dimensions_cache = get_image_dimensions(content)
|
||||
|
||||
|
@ -300,15 +285,6 @@ class ImageField(FileField):
|
|||
def get_manipulator_field_objs(self):
|
||||
return [oldforms.ImageUploadField, oldforms.HiddenField]
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
super(ImageField, self).contribute_to_class(cls, name)
|
||||
# Add get_BLAH_width and get_BLAH_height methods, but only if the
|
||||
# image field doesn't have width and height cache fields.
|
||||
if not self.width_field:
|
||||
setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self))
|
||||
if not self.height_field:
|
||||
setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {'form_class': forms.ImageField}
|
||||
defaults.update(kwargs)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import weakref
|
||||
import warnings
|
||||
try:
|
||||
set
|
||||
except NameError:
|
||||
|
@ -197,47 +196,3 @@ class Signal(object):
|
|||
for idx, (r_key, _) in enumerate(self.receivers):
|
||||
if r_key == key:
|
||||
del self.receivers[idx]
|
||||
|
||||
def connect(receiver, signal, sender=None, weak=True):
|
||||
"""
|
||||
For backward compatibility only. See Signal.connect()
|
||||
"""
|
||||
warnings.warn(
|
||||
category = DeprecationWarning,
|
||||
message = "dispatcher.connect() is deprecated; use Signal.connect() instead.",
|
||||
stacklevel = 2
|
||||
)
|
||||
return signal.connect(receiver, sender, weak)
|
||||
|
||||
def disconnect(receiver, signal, sender=None, weak=True):
|
||||
"""
|
||||
For backward compatibility only. See Signal.disconnect()
|
||||
"""
|
||||
warnings.warn(
|
||||
category = DeprecationWarning,
|
||||
message = "dispatcher.disconnect() is deprecated; use Signal.disconnect() instead.",
|
||||
stacklevel = 2
|
||||
)
|
||||
signal.disconnect(receiver, sender, weak)
|
||||
|
||||
def send(signal, sender=None, **named):
|
||||
"""
|
||||
For backward compatibility only. See Signal.send()
|
||||
"""
|
||||
warnings.warn(
|
||||
category = DeprecationWarning,
|
||||
message = "dispatcher.send() is deprecated; use Signal.send() instead.",
|
||||
stacklevel = 2
|
||||
)
|
||||
return signal.send(sender=sender, **named)
|
||||
|
||||
def sendExact(signal, sender, **named ):
|
||||
"""
|
||||
This function is deprecated, as it now has the same meaning as send.
|
||||
"""
|
||||
warnings.warn(
|
||||
category = DeprecationWarning,
|
||||
message = "dispatcher.sendExact() is deprecated; use Signal.send() instead.",
|
||||
stacklevel = 2
|
||||
)
|
||||
return signal.send(sender=sender, **named)
|
||||
|
|
|
@ -442,16 +442,7 @@ class FileField(Field):
|
|||
elif not data and initial:
|
||||
return initial
|
||||
|
||||
if isinstance(data, dict):
|
||||
# We warn once, then support both ways below.
|
||||
import warnings
|
||||
warnings.warn(
|
||||
message = "Representing uploaded files as dictionaries is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",
|
||||
category = DeprecationWarning,
|
||||
stacklevel = 2
|
||||
)
|
||||
data = UploadedFile(data['filename'], data['content'])
|
||||
|
||||
# UploadedFile objects should have name and size attributes.
|
||||
try:
|
||||
file_name = data.name
|
||||
file_size = data.size
|
||||
|
|
|
@ -3,8 +3,6 @@ Helper functions for creating Form classes from Django models
|
|||
and database field objects.
|
||||
"""
|
||||
|
||||
from warnings import warn
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import smart_unicode
|
||||
from django.utils.datastructures import SortedDict
|
||||
|
@ -18,8 +16,8 @@ from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME
|
|||
|
||||
__all__ = (
|
||||
'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
|
||||
'save_instance', 'form_for_model', 'form_for_instance', 'form_for_fields',
|
||||
'ModelChoiceField', 'ModelMultipleChoiceField',
|
||||
'save_instance', 'form_for_fields', 'ModelChoiceField',
|
||||
'ModelMultipleChoiceField',
|
||||
)
|
||||
|
||||
def save_instance(form, instance, fields=None, fail_message='saved',
|
||||
|
@ -74,65 +72,6 @@ def make_instance_save(instance, fields, fail_message):
|
|||
return save_instance(self, instance, fields, fail_message, commit)
|
||||
return save
|
||||
|
||||
def form_for_model(model, form=BaseForm, fields=None,
|
||||
formfield_callback=lambda f: f.formfield()):
|
||||
"""
|
||||
Returns a Form class for the given Django model class.
|
||||
|
||||
Provide ``form`` if you want to use a custom BaseForm subclass.
|
||||
|
||||
Provide ``formfield_callback`` if you want to define different logic for
|
||||
determining the formfield for a given database field. It's a callable that
|
||||
takes a database Field instance and returns a form Field instance.
|
||||
"""
|
||||
warn("form_for_model is deprecated. Use ModelForm instead.",
|
||||
PendingDeprecationWarning, stacklevel=3)
|
||||
opts = model._meta
|
||||
field_list = []
|
||||
for f in opts.fields + opts.many_to_many:
|
||||
if not f.editable:
|
||||
continue
|
||||
if fields and not f.name in fields:
|
||||
continue
|
||||
formfield = formfield_callback(f)
|
||||
if formfield:
|
||||
field_list.append((f.name, formfield))
|
||||
base_fields = SortedDict(field_list)
|
||||
return type(opts.object_name + 'Form', (form,),
|
||||
{'base_fields': base_fields, '_model': model,
|
||||
'save': make_model_save(model, fields, 'created')})
|
||||
|
||||
def form_for_instance(instance, form=BaseForm, fields=None,
|
||||
formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
|
||||
"""
|
||||
Returns a Form class for the given Django model instance.
|
||||
|
||||
Provide ``form`` if you want to use a custom BaseForm subclass.
|
||||
|
||||
Provide ``formfield_callback`` if you want to define different logic for
|
||||
determining the formfield for a given database field. It's a callable that
|
||||
takes a database Field instance, plus **kwargs, and returns a form Field
|
||||
instance with the given kwargs (i.e. 'initial').
|
||||
"""
|
||||
warn("form_for_instance is deprecated. Use ModelForm instead.",
|
||||
PendingDeprecationWarning, stacklevel=3)
|
||||
model = instance.__class__
|
||||
opts = model._meta
|
||||
field_list = []
|
||||
for f in opts.fields + opts.many_to_many:
|
||||
if not f.editable:
|
||||
continue
|
||||
if fields and not f.name in fields:
|
||||
continue
|
||||
current_value = f.value_from_object(instance)
|
||||
formfield = formfield_callback(f, initial=current_value)
|
||||
if formfield:
|
||||
field_list.append((f.name, formfield))
|
||||
base_fields = SortedDict(field_list)
|
||||
return type(opts.object_name + 'InstanceForm', (form,),
|
||||
{'base_fields': base_fields, '_model': model,
|
||||
'save': make_instance_save(instance, fields, 'changed')})
|
||||
|
||||
def form_for_fields(field_list):
|
||||
"""
|
||||
Returns a Form class for the given list of Django database field instances.
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
import warnings
|
||||
warnings.warn(
|
||||
category = DeprecationWarning,
|
||||
message = "django.newforms is no longer new. Import django.forms instead.",
|
||||
stacklevel = 2
|
||||
)
|
||||
from django.forms import *
|
|
@ -1,5 +0,0 @@
|
|||
import warnings
|
||||
|
||||
from django.core.files.images import get_image_dimensions
|
||||
|
||||
warnings.warn("django.utils.images has been moved to django.core.files.images.", DeprecationWarning)
|
|
@ -7,19 +7,6 @@ from django.utils.translation import ugettext
|
|||
from django.contrib.auth.views import redirect_to_login
|
||||
from django.views.generic import GenericViewError
|
||||
|
||||
def deprecate_follow(follow):
|
||||
"""
|
||||
Issues a DeprecationWarning if follow is anything but None.
|
||||
|
||||
The old Manipulator-based forms used a follow argument that is no longer
|
||||
needed for newforms-based forms.
|
||||
"""
|
||||
if follow is not None:
|
||||
import warnings
|
||||
msg = ("Generic views have been changed to use newforms, and the"
|
||||
" 'follow' argument is no longer used. Please update your code"
|
||||
" to not use the 'follow' argument.")
|
||||
warnings.warn(msg, DeprecationWarning, stacklevel=3)
|
||||
|
||||
def apply_extra_context(extra_context, context):
|
||||
"""
|
||||
|
@ -105,8 +92,7 @@ def lookup_object(model, object_id, slug, slug_field):
|
|||
|
||||
def create_object(request, model=None, template_name=None,
|
||||
template_loader=loader, extra_context=None, post_save_redirect=None,
|
||||
login_required=False, follow=None, context_processors=None,
|
||||
form_class=None):
|
||||
login_required=False, context_processors=None, form_class=None):
|
||||
"""
|
||||
Generic object-creation function.
|
||||
|
||||
|
@ -115,7 +101,6 @@ def create_object(request, model=None, template_name=None,
|
|||
form
|
||||
the form for the object
|
||||
"""
|
||||
deprecate_follow(follow)
|
||||
if extra_context is None: extra_context = {}
|
||||
if login_required and not request.user.is_authenticated():
|
||||
return redirect_to_login(request.path)
|
||||
|
@ -143,9 +128,9 @@ def create_object(request, model=None, template_name=None,
|
|||
|
||||
def update_object(request, model=None, object_id=None, slug=None,
|
||||
slug_field='slug', template_name=None, template_loader=loader,
|
||||
extra_context=None, post_save_redirect=None,
|
||||
login_required=False, follow=None, context_processors=None,
|
||||
template_object_name='object', form_class=None):
|
||||
extra_context=None, post_save_redirect=None, login_required=False,
|
||||
context_processors=None, template_object_name='object',
|
||||
form_class=None):
|
||||
"""
|
||||
Generic object-update function.
|
||||
|
||||
|
@ -156,7 +141,6 @@ def update_object(request, model=None, object_id=None, slug=None,
|
|||
object
|
||||
the original object being edited
|
||||
"""
|
||||
deprecate_follow(follow)
|
||||
if extra_context is None: extra_context = {}
|
||||
if login_required and not request.user.is_authenticated():
|
||||
return redirect_to_login(request.path)
|
||||
|
|
|
@ -483,8 +483,7 @@ accepted lookup types to ``exact`` and ``in``::
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Returns the default form field to use when this field is displayed
|
||||
in a model. This method is called by the `helper functions`_
|
||||
``form_for_model()`` and ``form_for_instance()``.
|
||||
in a model.
|
||||
|
||||
All of the ``kwargs`` dictionary is passed directly to the form field's
|
||||
``__init__()`` method. Normally, all you need to do is set up a good default
|
||||
|
|
|
@ -2313,37 +2313,6 @@ For a full example, see the `lookup API sample model`_.
|
|||
|
||||
.. _lookup API sample model: ../models/lookup/
|
||||
|
||||
get_FOO_filename()
|
||||
------------------
|
||||
|
||||
**Deprecated in Django development version**; use ``object.FOO.name`` instead.
|
||||
See `managing files`_ for details.
|
||||
|
||||
get_FOO_url()
|
||||
-------------
|
||||
|
||||
**Deprecated in Django development version**; use ``object.FOO.url`` instead.
|
||||
See `managing files`_ for details.
|
||||
|
||||
get_FOO_size()
|
||||
--------------
|
||||
|
||||
**Deprecated in Django development version**; use ``object.FOO.size`` instead.
|
||||
See `managing files`_ for details.
|
||||
|
||||
save_FOO_file(filename, raw_contents)
|
||||
-------------------------------------
|
||||
|
||||
**Deprecated in Django development version**; use ``object.FOO.save()`` instead.
|
||||
See `managing files`_ for details.
|
||||
|
||||
get_FOO_height() and get_FOO_width()
|
||||
------------------------------------
|
||||
|
||||
**Deprecated in Django development version**; use ``object.FOO.width`` and
|
||||
``object.FOO.height`` instead. See `managing files`_ for details.
|
||||
|
||||
.. _`managing files`: ../files/
|
||||
|
||||
Shortcuts
|
||||
=========
|
||||
|
|
|
@ -1,425 +0,0 @@
|
|||
Generating forms for models
|
||||
===========================
|
||||
|
||||
.. admonition:: Note
|
||||
|
||||
The APIs described in this document have been deprecated. If you're
|
||||
developing new code, use `ModelForms`_ instead.
|
||||
|
||||
.. _ModelForms: ../modelforms/
|
||||
|
||||
If you're building a database-driven app, chances are you'll have forms that
|
||||
map closely to Django models. For instance, you might have a ``BlogComment``
|
||||
model, and you want to create a form that lets people submit comments. In this
|
||||
case, it would be redundant to define the field types in your form, because
|
||||
you've already defined the fields in your model.
|
||||
|
||||
For this reason, Django provides a few helper functions that let you create a
|
||||
``Form`` class from a Django model.
|
||||
|
||||
``form_for_model()``
|
||||
--------------------
|
||||
|
||||
The method ``django.forms.form_for_model()`` creates a form based on the
|
||||
definition of a specific model. Pass it the model class, and it will return a
|
||||
``Form`` class that contains a form field for each model field.
|
||||
|
||||
For example::
|
||||
|
||||
>>> from django.forms import form_for_model
|
||||
|
||||
# Create the form class.
|
||||
>>> ArticleForm = form_for_model(Article)
|
||||
|
||||
# Create an empty form instance.
|
||||
>>> f = ArticleForm()
|
||||
|
||||
It bears repeating that ``form_for_model()`` takes the model *class*, not a
|
||||
model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
|
||||
|
||||
Field types
|
||||
~~~~~~~~~~~
|
||||
|
||||
The generated ``Form`` class will have a form field for every model field. Each
|
||||
model field has a corresponding default form field. For example, a
|
||||
``CharField`` on a model is represented as a ``CharField`` on a form. A
|
||||
model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
|
||||
the full list of conversions:
|
||||
|
||||
=============================== ========================================
|
||||
Model field Form field
|
||||
=============================== ========================================
|
||||
``AutoField`` Not represented in the form
|
||||
``BooleanField`` ``BooleanField``
|
||||
``CharField`` ``CharField`` with ``max_length`` set to
|
||||
the model field's ``max_length``
|
||||
``CommaSeparatedIntegerField`` ``CharField``
|
||||
``DateField`` ``DateField``
|
||||
``DateTimeField`` ``DateTimeField``
|
||||
``DecimalField`` ``DecimalField``
|
||||
``EmailField`` ``EmailField``
|
||||
``FileField`` ``FileField``
|
||||
``FilePathField`` ``CharField``
|
||||
``FloatField`` ``FloatField``
|
||||
``ForeignKey`` ``ModelChoiceField`` (see below)
|
||||
``ImageField`` ``ImageField``
|
||||
``IntegerField`` ``IntegerField``
|
||||
``IPAddressField`` ``IPAddressField``
|
||||
``ManyToManyField`` ``ModelMultipleChoiceField`` (see
|
||||
below)
|
||||
``NullBooleanField`` ``CharField``
|
||||
``PhoneNumberField`` ``USPhoneNumberField``
|
||||
(from ``django.contrib.localflavor.us``)
|
||||
``PositiveIntegerField`` ``IntegerField``
|
||||
``PositiveSmallIntegerField`` ``IntegerField``
|
||||
``SlugField`` ``CharField``
|
||||
``SmallIntegerField`` ``IntegerField``
|
||||
``TextField`` ``CharField`` with ``widget=Textarea``
|
||||
``TimeField`` ``TimeField``
|
||||
``URLField`` ``URLField`` with ``verify_exists`` set
|
||||
to the model field's ``verify_exists``
|
||||
``USStateField`` ``CharField`` with
|
||||
``widget=USStateSelect``
|
||||
(``USStateSelect`` is from
|
||||
``django.contrib.localflavor.us``)
|
||||
``XMLField`` ``CharField`` with ``widget=Textarea``
|
||||
=============================== ========================================
|
||||
|
||||
|
||||
.. note::
|
||||
The ``FloatField`` form field and ``DecimalField`` model and form fields
|
||||
are new in the development version.
|
||||
|
||||
As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
|
||||
types are special cases:
|
||||
|
||||
* ``ForeignKey`` is represented by ``django.forms.ModelChoiceField``,
|
||||
which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
|
||||
|
||||
* ``ManyToManyField`` is represented by
|
||||
``django.forms.ModelMultipleChoiceField``, which is a
|
||||
``MultipleChoiceField`` whose choices are a model ``QuerySet``.
|
||||
|
||||
In addition, each generated form field has attributes set as follows:
|
||||
|
||||
* If the model field has ``blank=True``, then ``required`` is set to
|
||||
``False`` on the form field. Otherwise, ``required=True``.
|
||||
|
||||
* The form field's ``label`` is set to the ``verbose_name`` of the model
|
||||
field, with the first character capitalized.
|
||||
|
||||
* The form field's ``help_text`` is set to the ``help_text`` of the model
|
||||
field.
|
||||
|
||||
* If the model field has ``choices`` set, then the form field's ``widget``
|
||||
will be set to ``Select``, with choices coming from the model field's
|
||||
``choices``. The choices will normally include the blank choice which is
|
||||
selected by default. If the field is required, this forces the user to
|
||||
make a selection. The blank choice will not be included if the model
|
||||
field has ``blank=False`` and an explicit ``default`` value (the
|
||||
``default`` value will be initially selected instead).
|
||||
|
||||
Finally, note that you can override the form field used for a given model
|
||||
field. See "Overriding the default field types" below.
|
||||
|
||||
A full example
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Consider this set of models::
|
||||
|
||||
from django.db import models
|
||||
|
||||
TITLE_CHOICES = (
|
||||
('MR', 'Mr.'),
|
||||
('MRS', 'Mrs.'),
|
||||
('MS', 'Ms.'),
|
||||
)
|
||||
|
||||
class Author(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
title = models.CharField(max_length=3, choices=TITLE_CHOICES)
|
||||
birth_date = models.DateField(blank=True, null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Book(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
authors = models.ManyToManyField(Author)
|
||||
|
||||
With these models, a call to ``form_for_model(Author)`` would return a ``Form``
|
||||
class equivalent to this::
|
||||
|
||||
class AuthorForm(forms.Form):
|
||||
name = forms.CharField(max_length=100)
|
||||
title = forms.CharField(max_length=3,
|
||||
widget=forms.Select(choices=TITLE_CHOICES))
|
||||
birth_date = forms.DateField(required=False)
|
||||
|
||||
A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to
|
||||
this::
|
||||
|
||||
class BookForm(forms.Form):
|
||||
name = forms.CharField(max_length=100)
|
||||
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
|
||||
|
||||
The ``save()`` method
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Every form produced by ``form_for_model()`` also has a ``save()`` method. This
|
||||
method creates and saves a database object from the data bound to the form. For
|
||||
example::
|
||||
|
||||
# Create a form instance from POST data.
|
||||
>>> f = ArticleForm(request.POST)
|
||||
|
||||
# Save a new Article object from the form's data.
|
||||
>>> new_article = f.save()
|
||||
|
||||
Note that ``save()`` will raise a ``ValueError`` if the data in the form
|
||||
doesn't validate -- i.e., ``if form.errors``.
|
||||
|
||||
This ``save()`` method accepts an optional ``commit`` keyword argument, which
|
||||
accepts either ``True`` or ``False``. If you call ``save()`` with
|
||||
``commit=False``, then it will return an object that hasn't yet been saved to
|
||||
the database. In this case, it's up to you to call ``save()`` on the resulting
|
||||
model instance. This is useful if you want to do custom processing on the
|
||||
object before saving it. ``commit`` is ``True`` by default.
|
||||
|
||||
Another side effect of using ``commit=False`` is seen when your model has
|
||||
a many-to-many relation with another model. If your model has a many-to-many
|
||||
relation and you specify ``commit=False`` when you save a form, Django cannot
|
||||
immediately save the form data for the many-to-many relation. This is because
|
||||
it isn't possible to save many-to-many data for an instance until the instance
|
||||
exists in the database.
|
||||
|
||||
To work around this problem, every time you save a form using ``commit=False``,
|
||||
Django adds a ``save_m2m()`` method to the form created by ``form_for_model``.
|
||||
After you've manually saved the instance produced by the form, you can invoke
|
||||
``save_m2m()`` to save the many-to-many form data. For example::
|
||||
|
||||
# Create a form instance with POST data.
|
||||
>>> f = AuthorForm(request.POST)
|
||||
|
||||
# Create, but don't save the new author instance.
|
||||
>>> new_author = f.save(commit=False)
|
||||
|
||||
# Modify the author in some way.
|
||||
>>> new_author.some_field = 'some_value'
|
||||
|
||||
# Save the new instance.
|
||||
>>> new_author.save()
|
||||
|
||||
# Now, save the many-to-many data for the form.
|
||||
>>> f.save_m2m()
|
||||
|
||||
Calling ``save_m2m()`` is only required if you use ``save(commit=False)``.
|
||||
When you use a simple ``save()`` on a form, all data -- including
|
||||
many-to-many data -- is saved without the need for any additional method calls.
|
||||
For example::
|
||||
|
||||
# Create a form instance with POST data.
|
||||
>>> f = AuthorForm(request.POST)
|
||||
|
||||
# Create and save the new author instance. There's no need to do anything else.
|
||||
>>> new_author = f.save()
|
||||
|
||||
Using an alternate base class
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to add custom methods to the form generated by
|
||||
``form_for_model()``, write a class that extends ``django.forms.BaseForm``
|
||||
and contains your custom methods. Then, use the ``form`` argument to
|
||||
``form_for_model()`` to tell it to use your custom form as its base class.
|
||||
For example::
|
||||
|
||||
# Create the new base class.
|
||||
>>> class MyBase(BaseForm):
|
||||
... def my_method(self):
|
||||
... # Do whatever the method does
|
||||
|
||||
# Create the form class with a different base class.
|
||||
>>> ArticleForm = form_for_model(Article, form=MyBase)
|
||||
|
||||
# Instantiate the form.
|
||||
>>> f = ArticleForm()
|
||||
|
||||
# Use the base class method.
|
||||
>>> f.my_method()
|
||||
|
||||
Using a subset of fields on the form
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**New in Django development version**
|
||||
|
||||
In some cases, you may not want all the model fields to appear on the generated
|
||||
form. There are two ways of telling ``form_for_model()`` to use only a subset
|
||||
of the model fields:
|
||||
|
||||
1. Set ``editable=False`` on the model field. As a result, *any* form
|
||||
created from the model via ``form_for_model()`` will not include that
|
||||
field.
|
||||
|
||||
2. Use the ``fields`` argument to ``form_for_model()``. This argument, if
|
||||
given, should be a list of field names to include in the form.
|
||||
|
||||
For example, if you want a form for the ``Author`` model (defined above)
|
||||
that includes only the ``name`` and ``title`` fields, you would specify
|
||||
``fields`` like this::
|
||||
|
||||
PartialArticleForm = form_for_model(Author, fields=('name', 'title'))
|
||||
|
||||
.. note::
|
||||
|
||||
If you specify ``fields`` when creating a form with ``form_for_model()``,
|
||||
then the fields that are *not* specified will not be set by the form's
|
||||
``save()`` method. Django will prevent any attempt to save an incomplete
|
||||
model, so if the model does not allow the missing fields to be empty, and
|
||||
does not provide a default value for the missing fields, any attempt to
|
||||
``save()`` a ``form_for_model`` with missing fields will fail. To avoid
|
||||
this failure, you must use ``save(commit=False)`` and manually set any
|
||||
extra required fields::
|
||||
|
||||
instance = form.save(commit=False)
|
||||
instance.required_field = 'new value'
|
||||
instance.save()
|
||||
|
||||
See the `section on saving forms`_ for more details on using
|
||||
``save(commit=False)``.
|
||||
|
||||
.. _section on saving forms: `The save() method`_
|
||||
|
||||
Overriding the default field types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The default field types, as described in the "Field types" table above, are
|
||||
sensible defaults; if you have a ``DateField`` in your model, chances are you'd
|
||||
want that to be represented as a ``DateField`` in your form. But
|
||||
``form_for_model()`` gives you the flexibility of changing the form field type
|
||||
for a given model field. You do this by specifying a **formfield callback**.
|
||||
|
||||
A formfield callback is a function that, when provided with a model field,
|
||||
returns a form field instance. When constructing a form, ``form_for_model()``
|
||||
asks the formfield callback to provide form field types.
|
||||
|
||||
By default, ``form_for_model()`` calls the ``formfield()`` method on the model
|
||||
field::
|
||||
|
||||
def default_callback(field, **kwargs):
|
||||
return field.formfield(**kwargs)
|
||||
|
||||
The ``kwargs`` are any keyword arguments that might be passed to the form
|
||||
field, such as ``required=True`` or ``label='Foo'``.
|
||||
|
||||
For example, if you wanted to use ``MyDateFormField`` for any ``DateField``
|
||||
field on the model, you could define the callback::
|
||||
|
||||
>>> def my_callback(field, **kwargs):
|
||||
... if isinstance(field, models.DateField):
|
||||
... return MyDateFormField(**kwargs)
|
||||
... else:
|
||||
... return field.formfield(**kwargs)
|
||||
|
||||
>>> ArticleForm = form_for_model(Article, formfield_callback=my_callback)
|
||||
|
||||
Note that your callback needs to handle *all* possible model field types, not
|
||||
just the ones that you want to behave differently to the default. That's why
|
||||
this example has an ``else`` clause that implements the default behavior.
|
||||
|
||||
.. warning::
|
||||
The field that is passed into the ``formfield_callback`` function in
|
||||
``form_for_model()`` and ``form_for_instance`` is the field instance from
|
||||
your model's class. You **must not** alter that object at all; treat it
|
||||
as read-only!
|
||||
|
||||
If you make any alterations to that object, it will affect any future
|
||||
users of the model class, because you will have changed the field object
|
||||
used to construct the class. This is almost certainly what you don't want
|
||||
to have happen.
|
||||
|
||||
Finding the model associated with a form
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The model class that was used to construct the form is available
|
||||
using the ``_model`` property of the generated form::
|
||||
|
||||
>>> ArticleForm = form_for_model(Article)
|
||||
>>> ArticleForm._model
|
||||
<class 'myapp.models.Article'>
|
||||
|
||||
``form_for_instance()``
|
||||
-----------------------
|
||||
|
||||
``form_for_instance()`` is like ``form_for_model()``, but it takes a model
|
||||
instance instead of a model class::
|
||||
|
||||
# Create an Author.
|
||||
>>> a = Author(name='Joe Smith', title='MR', birth_date=None)
|
||||
>>> a.save()
|
||||
|
||||
# Create a form for this particular Author.
|
||||
>>> AuthorForm = form_for_instance(a)
|
||||
|
||||
# Instantiate the form.
|
||||
>>> f = AuthorForm()
|
||||
|
||||
When a form created by ``form_for_instance()`` is created, the initial data
|
||||
values for the form fields are drawn from the instance. However, this data is
|
||||
not bound to the form. You will need to bind data to the form before the form
|
||||
can be saved.
|
||||
|
||||
Unlike ``form_for_model()``, a choice field in form created by
|
||||
``form_for_instance()`` will not include the blank choice if the respective
|
||||
model field has ``blank=False``. The initial choice is drawn from the instance.
|
||||
|
||||
When you call ``save()`` on a form created by ``form_for_instance()``,
|
||||
the database instance will be updated. As in ``form_for_model()``, ``save()``
|
||||
will raise ``ValueError`` if the data doesn't validate.
|
||||
|
||||
``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
|
||||
arguments that behave the same way as they do for ``form_for_model()``.
|
||||
|
||||
Let's modify the earlier `contact form`_ view example a little bit. Suppose we
|
||||
have a ``Message`` model that holds each contact submission. Something like::
|
||||
|
||||
class Message(models.Model):
|
||||
subject = models.CharField(max_length=100)
|
||||
message = models.TextField()
|
||||
sender = models.EmailField()
|
||||
cc_myself = models.BooleanField(required=False)
|
||||
|
||||
You could use this model to create a form (using ``form_for_model()``). You
|
||||
could also use existing ``Message`` instances to create a form for editing
|
||||
messages. The `simple example view`_ can be changed slightly to accept the ``id`` value
|
||||
of an existing ``Message`` and present it for editing::
|
||||
|
||||
def contact_edit(request, msg_id):
|
||||
# Create the form from the message id.
|
||||
message = get_object_or_404(Message, id=msg_id)
|
||||
ContactForm = form_for_instance(message)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = ContactForm(request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return HttpResponseRedirect('/url/on_success/')
|
||||
else:
|
||||
form = ContactForm()
|
||||
return render_to_response('contact.html', {'form': form})
|
||||
|
||||
Aside from how we create the ``ContactForm`` class here, the main point to
|
||||
note is that the form display in the ``GET`` branch of the function
|
||||
will use the values from the ``message`` instance as initial values for the
|
||||
form field.
|
||||
|
||||
.. _contact form: ../forms/#simple-view-example
|
||||
.. _`simple example view`: ../forms/#simple-view-example
|
||||
|
||||
When should you use ``form_for_model()`` and ``form_for_instance()``?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be
|
||||
shortcuts for the common case. If you want to create a form whose fields map to
|
||||
more than one model, or a form that contains fields that *aren't* on a model,
|
||||
you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way
|
||||
isn't that difficult, after all.
|
|
@ -1828,11 +1828,7 @@ Generating forms for models
|
|||
The prefered way of generating forms that work with models is explained in the
|
||||
`ModelForms documentation`_.
|
||||
|
||||
Looking for the ``form_for_model`` and ``form_for_instance`` documentation?
|
||||
They've been deprecated, but you can still `view the documentation`_.
|
||||
|
||||
.. _ModelForms documentation: ../modelforms/
|
||||
.. _view the documentation: ../form_for_model/
|
||||
|
||||
Media
|
||||
=====
|
||||
|
|
|
@ -308,12 +308,11 @@ For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and
|
|||
upload a file on Jan. 15, 2007, it will be saved in the directory
|
||||
``/home/media/photos/2007/01/15``.
|
||||
|
||||
If you want to retrieve the upload file's on-disk filename, or a URL that
|
||||
refers to that file, or the file's size, you can use the
|
||||
``get_FOO_filename()``, ``get_FOO_url()`` and ``get_FOO_size()`` methods.
|
||||
They are all documented here__.
|
||||
Information about the uploaded ``File`` object, such as its on-disk filename,
|
||||
its size, or its URL, is available via attributes on the object itself. See the
|
||||
`managing files`__ documentation for more information about ``File`` objects.
|
||||
|
||||
__ ../db-api/#get-foo-filename
|
||||
__ ../files/
|
||||
|
||||
Note that whenever you deal with uploaded files, you should pay close attention
|
||||
to where you're uploading them and what type of files they are, to avoid
|
||||
|
@ -392,19 +391,17 @@ image. Has two extra optional arguments, ``height_field`` and
|
|||
``width_field``, which, if set, will be auto-populated with the height and
|
||||
width of the image each time a model instance is saved.
|
||||
|
||||
In addition to the special ``get_FOO_*`` methods that are available for
|
||||
``FileField``, an ``ImageField`` also has ``get_FOO_height()`` and
|
||||
``get_FOO_width()`` methods. These are documented elsewhere_.
|
||||
In addition to the `standard attributes and methods`_ that are available for
|
||||
``FileField``, an ``ImageField`` also has ``width`` and ``height`` attributes.
|
||||
|
||||
Requires the `Python Imaging Library`_.
|
||||
|
||||
.. _Python Imaging Library: http://www.pythonware.com/products/pil/
|
||||
.. _elsewhere: ../db-api/#get-foo-height-and-get-foo-width
|
||||
|
||||
**New in development version:** By default, ``ImageField`` instances are
|
||||
created as ``varchar(100)`` columns in your database. As with other fields, you
|
||||
can change the maximum length using the ``max_length`` argument.
|
||||
|
||||
.. _standard attributes and methods: ../files/#file-attributes-and-methods
|
||||
.. _Python Imaging Library: http://www.pythonware.com/products/pil/
|
||||
|
||||
``IntegerField``
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -363,9 +363,8 @@ from the form can't provide a value for that field!
|
|||
<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
|
||||
<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
|
||||
|
||||
Use form_for_instance to create a Form from a model instance. The difference
|
||||
between this Form and one created via form_for_model is that the object's
|
||||
current values are inserted as 'initial' data in each Field.
|
||||
When the ModelForm is passed an instance, that instance's current values are
|
||||
inserted as 'initial' data in each Field.
|
||||
>>> w = Writer.objects.get(name='Mike Royko')
|
||||
>>> class RoykoForm(ModelForm):
|
||||
... class Meta:
|
||||
|
|
|
@ -25,7 +25,7 @@ class FileForm(django_forms.Form):
|
|||
file1 = django_forms.FileField()
|
||||
|
||||
__test__ = {'API_TESTS': """
|
||||
>>> from django.forms import form_for_model, form_for_instance
|
||||
>>> from django.forms.models import ModelForm
|
||||
>>> from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
|
||||
# FileModel with unicode filename and data #########################
|
||||
|
@ -37,7 +37,9 @@ True
|
|||
>>> m = FileModel.objects.create(file=f.cleaned_data['file1'])
|
||||
|
||||
# Boundary conditions on a PostitiveIntegerField #########################
|
||||
>>> BoundaryForm = form_for_model(BoundaryModel)
|
||||
>>> class BoundaryForm(ModelForm):
|
||||
... class Meta:
|
||||
... model = BoundaryModel
|
||||
>>> f = BoundaryForm({'positive_integer': 100})
|
||||
>>> f.is_valid()
|
||||
True
|
||||
|
@ -51,7 +53,9 @@ False
|
|||
# Formfield initial values ########
|
||||
If the model has default values for some fields, they are used as the formfield
|
||||
initial values.
|
||||
>>> DefaultsForm = form_for_model(Defaults)
|
||||
>>> class DefaultsForm(ModelForm):
|
||||
... class Meta:
|
||||
... model = Defaults
|
||||
>>> DefaultsForm().fields['name'].initial
|
||||
u'class default value'
|
||||
>>> DefaultsForm().fields['def_date'].initial
|
||||
|
@ -59,14 +63,14 @@ datetime.date(1980, 1, 1)
|
|||
>>> DefaultsForm().fields['value'].initial
|
||||
42
|
||||
|
||||
In form_for_instance(), the initial values come from the instance's values, not
|
||||
the model's defaults.
|
||||
In a ModelForm that is passed an instance, the initial values come from the
|
||||
instance's values, not the model's defaults.
|
||||
>>> foo_instance = Defaults(name=u'instance value', def_date=datetime.date(1969, 4, 4), value=12)
|
||||
>>> InstanceForm = form_for_instance(foo_instance)
|
||||
>>> InstanceForm().fields['name'].initial
|
||||
>>> instance_form = DefaultsForm(instance=foo_instance)
|
||||
>>> instance_form.initial['name']
|
||||
u'instance value'
|
||||
>>> InstanceForm().fields['def_date'].initial
|
||||
>>> instance_form.initial['def_date']
|
||||
datetime.date(1969, 4, 4)
|
||||
>>> InstanceForm().fields['value'].initial
|
||||
>>> instance_form.initial['value']
|
||||
12
|
||||
"""}
|
||||
|
|
Loading…
Reference in New Issue