Skip to content

Instantly share code, notes, and snippets.

@drdaeman
Last active March 10, 2016 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drdaeman/5326761 to your computer and use it in GitHub Desktop.
Save drdaeman/5326761 to your computer and use it in GitHub Desktop.
Quick-and-dirty fix for forms using ModelChoiceField with to_field_name set.
# Quick-and-dirty fix for forms using ModelChoiceField with to_field_name set.
# See https://code.djangoproject.com/ticket/20202 for details.
# Example usage:
# >>> import form_fixes
# >>> form_fixes.fix_to_field_name()
from django import forms
from django.db import models
def fix_to_field_name():
class TestModel(models.Model):
key = models.CharField(max_length=32, unique=True)
value = models.ForeignKey("TestModel", blank=True, null=True)
class Meta:
managed = False
app_label = "test"
class FakeQueryset(object):
def all(self):
m1 = TestModel(id=1, key="A", value=None)
m2 = TestModel(id=2, key="B", value=m1)
return [m1, m2]
class TestForm(forms.ModelForm):
value = forms.ModelChoiceField(FakeQueryset(), to_field_name="key")
class Meta:
model = TestModel
fields = ("value",)
m1, m2 = FakeQueryset().all()
f = TestForm(instance=m2)
if f.initial["value"] not in (m1, m1.key):
original_init = forms.BaseModelForm.__init__
def __init__(self, *args, **kwargs):
if "instance" in kwargs:
if not "initial" in kwargs:
kwargs["initial"] = {}
# Workaround for Django 1.4 bug, as model_to_dict uses PK, and
# does not know anything about form field's to_field_name.
instance = kwargs["instance"]
for name, field in self.declared_fields.items():
to_name = getattr(field, "to_field_name", None)
if to_name is not None:
f = getattr(instance, name)
if f is not None:
# ManyRelatedManager is a dynamically-generated class, thus the weird-looking check.
if f.__class__.__name__ == "ManyRelatedManager" and hasattr(f, "values_list"):
kwargs["initial"][name] = f.values_list(to_name, flat=True)
else:
kwargs["initial"][name] = getattr(f, to_name)
return original_init(self, *args, **kwargs)
forms.BaseModelForm.__init__ = __init__
return True
return False
if __name__ == "__main__":
patched = fix_to_field_name()
if patched:
assert not fix_to_field_name(), "Patch failed!"
print "Successfully patched"
else:
print "OK"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment