Opened 6 years ago
Last modified 3 years ago
#23816 assigned New feature
Ability to defer model field by default
Reported by: | Robert Coup | Owned by: | Denis.Tarykin |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | master |
Severity: | Normal | Keywords: | |
Cc: | akiskesoglou@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
Today's small #IWantAPony is to be able to mark model fields as deferred by default. No need to chase down every queryset and add .defer()
, or use a custom manager setup & remember to set use_for_related_fields
.
class MyModel(models.Model): enormous_field = models.TextField(defer=True) other_field = models.IntegerField()
Which is (simplistically) equivalent to the following:
class MyManager(models.Manager): use_for_related_fields = True def get_queryset(self, *args, **kwargs): return super(MyManager, self).get_queryset(*args, **kwargs).defer("enormous_field") class MyModel(models.Model): enormous_field = models.TextField() other_field = models.IntegerField() objects = MyManager()
Obviously, you can still do MyModel.objects.defer(None)
to do the full query.
Change History (9)
comment:1 Changed 6 years ago by
comment:2 Changed 6 years ago by
Cc: | akiskesoglou@… added |
---|
comment:3 Changed 6 years ago by
Triage Stage: | Unreviewed → Accepted |
---|
I am a little hesitant to accept since there is already a way to accomplish this, but tentatively accepting so we can see what a patch looks like and someone else really likes the idea.
comment:4 Changed 6 years ago by
I'm also hesitant about adding something that's already doable via a custom manager; I'm probably -0.
If we do it, it should definitely be a Meta
option, not a field arg, IMO. It applies to fields, but it's really a characteristic of querying on the model class, not inherently of the Field.
comment:5 Changed 6 years ago by
I'm inclined to have a go at this. Here's how I envision it:
class Post(models.Model): body_text = models.TextField() body_html = models.TextField(blank=True) class Meta: initially_deferred_fields = ('body_text', 'body_html')
Some thoughts:
- Not sure about the name of the meta attribute, it requires almost as much effort to get the spelling right as creating a custom manager, but I'd like to avoid naming it
defer
ordeferred_fields
. I'd like input on this, but it's not pressing. - The patch author should be aware of the model meta refactor, perhaps beginning work after it lands?
comment:6 Changed 5 years ago by
I can see a use for this. Currently using a manager which looks at auto_defer
(on the manager due to 5793).
class AutoDeferManagerMixin(object): use_for_related_fields = True auto_defer = tuple() def get_queryset(self, *args, **kwargs): return super(AutoDeferManagerMixin, self).get_queryset(*args, **kwargs).defer(*self.auto_defer)
comment:7 Changed 3 years ago by
Owner: | changed from nobody to Denis.Tarykin |
---|---|
Status: | new → assigned |
comment:9 Changed 3 years ago by
Patch needs improvement: | set |
---|
Marking "Patch needs improvement" pending comments on PR
I find this really useful, as most of the times you (myself actually, assuming most people too) really don't make a manager just for this optimisation. So defining deferred fields at model level makes sense for me. Though I would prefer to specify the fields in the model's Meta options, as a list of field names, similar to unique_together option.