Changes between Initial Version and Version 1 of Ticket #33137
- Timestamp:
- Sep 24, 2021, 7:00:27 AM (3 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Ticket #33137 – Description
initial v1 2 2 3 3 Let's say you have two models `A` and `B` where `A.rel = MyOneToOneField(B)` and `A.deleted = BooleanField()`. In a regular `OneToOneField` there would now be a unique index on `A.rel`. However, by adding a unique constraint to `A._meta.constraints` over `rel` with a condition on `deleted=False`, `rel` only needs to be unique among the "undeleted" objects. Doing so is possible by forcing `MyOneToOneField.unique=False` (otherwise migrations create a constraint). However, this will mean, `SQLCompiler.get_related_selections()` fails when trying to do `B.objects.select_related("a")`, since `a` is not a valid field. That is because `SQLCompiler.get_related_selections._get_field_choices()` uses `f.field.unique` instead of `(f.field.many_to_one or f.field.one_to_one)`, I think. Because, essentially, `opts.related_objects` is build based on those `(many|one)_to_(many|one)` field attributes. 4 5 I think, what would fix the behavior, could be something like this: 6 7 {{{#!python 8 class SQLCompiler: 9 def get_related_selections(self, select, opts=None, root_alias=None, cur_depth=1, 10 requested=None, restricted=None): 11 def _get_field_choices(): 12 direct_choices = (f.name for f in opts.fields if f.is_relation) 13 reverse_choices = ( 14 f.field.related_query_name() 15 for f in opts.related_objects if (f.field.many_to_one or f.field.one_to_one) 16 ) 17 return chain(direct_choices, reverse_choices, self.query._filtered_relations) 18 }}}