2012-12-17 23:09:07 +08:00
|
|
|
from collections import namedtuple
|
|
|
|
|
2012-07-21 16:00:10 +08:00
|
|
|
from django.utils.encoding import smart_text
|
2010-11-22 03:29:15 +08:00
|
|
|
from django.db.models.fields import BLANK_CHOICE_DASH
|
|
|
|
|
2012-12-17 23:09:07 +08:00
|
|
|
# PathInfo is used when converting lookups (fk__somecol). The contents
|
|
|
|
# describe the relation in Model terms (model Options and Fields for both
|
|
|
|
# sides of the relation. The join_field is the field backing the relation.
|
|
|
|
PathInfo = namedtuple('PathInfo',
|
2013-03-25 00:40:40 +08:00
|
|
|
'from_opts to_opts target_fields join_field '
|
2012-12-17 23:09:07 +08:00
|
|
|
'm2m direct')
|
|
|
|
|
2013-07-08 08:39:54 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
class RelatedObject(object):
|
|
|
|
def __init__(self, parent_model, model, field):
|
|
|
|
self.parent_model = parent_model
|
|
|
|
self.model = model
|
|
|
|
self.opts = model._meta
|
|
|
|
self.field = field
|
2013-02-05 17:16:07 +08:00
|
|
|
self.name = '%s:%s' % (self.opts.app_label, self.opts.model_name)
|
|
|
|
self.var_name = self.opts.model_name
|
2006-05-02 09:31:56 +08:00
|
|
|
|
2010-11-22 03:29:15 +08:00
|
|
|
def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH,
|
|
|
|
limit_to_currently_related=False):
|
|
|
|
"""Returns choices with a default blank choices included, for use
|
|
|
|
as SelectField choices for this field.
|
|
|
|
|
|
|
|
Analogue of django.db.models.fields.Field.get_choices, provided
|
2014-03-02 22:25:53 +08:00
|
|
|
initially for utilization by RelatedFieldListFilter.
|
2010-11-22 03:29:15 +08:00
|
|
|
"""
|
2013-05-17 22:33:36 +08:00
|
|
|
first_choice = blank_choice if include_blank else []
|
2010-11-22 03:29:15 +08:00
|
|
|
queryset = self.model._default_manager.all()
|
|
|
|
if limit_to_currently_related:
|
|
|
|
queryset = queryset.complex_filter(
|
2013-02-05 17:16:07 +08:00
|
|
|
{'%s__isnull' % self.parent_model._meta.model_name: False})
|
2012-07-21 16:00:10 +08:00
|
|
|
lst = [(x._get_pk_val(), smart_text(x)) for x in queryset]
|
2010-11-22 03:29:15 +08:00
|
|
|
return first_choice + lst
|
2012-07-21 16:00:10 +08:00
|
|
|
|
2009-12-22 23:18:51 +08:00
|
|
|
def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
|
2006-07-01 09:14:41 +08:00
|
|
|
# Defer to the actual field definition for db prep
|
2009-12-22 23:18:51 +08:00
|
|
|
return self.field.get_db_prep_lookup(lookup_type, value,
|
|
|
|
connection=connection, prepared=prepared)
|
Removed oldforms, validators, and related code:
* Removed `Manipulator`, `AutomaticManipulator`, and related classes.
* Removed oldforms specific bits from model fields:
* Removed `validator_list` and `core` arguments from constructors.
* Removed the methods:
* `get_manipulator_field_names`
* `get_manipulator_field_objs`
* `get_manipulator_fields`
* `get_manipulator_new_data`
* `prepare_field_objs_and_params`
* `get_follow`
* Renamed `flatten_data` method to `value_to_string` for better alignment with its use by the serialization framework, which was the only remaining code using `flatten_data`.
* Removed oldforms methods from `django.db.models.Options` class: `get_followed_related_objects`, `get_data_holders`, `get_follow`, and `has_field_type`.
* Removed oldforms-admin specific options from `django.db.models.fields.related` classes: `num_in_admin`, `min_num_in_admin`, `max_num_in_admin`, `num_extra_on_change`, and `edit_inline`.
* Serialization framework
* `Serializer.get_string_value` now calls the model fields' renamed `value_to_string` methods.
* Removed a special-casing of `models.DateTimeField` in `core.serializers.base.Serializer.get_string_value` that's handled by `django.db.models.fields.DateTimeField.value_to_string`.
* Removed `django.core.validators`:
* Moved `ValidationError` exception to `django.core.exceptions`.
* For the couple places that were using validators, brought over the necessary code to maintain the same functionality.
* Introduced a SlugField form field for validation and to compliment the SlugField model field (refs #8040).
* Removed an oldforms-style model creation hack (refs #2160).
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8616 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2008-08-27 15:19:44 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
def editable_fields(self):
|
|
|
|
"Get the fields in this class that should be edited inline."
|
|
|
|
return [f for f in self.opts.fields + self.opts.many_to_many if f.editable and f != self.field]
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return "<RelatedObject: %s related to %s>" % (self.name, self.field.name)
|
|
|
|
|
|
|
|
def get_accessor_name(self):
|
|
|
|
# This method encapsulates the logic that decides what name to give an
|
|
|
|
# accessor descriptor that retrieves related many-to-one or
|
|
|
|
# many-to-many objects. It uses the lower-cased object_name + "_set",
|
|
|
|
# but this can be overridden with the "related_name" option.
|
|
|
|
if self.field.rel.multiple:
|
2006-09-07 21:29:56 +08:00
|
|
|
# If this is a symmetrical m2m relation on self, there is no reverse accessor.
|
|
|
|
if getattr(self.field.rel, 'symmetrical', False) and self.model == self.parent_model:
|
|
|
|
return None
|
2014-06-07 00:16:17 +08:00
|
|
|
if self.field.rel.related_name:
|
|
|
|
return self.field.rel.related_name
|
|
|
|
if self.opts.default_related_name:
|
|
|
|
return self.opts.default_related_name % {
|
|
|
|
'model_name': self.opts.model_name.lower(),
|
|
|
|
'app_label': self.opts.app_label.lower(),
|
|
|
|
}
|
|
|
|
return self.opts.model_name + '_set'
|
2006-05-02 09:31:56 +08:00
|
|
|
else:
|
2013-02-05 17:16:07 +08:00
|
|
|
return self.field.rel.related_name or (self.opts.model_name)
|
2010-01-27 21:30:29 +08:00
|
|
|
|
|
|
|
def get_cache_name(self):
|
|
|
|
return "_%s_cache" % self.get_accessor_name()
|
2012-12-17 23:09:07 +08:00
|
|
|
|
|
|
|
def get_path_info(self):
|
|
|
|
return self.field.get_reverse_path_info()
|