Author: adrian
Date: 2007-01-25 12:05:10 -0600 (Thu, 25 Jan 2007)
New Revision: 4430
Modified:
django/branches/newforms-admin/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
django/branches/newforms-admin/django/contrib/admin/options.py
django/branches/newforms-admin/django/contrib/admin/widgets.py
django/branches/newforms-admin/django/contrib/comments/models.py
django/branches/newforms-admin/django/db/models/fields/generic.py
django/branches/newforms-admin/django/db/models/fields/related.py
django/branches/newforms-admin/django/db/models/manipulators.py
Log:
newforms-admin: Backwards-incompatible change: Refactored raw_id_admin. It is
no longer a valid attribute for fields. Instead, specify 'raw_id_fields', a
list of field names, in the 'class Admin'. Also removed raw_id functionality
for ManyToManyFields, as it was hackish.
Modified:
django/branches/newforms-admin/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
===================================================================
---
django/branches/newforms-admin/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
2007-01-25 13:47:55 UTC (rev 4429)
+++
django/branches/newforms-admin/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
2007-01-25 18:05:10 UTC (rev 4430)
@@ -1,4 +1,4 @@
-// Handles related-objects functionality: lookup link for raw_id_admin=True
+// Handles related-objects functionality: lookup link for raw_id_fields
// and Add Another links.
function showRelatedObjectLookupPopup(triggeringLink) {
Modified: django/branches/newforms-admin/django/contrib/admin/options.py
===================================================================
--- django/branches/newforms-admin/django/contrib/admin/options.py
2007-01-25 13:47:55 UTC (rev 4429)
+++ django/branches/newforms-admin/django/contrib/admin/options.py
2007-01-25 18:05:10 UTC (rev 4430)
@@ -108,6 +108,7 @@
ordering = None
js = None
fields = None
+ raw_id_fields = ()
def __init__(self, model):
self.model = model
@@ -224,12 +225,16 @@
return db_field.formfield(**kwargs)
# For ForeignKey or ManyToManyFields, use a special widget.
- if db_field.rel and isinstance(db_field.rel, (models.ManyToOneRel,
models.ManyToManyRel)):
- # Wrap the widget's render() method with a method that adds
- # extra HTML to the end of the rendered output.
- formfield = db_field.formfield(**kwargs)
- formfield.widget.render =
widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel)
- return formfield
+ if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
+ if isinstance(db_field, models.ForeignKey) and db_field.name in
self.raw_id_fields:
+ kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
+ return db_field.formfield(**kwargs)
+ else:
+ # Wrap the widget's render() method with a method that adds
+ # extra HTML to the end of the rendered output.
+ formfield = db_field.formfield(**kwargs)
+ formfield.widget.render =
widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel)
+ return formfield
# For any other type of field, just call its formfield() method.
return db_field.formfield(**kwargs)
Modified: django/branches/newforms-admin/django/contrib/admin/widgets.py
===================================================================
--- django/branches/newforms-admin/django/contrib/admin/widgets.py
2007-01-25 13:47:55 UTC (rev 4429)
+++ django/branches/newforms-admin/django/contrib/admin/widgets.py
2007-01-25 18:05:10 UTC (rev 4430)
@@ -3,6 +3,8 @@
"""
from django import newforms as forms
+from django.newforms.util import smart_unicode
+from django.utils.text import capfirst
class FilteredSelectMultiple(forms.SelectMultiple):
"""
@@ -41,6 +43,33 @@
return u'<p class="datetime">%s %s<br />%s %s</p>' % \
(_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1])
+class ForeignKeyRawIdWidget(forms.TextInput):
+ """
+ A Widget for displaying ForeignKeys in the "raw_id" interface rather than
+ in a <select> box.
+ """
+ def __init__(self, rel, attrs=None):
+ self.rel = rel
+ super(ForeignKeyRawIdWidget, self).__init__(attrs)
+
+ def render(self, name, value, attrs=None):
+ from django.conf import settings
+ related_url = '../../../%s/%s/' % (self.rel.to._meta.app_label,
self.rel.to._meta.object_name.lower())
+ if self.rel.limit_choices_to:
+ url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in
self.rel.limit_choices_to.items()])
+ else:
+ url = ''
+ attrs['class'] = 'vRawIdAdminField' # The JavaScript looks for this
hook.
+ output = [super(ForeignKeyRawIdWidget, self).render(name, value,
attrs)]
+ # TODO: "id_" is hard-coded here. This should instead use the correct
+ # API to determine the ID dynamically.
+ output.append('<a href="%s%s" class="related-lookup" id="lookup_id_%s"
onclick="return showRelatedObjectLookupPopup(this);"> ' % \
+ (related_url, url, name))
+ output.append('<img src="%simg/admin/selector-search.gif" width="16"
height="16" alt="Lookup"></a>' % settings.ADMIN_MEDIA_PREFIX)
+ return u''.join(output)
+ #if self.change: # TODO
+ #output.append(' <strong>TODO</strong>')
+
class RelatedFieldWidgetWrapper(object):
"""
This class is a wrapper whose __call__() method mimics the interface of a
@@ -54,21 +83,9 @@
rel_to = self.rel.to
related_url = '../../../%s/%s/' % (rel_to._meta.app_label,
rel_to._meta.object_name.lower())
output = [self.render_func(name, value, *args, **kwargs)]
- if self.rel.raw_id_admin:
- if self.rel.limit_choices_to:
- url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in
self.rel.limit_choices_to.items()])
- else:
- url = ''
+ if rel_to._meta.admin: # If the related object has an admin interface:
# TODO: "id_" is hard-coded here. This should instead use the
correct
# API to determine the ID dynamically.
- output.append('<a href="%s%s" class="related-lookup"
id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> ' % \
- (related_url, url, name))
- output.append('<img src="%simg/admin/selector-search.gif"
width="16" height="16" alt="Lookup"></a>' % settings.ADMIN_MEDIA_PREFIX)
- #if self.change: # TODO
- #output.append(' <strong>TODO</strong>')
- elif rel_to._meta.admin: # If the related object has an admin
interface:
- # TODO: "id_" is hard-coded here. This should instead use the
correct
- # API to determine the ID dynamically.
output.append(u'<a href="%sadd/" class="add-another"
id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' % \
(related_url, name))
output.append(u'<img src="%simg/admin/icon_addlink.gif" width="10"
height="10" alt="Add Another"/></a>' % settings.ADMIN_MEDIA_PREFIX)
Modified: django/branches/newforms-admin/django/contrib/comments/models.py
===================================================================
--- django/branches/newforms-admin/django/contrib/comments/models.py
2007-01-25 13:47:55 UTC (rev 4429)
+++ django/branches/newforms-admin/django/contrib/comments/models.py
2007-01-25 18:05:10 UTC (rev 4430)
@@ -62,7 +62,7 @@
return False
class Comment(models.Model):
- user = models.ForeignKey(User, raw_id_admin=True)
+ user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.IntegerField(_('object ID'))
headline = models.CharField(_('headline'), maxlength=255, blank=True)
@@ -101,6 +101,7 @@
list_filter = ('submit_date',)
date_hierarchy = 'submit_date'
search_fields = ('comment', 'user__username')
+ raw_id_fields = ('user',)
def __repr__(self):
return "%s: %s..." % (self.user.username, self.comment[:100])
Modified: django/branches/newforms-admin/django/db/models/fields/generic.py
===================================================================
--- django/branches/newforms-admin/django/db/models/fields/generic.py
2007-01-25 13:47:55 UTC (rev 4429)
+++ django/branches/newforms-admin/django/db/models/fields/generic.py
2007-01-25 18:05:10 UTC (rev 4430)
@@ -16,18 +16,18 @@
Provides a generic relation to any object through content-type/object-id
fields.
"""
-
+
def __init__(self, ct_field="content_type", fk_field="object_id"):
self.ct_field = ct_field
self.fk_field = fk_field
-
+
def contribute_to_class(self, cls, name):
- # Make sure the fields exist (these raise FieldDoesNotExist,
+ # Make sure the fields exist (these raise FieldDoesNotExist,
# which is a fine error to raise here)
self.name = name
self.model = cls
self.cache_attr = "_%s_cache" % name
-
+
# For some reason I don't totally understand, using weakrefs here
doesn't work.
dispatcher.connect(self.instance_pre_init, signal=signals.pre_init,
sender=cls, weak=False)
@@ -35,18 +35,18 @@
setattr(cls, name, self)
def instance_pre_init(self, signal, sender, args, kwargs):
- # Handle initalizing an object with the generic FK instaed of
- # content-type/object-id fields.
+ # Handle initalizing an object with the generic FK instaed of
+ # content-type/object-id fields.
if kwargs.has_key(self.name):
value = kwargs.pop(self.name)
kwargs[self.ct_field] = self.get_content_type(value)
kwargs[self.fk_field] = value._get_pk_val()
-
+
def get_content_type(self, obj):
# Convenience function using get_model avoids a circular import when
using this model
ContentType = get_model("contenttypes", "contenttype")
return ContentType.objects.get_for_model(obj)
-
+
def __get__(self, instance, instance_type=None):
if instance is None:
raise AttributeError, "%s must be accessed via instance" %
self.name
@@ -77,21 +77,21 @@
setattr(instance, self.ct_field, ct)
setattr(instance, self.fk_field, fk)
setattr(instance, self.cache_attr, value)
-
+
class GenericRelation(RelatedField, Field):
"""Provides an accessor to generic related objects (i.e. comments)"""
def __init__(self, to, **kwargs):
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
- kwargs['rel'] = GenericRel(to,
+ kwargs['rel'] = GenericRel(to,
related_name=kwargs.pop('related_name', None),
limit_choices_to=kwargs.pop('limit_choices_to',
None),
symmetrical=kwargs.pop('symmetrical', True))
-
+
# Override content-type/object-id field names on the related class
self.object_id_field_name = kwargs.pop("object_id_field", "object_id")
- self.content_type_field_name = kwargs.pop("content_type_field",
"content_type")
-
+ self.content_type_field_name = kwargs.pop("content_type_field",
"content_type")
+
kwargs['blank'] = True
kwargs['editable'] = False
Field.__init__(self, **kwargs)
@@ -115,7 +115,7 @@
def m2m_column_name(self):
return self.object_id_field_name
-
+
def m2m_reverse_name(self):
return self.object_id_field_name
@@ -130,13 +130,13 @@
def contribute_to_related_class(self, cls, related):
pass
-
+
def set_attributes_from_rel(self):
pass
def get_internal_type(self):
return "ManyToManyField"
-
+
class ReverseGenericRelatedObjectsDescriptor(object):
"""
This class provides the functionality that makes the related-object
@@ -190,12 +190,12 @@
Factory function for a manager that subclasses 'superclass' (which is a
Manager) and adds behavior for generic related objects.
"""
-
+
class GenericRelatedObjectManager(superclass):
def __init__(self, model=None, core_filters=None, instance=None,
symmetrical=None,
join_table=None, source_col_name=None,
target_col_name=None, content_type=None,
content_type_field_name=None, object_id_field_name=None):
-
+
super(GenericRelatedObjectManager, self).__init__()
self.core_filters = core_filters or {}
self.model = model
@@ -209,10 +209,10 @@
self.content_type_field_name = content_type_field_name
self.object_id_field_name = object_id_field_name
self.pk_val = self.instance._get_pk_val()
-
+
def get_query_set(self):
query = {
- '%s__pk' % self.content_type_field_name :
self.content_type.id,
+ '%s__pk' % self.content_type_field_name : self.content_type.id,
'%s__exact' % self.object_id_field_name : self.pk_val,
}
return superclass.get_query_set(self).filter(**query)
@@ -252,8 +252,5 @@
self.filter_interface = None
self.limit_choices_to = limit_choices_to or {}
self.edit_inline = False
- self.raw_id_admin = False
self.symmetrical = symmetrical
self.multiple = True
- assert not (self.raw_id_admin and self.filter_interface), \
- "Generic relations may not use both raw_id_admin and
filter_interface"
Modified: django/branches/newforms-admin/django/db/models/fields/related.py
===================================================================
--- django/branches/newforms-admin/django/db/models/fields/related.py
2007-01-25 13:47:55 UTC (rev 4429)
+++ django/branches/newforms-admin/django/db/models/fields/related.py
2007-01-25 18:05:10 UTC (rev 4430)
@@ -483,8 +483,7 @@
edit_inline=kwargs.pop('edit_inline', False),
related_name=kwargs.pop('related_name', None),
limit_choices_to=kwargs.pop('limit_choices_to', None),
- lookup_overrides=kwargs.pop('lookup_overrides', None),
- raw_id_admin=kwargs.pop('raw_id_admin', False))
+ lookup_overrides=kwargs.pop('lookup_overrides', None))
Field.__init__(self, **kwargs)
self.db_index = True
@@ -497,27 +496,20 @@
def prepare_field_objs_and_params(self, manipulator, name_prefix):
params = {'validator_list': self.validator_list[:], 'member_name':
name_prefix + self.attname}
- if self.rel.raw_id_admin:
- field_objs = self.get_manipulator_field_objs()
- params['validator_list'].append(curry(manipulator_valid_rel_key,
self, manipulator))
+ if self.radio_admin:
+ field_objs = [oldforms.RadioSelectField]
+ params['ul_class'] = get_ul_class(self.radio_admin)
else:
- if self.radio_admin:
- field_objs = [oldforms.RadioSelectField]
- params['ul_class'] = get_ul_class(self.radio_admin)
+ if self.null:
+ field_objs = [oldforms.NullSelectField]
else:
- if self.null:
- field_objs = [oldforms.NullSelectField]
- else:
- field_objs = [oldforms.SelectField]
- params['choices'] = self.get_choices_default()
+ field_objs = [oldforms.SelectField]
+ params['choices'] = self.get_choices_default()
return field_objs, params
def get_manipulator_field_objs(self):
rel_field = self.rel.get_related_field()
- if self.rel.raw_id_admin and not isinstance(rel_field, AutoField):
- return rel_field.get_manipulator_field_objs()
- else:
- return [oldforms.IntegerField]
+ return [oldforms.IntegerField]
def get_db_prep_save(self, value):
if value == '' or value == None:
@@ -533,7 +525,7 @@
# is *2*, not 1, because SelectFields always have an initial
# "blank" value. Otherwise (radio_admin=True), we check that the
# length is 1.
- if not self.blank and (not self.rel.raw_id_admin or self.choices):
+ if not self.blank and self.choices:
choice_list = self.get_choices_default()
if self.radio_admin and len(choice_list) == 1:
return {self.attname: choice_list[0][0]}
@@ -573,8 +565,7 @@
edit_inline=kwargs.pop('edit_inline', False),
related_name=kwargs.pop('related_name', None),
limit_choices_to=kwargs.pop('limit_choices_to', None),
- lookup_overrides=kwargs.pop('lookup_overrides', None),
- raw_id_admin=kwargs.pop('raw_id_admin', False))
+ lookup_overrides=kwargs.pop('lookup_overrides', None))
kwargs['primary_key'] = True
IntegerField.__init__(self, **kwargs)
@@ -590,19 +581,15 @@
# ManyToManyField. This works for now.
def prepare_field_objs_and_params(self, manipulator, name_prefix):
params = {'validator_list': self.validator_list[:], 'member_name':
name_prefix + self.attname}
- if self.rel.raw_id_admin:
- field_objs = self.get_manipulator_field_objs()
- params['validator_list'].append(curry(manipulator_valid_rel_key,
self, manipulator))
+ if self.radio_admin:
+ field_objs = [oldforms.RadioSelectField]
+ params['ul_class'] = get_ul_class(self.radio_admin)
else:
- if self.radio_admin:
- field_objs = [oldforms.RadioSelectField]
- params['ul_class'] = get_ul_class(self.radio_admin)
+ if self.null:
+ field_objs = [oldforms.NullSelectField]
else:
- if self.null:
- field_objs = [oldforms.NullSelectField]
- else:
- field_objs = [oldforms.SelectField]
- params['choices'] = self.get_choices_default()
+ field_objs = [oldforms.SelectField]
+ params['choices'] = self.get_choices_default()
return field_objs, params
def contribute_to_class(self, cls, name):
@@ -627,24 +614,15 @@
related_name=kwargs.pop('related_name', None),
filter_interface=kwargs.pop('filter_interface', None),
limit_choices_to=kwargs.pop('limit_choices_to', None),
- raw_id_admin=kwargs.pop('raw_id_admin', False),
symmetrical=kwargs.pop('symmetrical', True))
- if kwargs["rel"].raw_id_admin:
- kwargs.setdefault("validator_list", []).append(self.isValidIDList)
Field.__init__(self, **kwargs)
- if self.rel.raw_id_admin:
- msg = gettext_lazy('Separate multiple IDs with commas.')
- else:
- msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to
select more than one.')
+ msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to
select more than one.')
self.help_text = string_concat(self.help_text, ' ', msg)
def get_manipulator_field_objs(self):
- if self.rel.raw_id_admin:
- return [oldforms.RawIdAdminField]
- else:
- choices = self.get_choices_default()
- return [curry(oldforms.SelectMultipleField,
size=min(max(len(choices), 5), 15), choices=choices)]
+ choices = self.get_choices_default()
+ return [curry(oldforms.SelectMultipleField, size=min(max(len(choices),
5), 15), choices=choices)]
def get_choices_default(self):
return Field.get_choices(self, include_blank=False)
@@ -690,14 +668,11 @@
new_data = {}
if obj:
instance_ids = [instance._get_pk_val() for instance in
getattr(obj, self.name).all()]
- if self.rel.raw_id_admin:
- new_data[self.name] = ",".join([str(id) for id in
instance_ids])
- else:
- new_data[self.name] = instance_ids
+ new_data[self.name] = instance_ids
else:
# In required many-to-many fields with only one available choice,
# select that one available choice.
- if not self.blank and not self.rel.edit_inline and not
self.rel.raw_id_admin:
+ if not self.blank and not self.rel.edit_inline:
choices_list = self.get_choices_default()
if len(choices_list) == 1:
new_data[self.name] = [choices_list[0][0]]
@@ -741,7 +716,7 @@
class ManyToOneRel(object):
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,
- related_name=None, limit_choices_to=None, lookup_overrides=None,
raw_id_admin=False):
+ related_name=None, limit_choices_to=None, lookup_overrides=None):
try:
to._meta
except AttributeError: # to._meta doesn't exist, so it must be
RECURSIVE_RELATIONSHIP_CONSTANT
@@ -754,7 +729,6 @@
limit_choices_to = {}
self.limit_choices_to = limit_choices_to
self.lookup_overrides = lookup_overrides or {}
- self.raw_id_admin = raw_id_admin
self.multiple = True
def get_related_field(self):
@@ -763,8 +737,7 @@
class OneToOneRel(ManyToOneRel):
def __init__(self, to, field_name, num_in_admin=0, edit_inline=False,
- related_name=None, limit_choices_to=None, lookup_overrides=None,
- raw_id_admin=False):
+ related_name=None, limit_choices_to=None, lookup_overrides=None):
self.to, self.field_name = to, field_name
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
self.related_name = related_name
@@ -772,12 +745,11 @@
limit_choices_to = {}
self.limit_choices_to = limit_choices_to
self.lookup_overrides = lookup_overrides or {}
- self.raw_id_admin = raw_id_admin
self.multiple = False
class ManyToManyRel(object):
def __init__(self, to, num_in_admin=0, related_name=None,
- filter_interface=None, limit_choices_to=None, raw_id_admin=False,
symmetrical=True):
+ filter_interface=None, limit_choices_to=None, symmetrical=True):
self.to = to
self.num_in_admin = num_in_admin
self.related_name = related_name
@@ -786,8 +758,5 @@
limit_choices_to = {}
self.limit_choices_to = limit_choices_to
self.edit_inline = False
- self.raw_id_admin = raw_id_admin
self.symmetrical = symmetrical
self.multiple = True
-
- assert not (self.raw_id_admin and self.filter_interface),
"ManyToManyRels may not use both raw_id_admin and filter_interface"
Modified: django/branches/newforms-admin/django/db/models/manipulators.py
===================================================================
--- django/branches/newforms-admin/django/db/models/manipulators.py
2007-01-25 13:47:55 UTC (rev 4429)
+++ django/branches/newforms-admin/django/db/models/manipulators.py
2007-01-25 18:05:10 UTC (rev 4430)
@@ -116,10 +116,7 @@
for f in self.opts.many_to_many:
if self.follow.get(f.name, None):
if not f.rel.edit_inline:
- if f.rel.raw_id_admin:
- new_vals = new_data.get(f.name, ())
- else:
- new_vals = new_data.getlist(f.name)
+ new_vals = new_data.getlist(f.name)
# First, clear the existing values.
rel_manager = getattr(new_object, f.name)
rel_manager.clear()
@@ -216,8 +213,6 @@
for f in related.opts.many_to_many:
if child_follow.get(f.name, None) and not
f.rel.edit_inline:
new_value = rel_new_data[f.attname]
- if f.rel.raw_id_admin:
- new_value = new_value[0]
setattr(new_rel_obj, f.name,
f.rel.to.objects.filter(pk__in=new_value))
if self.change:
self.fields_changed.append('%s for %s
"%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---