Last active
March 10, 2016 14:05
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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