Last active
September 20, 2024 07:55
-
-
Save tim-schilling/62198998a99a19c7f4b73f14d29c6997 to your computer and use it in GitHub Desktop.
Helper classes and a monkeypatch to always register a model's field in the admin as raw_id_fields. This is useful when you have models with 1000+ rows to avoid massive select elements.
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
from functools import wraps | |
from django.contrib import admin | |
class AdminMeta: | |
""" | |
Use this Meta class on a model since we can't add | |
custom fields to Model.Meta | |
""" | |
always_raw_id_field = False | |
def patch_model_admin_always_raw_id_field(): | |
""" | |
Monkey patch admin.ModelAdmin to dynamically register | |
additional raw_id_fields. | |
This is best used in an AppConfig.ready() method | |
""" | |
def patch_model_admin(init): | |
@wraps(init) | |
def __init__(self, model, admin_site, **kwargs): | |
init(self, model, admin_site, **kwargs) | |
# iterate over relationship fields, check if any related models are AdminMeta.always_raw_id_field | |
new_raw_ids_fields = [ | |
field.name | |
for field in model._meta.get_fields() | |
if field.is_relation | |
and field.related_model | |
and field.concrete | |
and (admin_meta := getattr(field.related_model, AdminMeta.__name__, None)) | |
and issubclass(admin_meta, AdminMeta) | |
and admin_meta.always_raw_id_field | |
] | |
if new_raw_ids_fields: | |
self.raw_id_fields = list(self.raw_id_fields) + new_raw_ids_fields | |
return __init__ | |
if getattr(admin.ModelAdmin, '_patched_model_admin_always_raw_id_field', None): | |
return | |
admin.ModelAdmin.__init__ = patch_model_admin(admin.ModelAdmin.__init__) | |
admin.ModelAdmin._patched_model_admin_always_raw_id_field = True |
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
from django.db import models | |
from admin_meta import AdminMeta | |
class AlwaysRawIdModel(models.Model): | |
""" | |
Inherit from this model so that any reference to this | |
field in the admin will be a raw id field | |
""" | |
class Meta: | |
abstract = True | |
class AdminMeta(AdminMeta): | |
always_raw_id_field = True |
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
from django.apps import AppConfig | |
from admin_meta import patch_model_admin_always_raw_id_field | |
class MyApp(AppConfig): | |
name = "my_app" | |
def ready(self): | |
patch_model_admin_always_raw_id_field() |
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
from django.contrib.admin | |
from always_raw_id import AlwaysRawIdModel | |
class MyModel(AlwaysRawIdModel): | |
pass | |
class OtherModel(models.Model): | |
class AdminMeta(AdminMeta): | |
always_raw_id_field = True | |
admin.register(MyModel) | |
admin.register(OtherModel) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment