1+ from collections .abc import Iterable
2+ from itertools import islice , zip_longest
3+
14from django .core import exceptions , validators
25from django .db import models
36from django .apps import apps
1215from .generic import GenericForeignKey
1316from .widgets import SourceSelect
1417
18+ try :
19+ from django .utils .choices import BaseChoiceIterator
20+ except ImportError :
21+ class BaseChoiceIterator :
22+ """Base class for lazy iterators for choices."""
23+
24+ def __eq__ (self , other ):
25+ if isinstance (other , Iterable ):
26+ return all (a == b for a , b in zip_longest (self , other , fillvalue = object ()))
27+ return super ().__eq__ (other )
28+
29+ def __getitem__ (self , index ):
30+ if isinstance (index , slice ) or index < 0 :
31+ # Suboptimally consume whole iterator to handle slices and negative
32+ # indexes.
33+ return list (self )[index ]
34+ try :
35+ return next (islice (self , index , index + 1 ))
36+ except StopIteration :
37+ raise IndexError ("index out of range" ) from None
38+
39+ def __iter__ (self ):
40+ raise NotImplementedError (
41+ "BaseChoiceIterator subclasses must implement __iter__()."
42+ )
43+
44+
1545
1646def get_content_type_id_for_model (model ):
1747 value = ContentType .objects .get_for_model (model , False ).pk
@@ -109,7 +139,7 @@ class CuratedGenericForeignKey(CuratedRelatedField, GenericForeignKey):
109139 pass
110140
111141
112- class ContentTypeIdChoices (object ):
142+ class ContentTypeIdChoices (BaseChoiceIterator ):
113143 """
114144 Iterable used for ContentTypeSourceField's `choices` keyword argument
115145 """
@@ -136,7 +166,7 @@ def __iter__(self):
136166 yield (source_value , label )
137167
138168
139- class ContentTypeSourceChoices (object ):
169+ class ContentTypeSourceChoices (BaseChoiceIterator ):
140170
141171 # Sentinel value if a given choice in ct_choices is a 2-tuple and so does
142172 # not have a source_value
@@ -544,6 +574,9 @@ def __init__(self, *args, **kwargs):
544574 kwargs .setdefault ('on_delete' , models .CASCADE )
545575 super (ContentTypeSourceField , self ).__init__ ('contenttypes.ContentType' , * args , ** kwargs )
546576
577+ def get_cache_name (self ):
578+ return self .name
579+
547580 def contribute_to_class (self , cls , name ):
548581 super (models .ForeignKey , self ).contribute_to_class (cls , name )
549582
0 commit comments