Skip to content

Instantly share code, notes, and snippets.

@carymrobbins
Last active August 3, 2022 12:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save carymrobbins/8721082 to your computer and use it in GitHub Desktop.
Save carymrobbins/8721082 to your computer and use it in GitHub Desktop.
Override a model field in Django!
from django.db.models.fields.related import ReverseSingleRelatedObjectDescriptor
def override_model_field(model, name, column, field):
"""Force override a field in a Django Model.
Usage: override_model_field(
MyModel, models.ForeignKey(OtherModel), 'other', 'other_id')
:type model: django.db.models.base.ModelBase
:type name: basestring
:type column: basestring
:type field: django.db.models.fields.Field
"""
class FieldOverrideProxy(type(field)):
# noinspection PyMissingConstructor
def __init__(self, original_field):
self.original_field = original_field
self.new_field = field
self.name = self.new_field.name = name
self.attname = self.new_field.attname = column
self.default = original_field.default
self.new_field.verbose_name = (field.verbose_name or
original_field.verbose_name)
def __getattr__(self, item):
try:
return getattr(self.new_field, item)
except AttributeError:
return getattr(self.original_field, item)
for i, f in enumerate(model._meta.fields):
if f.name == name:
field_proxy = FieldOverrideProxy(f)
model._meta.fields[i] = field_proxy
break
else:
raise TypeError('Model {!r} does not have a field {!r}.'
.format(model, name))
model.add_to_class(name, ReverseSingleRelatedObjectDescriptor(field_proxy))
# Example usage:
from django.db import models
class ChildModel(models.Model):
pass
class TheModel(models.Model):
child = models.ForeignKey(ChildModel)
class ChildModelProxy(ChildModel):
class Meta:
proxy = True
class TheModelProxy(TheModel):
class Meta:
proxy = True
override_model_field(TheModelProxy, 'child', 'child_id',
models.ForeignKey(ChildModelProxy))
@shadeofblue
Copy link

@carymrobbins hi, what's the license associated with the snippet above? I'd like to use it in a closed-source project if you have nothing against it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment