Skip to content

Instantly share code, notes, and snippets.

@scythargon
Last active August 29, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scythargon/9949835 to your computer and use it in GitHub Desktop.
Save scythargon/9949835 to your computer and use it in GitHub Desktop.
def get_chained_select_choices(content_type, depth=1, with_field_types=False):
""" Gets field names from the content_type.
depth=1 means return any fk or manytomany fields as well
TODO: depth>1 is not implemented yet
"""
if depth > 1:
raise Exception("depth should be 0 or 1")
# helpers
model_klass = content_type.model_class()
model_to_fields = defaultdict(list)
# dict model -> fields related to that model
for fld in (model_klass._meta.fields + model_klass._meta.many_to_many):
if fld.rel:
model_to_fields[fld.rel.to].append(fld)
model_to_fields = dict(model_to_fields)
all_fields = sum(model_to_fields.values(), [])
# names of fields available on form
fields_on_form = set(content_type.config.modelfield_set.values_list('fieldname', flat=True))
def flatelizer(fields):
# go thrue every field in model
for fld in fields:
# if it's foreing key and visible on form
if fld.rel and fld.name in fields_on_form:
# get all related for that field
for subfield in fld.rel.to._meta.fields + fld.rel.to._meta.many_to_many:
# if it's related
if subfield.rel:
# subsubfield.rel.to should pointing to any field on form, it its correct
# that pointed field can filter subsubfield by subfield filter
for subsubfield in model_to_fields.get(subfield.rel.to, []):
# if fld.name != subsubfield.name and subfield:
if fld.name != subsubfield.name:
yield subsubfield.name, subfield.name, fld.name,
tmp = defaultdict(list)
for parent, filter_by, fld_name in flatelizer(all_fields):
tmp[parent].append([filter_by, fld_name])
choices = []
for parent, subfields in tmp.iteritems():
if len(subfields)==1:
choices.append(('{0}__{1}'.format(parent, subfields[0][0], '{0} fld: {1}'.format(parent, subfields[0][1], False, False, False))))
else:
for filtered_by, fld_name in subfields:
choices.append(('{0}__{1}'.format(parent, filtered_by), '{0} ({1}) fld: {2}'.format(parent, filtered_by, fld_name)))
#choices = [(relative_field, relative_field.replace('__', ' → '), '', False, False, ('.field-fieldname select', for_field)) for relative_field, for_field in flatelizer(all_fields)]
return tuple(choices)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment