Question: SQL generated for negated F() expressions is incorrect Description Consider the following model definition. from import models class Rectangle(models.Model): length = models.IntegerField(null=True) width = models.IntegerField(null=True) We make the following queries: Q1) Rectangles that are squares. Q2a) Rectangles that are not squares (length != width). Q2b) Rectangles that are not squares (width != length). Queries Q2a and Q2b semantically mean the same. However, the ORM generates different SQL for these two queries. import django () from import F from import Rectangle print '--- Q1: Get the rectangles that are squares' print (length=F('width')).values('pk').query print '--- Q2a: Get the rectangles that are not squares' print Rectangle.objects.exclude(length=F('width')).values('pk').query print '--- Q2b: Get the rectangles that are not squares' print Rectangle.objects.exclude(width=F('length')).values('pk').query The generated SQL is --- Q1: Get the rectangles that are squares SELECT "testapprectangle"."id" FROM "testapprectangle" WHERE "testapprectangle"."length" = ("testapprectangle"."width") --- Q2a: Get the rectangles that are not squares SELECT "testapprectangle"."id" FROM "testapprectangle" WHERE NOT ("testapprectangle"."length" = ("testapprectangle"."width") AND "testapprectangle"."length" IS NOT NULL) --- Q2b: Get the rectangles that are not squares SELECT "testapprectangle"."id" FROM "testapprectangle" WHERE NOT ("testapprectangle"."width" = ("testapprectangle"."length") AND "testapprectangle"."width" IS NOT NULL) Note the asymmetry between Q2a and Q2b. These queries will return different results. Reddit user /u/charettes set up this useful SQL fiddle with the above mentioned schema and test values: !12//4 Here's my reddit post on this issue:

# (col IS NULL OR col != someval)                 #   <=>                 # NOT (col IS NOT NULL AND col = someval).                lookup_class = targets[0].get_lookup('isnull')                col = self._get_col(targets[0], join_info.targets[0], alias)                clause.add(lookup_class(col, False), AND)                if (                    self.is_nullable(targets[0]) or                    self.alias_map[join_list[-1]].join_type == LOUTER                ):                    lookup_class = targets[0].get_lookup('isnull')                    col = self._get_col(targets[0], join_info.targets[0], alias)                    clause.add(lookup_class(col, False), AND)                # If someval is a nullable column, someval IS NOT NULL is                # added.                if isinstance(value, Col) and self.is_nullable(value.target):                    lookup_class = value.target.get_lookup('isnull')                    clause.add(lookup_class(value, False), AND)         return clause, used_joins if not require_outer else ()      def add_filter(self, filter_clause):


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

"""         raise NotImplementedError('subclasses of BaseDatabaseOperations may require a date_extract_sql() method')     def date_interval_sql(self, timedelta):        """        Implement the date interval functionality for expressions.        """        raise NotImplementedError('subclasses of BaseDatabaseOperations may require a date_interval_sql() method')     def date_trunc_sql(self, lookup_type, field_name):         """         Given a lookup_type of 'year', 'month', or 'day', return the SQL thatdiff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py-- a/django/db/backends/mysql/operations.py++ b/django/db/backends/mysql/operations.py


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

from django.conf import settings from django.db.backends.base.operations import BaseDatabaseOperations from django.utils import timezone<del>from django.utils.duration import duration_microseconds</del> from django.utils.encoding import force_str


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

else:             return "TIME(%s)" % (field_name)     def date_interval_sql(self, timedelta):        return 'INTERVAL %s MICROSECOND' % duration_microseconds(timedelta)     def fetch_returned_insert_rows(self, cursor):         """         Given a cursor object that has just performed an INSERT...RETURNINGdiff --git a/django/db/backends/sqlite3/operations.py b/django/db/backends/sqlite3/operations.py-- a/django/db/backends/sqlite3/operations.py++ b/django/db/backends/sqlite3/operations.py


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

from django.db.models.expressions import Col from django.utils import timezone from django.utils.dateparse import parse_date, parse_datetime, parse_time<del>from django.utils.duration import duration_microseconds</del> from django.utils.functional import cached_property


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

"""         return "django_date_extract('%s', %s)" % (lookup_type.lower(), field_name)     def date_interval_sql(self, timedelta):        return str(duration_microseconds(timedelta))     def format_for_duration_arithmetic(self, sql):         """Do nothing since formatting is handled in the custom function."""         return sqldiff --git a/django/db/models/expressions.py b/django/db/models/expressions.py-- a/django/db/models/expressions.py++ b/django/db/models/expressions.py


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

def _combine(self, other, connector, reversed):         if not hasattr(other, 'resolve_expression'):             # everything must be resolvable to an expression            if isinstance(other, datetime.timedelta):                other = DurationValue(other, output_field=fields.DurationField())            else:                other = Value(other)            output_field = (                fields.DurationField()                if isinstance(other, datetime.timedelta) else                None            )            other = Value(other, output_field=output_field)          if reversed:             return CombinedExpression(other, connector, self)


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

def as_sql(self, compiler, connection):         try:            lhs_output = self.lhs.output_field            lhs_type = self.lhs.output_field.get_internal_type()         except FieldError:            lhs_output = None            lhs_type = None         try:            rhs_output = self.rhs.output_field            rhs_type = self.rhs.output_field.get_internal_type()         except FieldError:            rhs_output = None        if (not connection.features.has_native_duration_field and                ((lhs_output and lhs_output.get_internal_type() == 'DurationField') or                 (rhs_output and rhs_output.get_internal_type() == 'DurationField'))):            rhs_type = None        if (            not connection.features.has_native_duration_field and            'DurationField' in {lhs_type, rhs_type} and            lhs_type != rhs_type        ):             return DurationExpression(self.lhs, self.connector, self.rhs).as_sql(compiler, connection)        if (lhs_output and rhs_output and self.connector == self.SUB and            lhs_output.get_internal_type() in {'DateField', 'DateTimeField', 'TimeField'} and                lhs_output.get_internal_type() == rhs_output.get_internal_type()):        datetime_fields = {'DateField', 'DateTimeField', 'TimeField'}        if self.connector == self.SUB and lhs_type in datetime_fields and lhs_type == rhs_type:             return TemporalSubtraction(self.lhs, self.rhs).as_sql(compiler, connection)         expressions = []         expression_params = []


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

class DurationExpression(CombinedExpression):     def compile(self, side, compiler, connection):        if not isinstance(side, DurationValue):            try:                output = side.output_field            except FieldError:                pass            else:                if output.get_internal_type() == 'DurationField':                    sql, params = compiler.compile(side)                    return connection.ops.format_for_duration_arithmetic(sql), params        try:            output = side.output_field        except FieldError:            pass        else:            if output.get_internal_type() == 'DurationField':                sql, params = compiler.compile(side)                return connection.ops.format_for_duration_arithmetic(sql), params         return compiler.compile(side)      def as_sql(self, compiler, connection):


Question: durations-only expressions doesn't work on SQLite and MySQL Description class Experiment(models.Model): estimatedtime = models.DurationField() list(Experiment.objects.annotate(duration=F('estimatedtime') + datime.timedelta(1))) Traceback (most recent call last): File "", line 1218, in testdurationexpressions list(Experiment.objects.annotate(duration=F('estimatedtime') + delta)) File "", line 269, in iter self.fetchall() File "", line 1172, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 63, in iter for row in compiler.resultsiter(results): File "", line 998, in applyconverters value = converter(value, expression, connection) File "", line 571, in convertdurationfield_value value = str(decimal.Decimal(value) / decimal.Decimal()) decimal.InvalidOperation: [<class 'decimal.ConversionSyntax']

return []  <del>class DurationValue(Value):    def as_sql(self, compiler, connection):        connection.ops.check_expression_support(self)        if connection.features.has_native_duration_field:            return super().as_sql(compiler, connection)        return connection.ops.date_interval_sql(self.value), []</del> class RawSQL(Expression):     def __init__(self, sql, params, output_field=None):         if output_field is None:


Question: make temporal subtraction work without ExpressionWrapper Description class Experiment(models.Model): start = models.DateTimeField() end = models.DateTimeField() Experiment.objects.annotate( delta=F('end') - F('start') + Value(datetime.timedelta(), outputfield=DurationField()) ) This gives: Expression contains mixed types: DateTimeField, DurationField. You must set outputfield.

self.lhs, self.rhs = exprs      def as_sql(self, compiler, connection):<del>        try:            lhs_type = self.lhs.output_field.get_internal_type()        except FieldError:            lhs_type = None        try:            rhs_type = self.rhs.output_field.get_internal_type()        except FieldError:            rhs_type = None        if (            not connection.features.has_native_duration_field and            'DurationField' in {lhs_type, rhs_type} and            lhs_type != rhs_type        ):            return DurationExpression(self.lhs, self.connector, self.rhs).as_sql(compiler, connection)        datetime_fields = {'DateField', 'DateTimeField', 'TimeField'}        if self.connector == self.SUB and lhs_type in datetime_fields and lhs_type == rhs_type:            return TemporalSubtraction(self.lhs, self.rhs).as_sql(compiler, connection)</del>         expressions = []         expression_params = []         sql, params = compiler.compile(self.lhs)


Question: make temporal subtraction work without ExpressionWrapper Description class Experiment(models.Model): start = models.DateTimeField() end = models.DateTimeField() Experiment.objects.annotate( delta=F('end') - F('start') + Value(datetime.timedelta(), outputfield=DurationField()) ) This gives: Expression contains mixed types: DateTimeField, DurationField. You must set outputfield.

return expression_wrapper % sql, expression_params      def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):        lhs = self.lhs.resolve_expression(query, allow_joins, reuse, summarize, for_save)        rhs = self.rhs.resolve_expression(query, allow_joins, reuse, summarize, for_save)        if not isinstance(self, (DurationExpression, TemporalSubtraction)):            try:                lhs_type = lhs.output_field.get_internal_type()            except (AttributeError, FieldError):                lhs_type = None            try:                rhs_type = rhs.output_field.get_internal_type()            except (AttributeError, FieldError):                rhs_type = None            if 'DurationField' in {lhs_type, rhs_type} and lhs_type != rhs_type:                return DurationExpression(self.lhs, self.connector, self.rhs).resolve_expression(                    query, allow_joins, reuse, summarize, for_save,                )            datetime_fields = {'DateField', 'DateTimeField', 'TimeField'}            if self.connector == self.SUB and lhs_type in datetime_fields and lhs_type == rhs_type:                return TemporalSubtraction(self.lhs, self.rhs).resolve_expression(                    query, allow_joins, reuse, summarize, for_save,                )         c = self.copy()         c.is_summary = summarize        c.lhs = c.lhs.resolve_expression(query, allow_joins, reuse, summarize, for_save)        c.rhs = c.rhs.resolve_expression(query, allow_joins, reuse, summarize, for_save)        c.lhs = lhs        c.rhs = rhs         return c


Question: make temporal subtraction work without ExpressionWrapper Description class Experiment(models.Model): start = models.DateTimeField() end = models.DateTimeField() Experiment.objects.annotate( delta=F('end') - F('start') + Value(datetime.timedelta(), outputfield=DurationField()) ) This gives: Expression contains mixed types: DateTimeField, DurationField. You must set outputfield.

return compiler.compile(side)      def as_sql(self, compiler, connection):<ins>        if connection.features.has_native_duration_field:            return super().as_sql(compiler, connection)</ins>         connection.ops.check_expression_support(self)         expressions = []         expression_params = []


Question: timesince 'depth' parameter Description (last modified by Toby Such) Discussed here. The timesince function is a bit limiting as it is right now. A depth parameter should be to configure how many values are shown. The depth parameter should be defaulted to 2 as this is how the current implementation behaves. The existing rule of values having to be adjacent to one another should still remain. The logic for calculating the time since, before formatting should also be pulled out of the function and placed in its own so that custom implementations can be created. For example: With a depth of one it should always display as "1 week" or "3 years" etc. With a depth of two: "1 week, 3 days" or "3 years, 7 months" With a depth of three: "1 week, 3 days, 5 hours" or "3 years, 7 months, 2 weeks"

)  def timesince(d, now=None, reversed=False, time_strings=None):def timesince(d, now=None, reversed=False, time_strings=None, depth=2):     """     Take two datetime objects and return the time between d and now as a nicely     formatted string, e.g. "10 minutes". If d occurs after now, return     "0 minutes".      Units used are years, months, weeks, days, hours, and minutes.    Seconds and microseconds are ignored.  Up to two adjacent units will be    Seconds and microseconds are ignored. Up to `depth` adjacent units will be     displayed.  For example, "2 weeks, 3 days" and "1 year, 3 months" are     possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.      `time_strings` is an optional dict of strings to replace the default     TIME_STRINGS dict.     `depth` is an optional integer to control the number of adjacent time    units returned.     Adapted from     https://web.archive.org/web/20060617175230/http://blog.natbat.co.uk/archive/2003/Jun/14/time_since     """     if time_strings is None:         time_strings = TIME_STRINGS    if depth <= 0:        raise ValueError('depth must be greater than 0.')     # Convert datetime.date to datetime.datetime for comparison.     if not isinstance(d, datetime.datetime):         d = datetime.datetime(d.year, d.month, d.day)


Question: timesince 'depth' parameter Description (last modified by Toby Such) Discussed here. The timesince function is a bit limiting as it is right now. A depth parameter should be to configure how many values are shown. The depth parameter should be defaulted to 2 as this is how the current implementation behaves. The existing rule of values having to be adjacent to one another should still remain. The logic for calculating the time since, before formatting should also be pulled out of the function and placed in its own so that custom implementations can be created. For example: With a depth of one it should always display as "1 week" or "3 years" etc. With a depth of two: "1 week, 3 days" or "3 years, 7 months" With a depth of three: "1 week, 3 days, 5 hours" or "3 years, 7 months, 2 weeks"

count = since // seconds         if count != 0:             break    result = avoid_wrapping(time_strings[name] % count)    if i + 1 < len(TIMESINCE_CHUNKS):        # Now get the second item        seconds2, name2 = TIMESINCE_CHUNKS[i + 1]        count2 = (since - (seconds * count)) // seconds2        if count2 != 0:            result += gettext(', ') + avoid_wrapping(time_strings[name2] % count2)    return result    else:        return avoid_wrapping(time_strings['minute'] % 0)    result = []    current_depth = 0    while i < len(TIMESINCE_CHUNKS) and current_depth < depth:        seconds, name = TIMESINCE_CHUNKS[i]        count = since // seconds        if count == 0:            break        result.append(avoid_wrapping(time_strings[name] % count))        since -= seconds * count        current_depth += 1        i += 1    return gettext(', ').join(result)  def timeuntil(d, now=None, time_strings=None):def timeuntil(d, now=None, time_strings=None, depth=2):     """     Like timesince, but return a string measuring the time until the given time.     """    return timesince(d, now, reversed=True, time_strings=time_strings)    return timesince(d, now, reversed=True, time_strings=time_strings, depth=depth)


Question: () on combined queries returns all results. Description I came across this issue on Stack Overflow. I'm not 100% sure it's a bug, but it does seem strange. With this code (excuse the bizarre example filtering): class Publication(models.Model): pass class Article(models.Model): publications = models.ManyToManyField(to=Publication, blank=True, null=True) class ArticleForm(forms.ModelForm): publications = forms.ModelMultipleChoiceField( (idlt=2) | (idgt=5), required=False, ) class Meta: model = Article fields = ["publications"] class ArticleAdmin(admin.ModelAdmin): form = ArticleForm This works well. However, changing the ModelMultipleChoiceField queryset to use union() breaks things. publications = forms.ModelMultipleChoiceField( (idlt=2).union( (idgt=5) ), required=False, ) The form correctly shows only the matching objects. However, if you submit this form while empty (i.e. you didn't select any publications), ALL objects matching the queryset will be . Using the OR query, NO objects are , as I'd expect.

obj.annotation_select_mask = None         else:             obj.annotation_select_mask = self.annotation_select_mask.copy()<ins>        obj.combined_queries = tuple(query.clone() for query in self.combined_queries)</ins>         # _annotation_select_cache cannot be copied, as doing so breaks the         # (necessary) state in which both annotations and         # _annotation_select_cache point to the same underlying objects.


Question: () on combined queries returns all results. Description I came across this issue on Stack Overflow. I'm not 100% sure it's a bug, but it does seem strange. With this code (excuse the bizarre example filtering): class Publication(models.Model): pass class Article(models.Model): publications = models.ManyToManyField(to=Publication, blank=True, null=True) class ArticleForm(forms.ModelForm): publications = forms.ModelMultipleChoiceField( (idlt=2) | (idgt=5), required=False, ) class Meta: model = Article fields = ["publications"] class ArticleAdmin(admin.ModelAdmin): form = ArticleForm This works well. However, changing the ModelMultipleChoiceField queryset to use union() breaks things. publications = forms.ModelMultipleChoiceField( (idlt=2).union( (idgt=5) ), required=False, ) The form correctly shows only the matching objects. However, if you submit this form while empty (i.e. you didn't select any publications), ALL objects matching the queryset will be . Using the OR query, NO objects are , as I'd expect.

def set_empty(self):         self.where.add(NothingNode(), AND)<ins>        for query in self.combined_queries:            query.set_empty()</ins>      def is_empty(self):         return any(isinstance(c, NothingNode) for c in self.where.children)


Question: Improve default name of merge migrations. Description Currently, merge migrations filenames are created with a timestamp. For example: This name is more opaque than necessary. When one reads it, it isn't immediately clear which migrations were merged. One must inspect the file to find that information. Instead, I suggest the default filename should be created by combining the files being merged. This way, it includes the information without requiring one to inspect the file. This information is also useful in the migrate command's output. As it is most likely to merge two migrations files, this should remain a reasonable length. For example: If preferable, we could decide to join the names in other ways too. For example, separate names by _ (two underscores) or exclude prefix numbers. To start, I'll go with the easiest approach unless there is strong preference for a different naming scheme.

subclass = type("Migration", (Migration,), {                     "dependencies": [(app_label, migration.name) for migration in merge_migrations],                 })                migration_name = "%04i_%s" % (                    biggest_number + 1,                    self.migration_name or ("merge_%s" % get_migration_name_timestamp())                )                parts = ['%04i' % (biggest_number + 1)]                if self.migration_name:                    parts.append(self.migration_name)                else:                    parts.append('merge')                    leaf_names = '_'.join(sorted(migration.name for migration in merge_migrations))                    if len(leaf_names) > 47:                        parts.append(get_migration_name_timestamp())                    else:                        parts.append(leaf_names)                migration_name = '_'.join(parts)                 new_migration = subclass(migration_name, app_label)                 writer = MigrationWriter(new_migration, self.include_header)


Question: ExpressionWrapper loses outputfield for combined expression without an outputfield. Description I have the following model. class Mallets(models.Model): id = models.AutoField(primarykey=True,blank=True, null=True) hindsight = models.ForeignKey(Hindsight, models.DONOTHING, blank=True, null=True) believer = models.IntegerField(blank=True, null=True) damnably = models.IntegerField(blank=True, null=True) issue = models.IntegerField(blank=True, null=True) glover = models.TextField(blank=True, null=True) # This field type is a guess. class Meta: dbtable = 'mallets' and I perform the following query on Django 3.2 sheer = ExpressionWrapper((F('issue') / F('id')), outputfield=FloatField()) lacquer = ExpressionWrapper(Avg(F('sheer'), outputfield=FloatField()), outputfield=TextField()) q = ('default') ret = q.annotate(sheer=sheer).values('sheer').annotate(lacquer=Sum(F('believer'))).orderby('sheer').first() Django however throws the following exception Traceback (most recent call last): File "", line 25, in <moduleret2 = ret1.annotate(sheer=sheer).values('sheer').annotate(lacquer=Sum('believer')).orderby('sheer').first() File "", line 678, in first for obj in (self if self.ordered else self.orderby('pk'))[:1]: File "", line 287, in iter self.fetchall() File "", line 1305, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 111, in iter for row in compiler.resultsiter(chunkedfetch=self.chunkedfetch, chunksize=self.chunksize): File "", line 1113, in resultsiter results = self.executesql(MULTI, chunkedfetch=chunkedfetch, chunksize=chunksize) File "", line 1148, in executesql sql, params = () File "", line 498, in assql extraselect, orderby, groupby = self.presqlsetup() File "", line 60, in presqlsetup groupby = self.getgroupby( + extraselect, orderby) File "", line 142, in getgroupby sql, params = expr.selectformat(self, sql, params) File "", line 388, in selectformat if hasattr(self.outputfield, 'selectformat'): File "", line 48, in get res = [] = (instance) File "", line 269, in outputfield outputfield = self.resolveoutputfield() File "", line 309, in resolveoutputfield , Expression contains mixed types: IntegerField, AutoField. You must set output_field. Note that when I run the query above on Django 3.0.8, this query runs as expected. So is this a regression in Django 3.2?

def __init__(self, expression, output_field):         super().__init__(output_field=output_field)<del>        if getattr(expression, '_output_field_or_none', True) is None:            expression = expression.copy()            expression.output_field = output_field</del>         self.expression = expression      def set_source_expressions(self, exprs):


Question: ExpressionWrapper loses outputfield for combined expression without an outputfield. Description I have the following model. class Mallets(models.Model): id = models.AutoField(primarykey=True,blank=True, null=True) hindsight = models.ForeignKey(Hindsight, models.DONOTHING, blank=True, null=True) believer = models.IntegerField(blank=True, null=True) damnably = models.IntegerField(blank=True, null=True) issue = models.IntegerField(blank=True, null=True) glover = models.TextField(blank=True, null=True) # This field type is a guess. class Meta: dbtable = 'mallets' and I perform the following query on Django 3.2 sheer = ExpressionWrapper((F('issue') / F('id')), outputfield=FloatField()) lacquer = ExpressionWrapper(Avg(F('sheer'), outputfield=FloatField()), outputfield=TextField()) q = ('default') ret = q.annotate(sheer=sheer).values('sheer').annotate(lacquer=Sum(F('believer'))).orderby('sheer').first() Django however throws the following exception Traceback (most recent call last): File "", line 25, in <moduleret2 = ret1.annotate(sheer=sheer).values('sheer').annotate(lacquer=Sum('believer')).orderby('sheer').first() File "", line 678, in first for obj in (self if self.ordered else self.orderby('pk'))[:1]: File "", line 287, in iter self.fetchall() File "", line 1305, in fetchall self.resultcache = list(self.iterableclass(self)) File "", line 111, in iter for row in compiler.resultsiter(chunkedfetch=self.chunkedfetch, chunksize=self.chunksize): File "", line 1113, in resultsiter results = self.executesql(MULTI, chunkedfetch=chunkedfetch, chunksize=chunksize) File "", line 1148, in executesql sql, params = () File "", line 498, in assql extraselect, orderby, groupby = self.presqlsetup() File "", line 60, in presqlsetup groupby = self.getgroupby( + extraselect, orderby) File "", line 142, in getgroupby sql, params = expr.selectformat(self, sql, params) File "", line 388, in selectformat if hasattr(self.outputfield, 'selectformat'): File "", line 48, in get res = [] = (instance) File "", line 269, in outputfield outputfield = self.resolveoutputfield() File "", line 309, in resolveoutputfield , Expression contains mixed types: IntegerField, AutoField. You must set output_field. Note that when I run the query above on Django 3.0.8, this query runs as expected. So is this a regression in Django 3.2?

return [self.expression]      def get_group_by_cols(self, alias=None):        return self.expression.get_group_by_cols(alias=alias)        expression = self.expression.copy()        expression.output_field = self.output_field        return expression.get_group_by_cols(alias=alias)      def as_sql(self, compiler, connection):         return self.expression.as_sql(compiler, connection)


Question: Support nested relations in FilteredRelation's condition Description As the documentation explains, FilteredRelation's condition do not support nested relations: Restaurant.objects.annotate( ... pizzaswithtoppingsstartswithn=FilteredRelation( ... 'pizzastoppings', ... condition=Q(pizzastoppingsnamestartswith='n'), ... ), ... ) Traceback (most recent call last): ... ValueError: FilteredRelation's condition doesn't support nested relations (got 'pizzastoppingsname__startswith'). It would be great to support nested relations in FilteredRelation's condition (I encountered this limitation multiple times recently).

def add_filtered_relation(self, filtered_relation, alias):         filtered_relation.alias = alias         lookups = dict(get_children_from_q(filtered_relation.condition))        for lookup in chain((filtered_relation.relation_name,), lookups):            lookup_parts, field_parts, _ = self.solve_lookup_type(lookup)        relation_lookup_parts, relation_field_parts, _ = self.solve_lookup_type(filtered_relation.relation_name)        if relation_lookup_parts:            raise ValueError(                "FilteredRelation's relation_name cannot contain lookups "                "(got %r)." % filtered_relation.relation_name            )        for lookup in chain(lookups):            lookup_parts, lookup_field_parts, _ = self.solve_lookup_type(lookup)             shift = 2 if not lookup_parts else 1            if len(field_parts) > (shift + len(lookup_parts)):                raise ValueError(                    "FilteredRelation's condition doesn't support nested "                    "relations (got %r)." % lookup                )            lookup_field_path = lookup_field_parts[:-shift]            for idx, lookup_field_part in enumerate(lookup_field_path):                if len(relation_field_parts) > idx:                    if relation_field_parts[idx] != lookup_field_part:                        raise ValueError(                            "FilteredRelation's condition doesn't support "                            "relations outside the %r (got %r)."                            % (filtered_relation.relation_name, lookup)                        )                else:                    raise ValueError(                        "FilteredRelation's condition doesn't support nested "                        "relations deeper than the relation_name (got %r for "                        "%r)." % (lookup, filtered_relation.relation_name)                    )         self._filtered_relations[filtered_relation.alias] = filtered_relation      def names_to_path(self, names, opts, allow_many=True, fail_on_missing=False):


Question: Support nested relations in FilteredRelation's condition Description As the documentation explains, FilteredRelation's condition do not support nested relations: Restaurant.objects.annotate( ... pizzaswithtoppingsstartswithn=FilteredRelation( ... 'pizzastoppings', ... condition=Q(pizzastoppingsnamestartswith='n'), ... ), ... ) Traceback (most recent call last): ... ValueError: FilteredRelation's condition doesn't support nested relations (got 'pizzastoppingsname__startswith'). It would be great to support nested relations in FilteredRelation's condition (I encountered this limitation multiple times recently).

field = self.annotation_select[name].output_field                 elif name in self._filtered_relations and pos == 0:                     filtered_relation = self._filtered_relations[name]                    field = opts.get_field(filtered_relation.relation_name)                    if LOOKUP_SEP in filtered_relation.relation_name:                        parts = filtered_relation.relation_name.split(LOOKUP_SEP)                        filtered_relation_path, field, _, _ = self.names_to_path(                            parts, opts, allow_many, fail_on_missing,                        )                        path.extend(filtered_relation_path[:-1])                    else:                        field = opts.get_field(filtered_relation.relation_name)             if field is not None:                 # Fields that contain one-to-many relations with a generic                 # model (like a GenericForeignKey) cannot generate reverse


Question: Emails name over 75 characters are incompatible with the latest versions of python. Description In the process of sending an email the addresses is sanatized: =def sanitizeaddress(addr, encoding) The Name portion is encoded via the Header class which will introduce newlines at 75 characters. Unfortunately the most recent python security update no longer allows that to happen. So when Address(nm, addrspec=addr) is called in sanitize_address a new error is raised from the Python Standard library. The update to python can be found here:  Essentially Django can no longer send emails with names longer then 75 chracters.

from email.mime.message import MIMEMessage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMETextfrom email.utils import formatdate, getaddresses, make_msgidfrom email.utils import formataddr, formatdate, getaddresses, make_msgid from io import BytesIO, StringIO from pathlib import Path


Question: Emails name over 75 characters are incompatible with the latest versions of python. Description In the process of sending an email the addresses is sanatized: =def sanitizeaddress(addr, encoding) The Name portion is encoded via the Header class which will introduce newlines at 75 characters. Unfortunately the most recent python security update no longer allows that to happen. So when Address(nm, addrspec=addr) is called in sanitize_address a new error is raised from the Python Standard library. The update to python can be found here:  Essentially Django can no longer send emails with names longer then 75 chracters.

nm, address = addr         localpart, domain = address.rsplit('@', 1)     nm = Header(nm, encoding).encode()    address_parts = nm + localpart + domain    if '\n' in address_parts or '\r' in address_parts:        raise ValueError('Invalid address; address parts cannot contain newlines.')     # Avoid UTF-8 encode, if it's possible.    try:        nm.encode('ascii')        nm = Header(nm).encode()    except UnicodeEncodeError:        nm = Header(nm, encoding).encode()     try:         localpart.encode('ascii')     except UnicodeEncodeError:         localpart = Header(localpart, encoding).encode()     domain = punycode(domain)     parsed_address = Address(nm, username=localpart, domain=domain)    return str(parsed_address)    parsed_address = Address(username=localpart, domain=domain)    return formataddr((nm, parsed_address.addr_spec))   class MIMEMixin:


Question: HttpResponse.deletecookie() should preserve cookie's samesite. Description We noticed we were getting this warning message from Firefox: 'Cookie “messages” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read ' We are getting this from the messages system but it doesn't look like an issue with the messages app. Here is the cookie header for messages on the POST: Set-Cookie: messages=(... encoded message text ...); HttpOnly; Path=/; SameSite=Lax This has SameSite set. But the POST returns a 304 and the following GET's cookie header is this: Set-Cookie: messages=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/ This looks like it is just expiring the cookie so the browser will delete it. As we were digging in to what might be causing this we noticed that messages is using the response's deletecookie method to expire the cookie if there is no message data. HttpResponseBase's deletecookie method doesn't seem like it setting the Samesite setting on Set-Cookie headers. It also is only setting 'Secure' if the cookie's key begins with 'Secure' or 'Host'. Chrome and Firefox will soon begin ignoring Set-Cookie headers with Samesite=None that aren't marked 'Secure'. This could result in Chrome and Firefox ignoring all cookies deleted through HttpResponseBase's deletecookie method if the cookie key does not start with 'Secure' or 'Host'. For testing I modified deletecookie to look like this: def deletecookie(self, key, path='/', domain=None): # Most browsers ignore the Set-Cookie header if the cookie name starts # with Host- or Secure- and the cookie doesn't use the secure flag. self.setcookie( key, maxage=0, path=path, expires='Thu, 01 Jan 1970 00:00:00 GMT', domain=domain if domain is not None else settings.SESSIONCOOKIEDOMAIN, secure=settings.SESSIONCOOKIESECURE or key.startswith(('Secure-', 'Host-')), httponly=settings.SESSIONCOOKIEHTTPONLY or None, samesite=settings.SESSIONCOOKIESAMESITE, ) Definitely wouldn't want to use the session cookie settings for everything but changing this stopped the warnings from coming in on Firefox. I copied the kwargs from the messages code. Thought this might be worth a report.

samesite=settings.SESSION_COOKIE_SAMESITE,             )         else:            response.delete_cookie(self.cookie_name, domain=settings.SESSION_COOKIE_DOMAIN)            response.delete_cookie(                self.cookie_name,                domain=settings.SESSION_COOKIE_DOMAIN,                samesite=settings.SESSION_COOKIE_SAMESITE,            )      def _store(self, messages, response, remove_oldest=True, *args, **kwargs):         """diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py-- a/django/contrib/sessions/middleware.py++ b/django/contrib/sessions/middleware.py


Question: HttpResponse.deletecookie() should preserve cookie's samesite. Description We noticed we were getting this warning message from Firefox: 'Cookie “messages” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read ' We are getting this from the messages system but it doesn't look like an issue with the messages app. Here is the cookie header for messages on the POST: Set-Cookie: messages=(... encoded message text ...); HttpOnly; Path=/; SameSite=Lax This has SameSite set. But the POST returns a 304 and the following GET's cookie header is this: Set-Cookie: messages=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/ This looks like it is just expiring the cookie so the browser will delete it. As we were digging in to what might be causing this we noticed that messages is using the response's deletecookie method to expire the cookie if there is no message data. HttpResponseBase's deletecookie method doesn't seem like it setting the Samesite setting on Set-Cookie headers. It also is only setting 'Secure' if the cookie's key begins with 'Secure' or 'Host'. Chrome and Firefox will soon begin ignoring Set-Cookie headers with Samesite=None that aren't marked 'Secure'. This could result in Chrome and Firefox ignoring all cookies deleted through HttpResponseBase's deletecookie method if the cookie key does not start with 'Secure' or 'Host'. For testing I modified deletecookie to look like this: def deletecookie(self, key, path='/', domain=None): # Most browsers ignore the Set-Cookie header if the cookie name starts # with Host- or Secure- and the cookie doesn't use the secure flag. self.setcookie( key, maxage=0, path=path, expires='Thu, 01 Jan 1970 00:00:00 GMT', domain=domain if domain is not None else settings.SESSIONCOOKIEDOMAIN, secure=settings.SESSIONCOOKIESECURE or key.startswith(('Secure-', 'Host-')), httponly=settings.SESSIONCOOKIEHTTPONLY or None, samesite=settings.SESSIONCOOKIESAMESITE, ) Definitely wouldn't want to use the session cookie settings for everything but changing this stopped the warnings from coming in on Firefox. I copied the kwargs from the messages code. Thought this might be worth a report.

settings.SESSION_COOKIE_NAME,                 path=settings.SESSION_COOKIE_PATH,                 domain=settings.SESSION_COOKIE_DOMAIN,                samesite=settings.SESSION_COOKIE_SAMESITE,             )             patch_vary_headers(response, ('Cookie',))         else:diff --git a/django/http/response.py b/django/http/response.py-- a/django/http/response.py++ b/django/http/response.py


Question: HttpResponse.deletecookie() should preserve cookie's samesite. Description We noticed we were getting this warning message from Firefox: 'Cookie “messages” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read ' We are getting this from the messages system but it doesn't look like an issue with the messages app. Here is the cookie header for messages on the POST: Set-Cookie: messages=(... encoded message text ...); HttpOnly; Path=/; SameSite=Lax This has SameSite set. But the POST returns a 304 and the following GET's cookie header is this: Set-Cookie: messages=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/ This looks like it is just expiring the cookie so the browser will delete it. As we were digging in to what might be causing this we noticed that messages is using the response's deletecookie method to expire the cookie if there is no message data. HttpResponseBase's deletecookie method doesn't seem like it setting the Samesite setting on Set-Cookie headers. It also is only setting 'Secure' if the cookie's key begins with 'Secure' or 'Host'. Chrome and Firefox will soon begin ignoring Set-Cookie headers with Samesite=None that aren't marked 'Secure'. This could result in Chrome and Firefox ignoring all cookies deleted through HttpResponseBase's deletecookie method if the cookie key does not start with 'Secure' or 'Host'. For testing I modified deletecookie to look like this: def deletecookie(self, key, path='/', domain=None): # Most browsers ignore the Set-Cookie header if the cookie name starts # with Host- or Secure- and the cookie doesn't use the secure flag. self.setcookie( key, maxage=0, path=path, expires='Thu, 01 Jan 1970 00:00:00 GMT', domain=domain if domain is not None else settings.SESSIONCOOKIEDOMAIN, secure=settings.SESSIONCOOKIESECURE or key.startswith(('Secure-', 'Host-')), httponly=settings.SESSIONCOOKIEHTTPONLY or None, samesite=settings.SESSIONCOOKIESAMESITE, ) Definitely wouldn't want to use the session cookie settings for everything but changing this stopped the warnings from coming in on Firefox. I copied the kwargs from the messages code. Thought this might be worth a report.

value = signing.get_cookie_signer(salt=key + salt).sign(value)         return self.set_cookie(key, value, **kwargs)     def delete_cookie(self, key, path='/', domain=None):        # Most browsers ignore the Set-Cookie header if the cookie name starts        # with __Host- or __Secure- and the cookie doesn't use the secure flag.        secure = key.startswith(('__Secure-', '__Host-'))    def delete_cookie(self, key, path='/', domain=None, samesite=None):        # Browsers can ignore the Set-Cookie header if the cookie doesn't use        # the secure flag and:        # - the cookie name starts with "__Host-" or "__Secure-", or        # - the samesite is "none".        secure = (            key.startswith(('__Secure-', '__Host-')) or            (samesite and samesite.lower() == 'none')        )         self.set_cookie(             key, max_age=0, path=path, domain=domain, secure=secure,            expires='Thu, 01 Jan 1970 00:00:00 GMT',            expires='Thu, 01 Jan 1970 00:00:00 GMT', samesite=samesite,         )      # Common methods used by subclasses


Question: HttpResponse.deletecookie() should preserve cookie's samesite. Description We noticed we were getting this warning message from Firefox: 'Cookie “messages” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read ' We are getting this from the messages system but it doesn't look like an issue with the messages app. Here is the cookie header for messages on the POST: Set-Cookie: messages=(... encoded message text ...); HttpOnly; Path=/; SameSite=Lax This has SameSite set. But the POST returns a 304 and the following GET's cookie header is this: Set-Cookie: messages=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/ This looks like it is just expiring the cookie so the browser will delete it. As we were digging in to what might be causing this we noticed that messages is using the response's deletecookie method to expire the cookie if there is no message data. HttpResponseBase's deletecookie method doesn't seem like it setting the Samesite setting on Set-Cookie headers. It also is only setting 'Secure' if the cookie's key begins with 'Secure' or 'Host'. Chrome and Firefox will soon begin ignoring Set-Cookie headers with Samesite=None that aren't marked 'Secure'. This could result in Chrome and Firefox ignoring all cookies deleted through HttpResponseBase's deletecookie method if the cookie key does not start with 'Secure' or 'Host'. For testing I modified deletecookie to look like this: def deletecookie(self, key, path='/', domain=None): # Most browsers ignore the Set-Cookie header if the cookie name starts # with Host- or Secure- and the cookie doesn't use the secure flag. self.setcookie( key, maxage=0, path=path, expires='Thu, 01 Jan 1970 00:00:00 GMT', domain=domain if domain is not None else settings.SESSIONCOOKIEDOMAIN, secure=settings.SESSIONCOOKIESECURE or key.startswith(('Secure-', 'Host-')), httponly=settings.SESSIONCOOKIEHTTPONLY or None, samesite=settings.SESSIONCOOKIESAMESITE, ) Definitely wouldn't want to use the session cookie settings for everything but changing this stopped the warnings from coming in on Firefox. I copied the kwargs from the messages code. Thought this might be worth a report.


Question: HttpResponse.deletecookie() should preserve cookie's samesite. Description We noticed we were getting this warning message from Firefox: 'Cookie “messages” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read ' We are getting this from the messages system but it doesn't look like an issue with the messages app. Here is the cookie header for messages on the POST: Set-Cookie: messages=(... encoded message text ...); HttpOnly; Path=/; SameSite=Lax This has SameSite set. But the POST returns a 304 and the following GET's cookie header is this: Set-Cookie: messages=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/ This looks like it is just expiring the cookie so the browser will delete it. As we were digging in to what might be causing this we noticed that messages is using the response's deletecookie method to expire the cookie if there is no message data. HttpResponseBase's deletecookie method doesn't seem like it setting the Samesite setting on Set-Cookie headers. It also is only setting 'Secure' if the cookie's key begins with 'Secure' or 'Host'. Chrome and Firefox will soon begin ignoring Set-Cookie headers with Samesite=None that aren't marked 'Secure'. This could result in Chrome and Firefox ignoring all cookies deleted through HttpResponseBase's deletecookie method if the cookie key does not start with 'Secure' or 'Host'. For testing I modified deletecookie to look like this: def deletecookie(self, key, path='/', domain=None): # Most browsers ignore the Set-Cookie header if the cookie name starts # with Host- or Secure- and the cookie doesn't use the secure flag. self.setcookie( key, maxage=0, path=path, expires='Thu, 01 Jan 1970 00:00:00 GMT', domain=domain if domain is not None else settings.SESSIONCOOKIEDOMAIN, secure=settings.SESSIONCOOKIESECURE or key.startswith(('Secure-', 'Host-')), httponly=settings.SESSIONCOOKIEHTTPONLY or None, samesite=settings.SESSIONCOOKIESAMESITE, ) Definitely wouldn't want to use the session cookie settings for everything but changing this stopped the warnings from coming in on Firefox. I copied the kwargs from the messages code. Thought this might be worth a report.


Question: HttpResponse.deletecookie() should preserve cookie's samesite. Description We noticed we were getting this warning message from Firefox: 'Cookie “messages” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read ' We are getting this from the messages system but it doesn't look like an issue with the messages app. Here is the cookie header for messages on the POST: Set-Cookie: messages=(... encoded message text ...); HttpOnly; Path=/; SameSite=Lax This has SameSite set. But the POST returns a 304 and the following GET's cookie header is this: Set-Cookie: messages=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/ This looks like it is just expiring the cookie so the browser will delete it. As we were digging in to what might be causing this we noticed that messages is using the response's deletecookie method to expire the cookie if there is no message data. HttpResponseBase's deletecookie method doesn't seem like it setting the Samesite setting on Set-Cookie headers. It also is only setting 'Secure' if the cookie's key begins with 'Secure' or 'Host'. Chrome and Firefox will soon begin ignoring Set-Cookie headers with Samesite=None that aren't marked 'Secure'. This could result in Chrome and Firefox ignoring all cookies deleted through HttpResponseBase's deletecookie method if the cookie key does not start with 'Secure' or 'Host'. For testing I modified deletecookie to look like this: def deletecookie(self, key, path='/', domain=None): # Most browsers ignore the Set-Cookie header if the cookie name starts # with Host- or Secure- and the cookie doesn't use the secure flag. self.setcookie( key, maxage=0, path=path, expires='Thu, 01 Jan 1970 00:00:00 GMT', domain=domain if domain is not None else settings.SESSIONCOOKIEDOMAIN, secure=settings.SESSIONCOOKIESECURE or key.startswith(('Secure-', 'Host-')), httponly=settings.SESSIONCOOKIEHTTPONLY or None, samesite=settings.SESSIONCOOKIESAMESITE, ) Definitely wouldn't want to use the session cookie settings for everything but changing this stopped the warnings from coming in on Firefox. I copied the kwargs from the messages code. Thought this might be worth a report.

value = signing.get_cookie_signer(salt=key + salt).sign(value)         return self.set_cookie(key, value, **kwargs)     def delete_cookie(self, key, path='/', domain=None):    def delete_cookie(self, key, path='/', domain=None, samesite=None):         # Most browsers ignore the Set-Cookie header if the cookie name starts         # with __Host- or __Secure- and the cookie doesn't use the secure flag.         secure = key.startswith(('__Secure-', '__Host-'))         self.set_cookie(             key, max_age=0, path=path, domain=domain, secure=secure,            expires='Thu, 01 Jan 1970 00:00:00 GMT',            expires='Thu, 01 Jan 1970 00:00:00 GMT', samesite=samesite,         )      # Common methods used by subclasses


Question: Allow migrations directories without files Description (last modified by Tim Graham) Background: In python 3 a package with no is implicitly a namespace package, so it has no file attribute. The migrate command currently checks for existence of a file attribute on the migrations package. This check was introduced in , because the file attribute was used in migration file discovery. However, in migration file discovery was changed to use pkgutil.itermodules (), instead of direct filesystem access. pkgutil. itermodules() uses the package's path list, which exists on implicit namespace packages. As a result, the file check is no longer needed, and in fact prevents migrate from working on namespace packages (implicit or otherwise). Related work:

continue                 raise             else:<ins>                # Empty directories are namespaces.                # getattr() needed on PY36 and older (replace w/attribute access).                if getattr(module, '__file__', None) is None:                    self.unmigrated_apps.add(app_config.label)                    continue</ins>                 # Module is not a package (e.g. migrations.py).                 if not hasattr(module, '__path__'):                     self.unmigrated_apps.add(app_config.label)


Question: Allow migrations directories without files Description (last modified by Tim Graham) Background: In python 3 a package with no is implicitly a namespace package, so it has no file attribute. The migrate command currently checks for existence of a file attribute on the migrations package. This check was introduced in , because the file attribute was used in migration file discovery. However, in migration file discovery was changed to use pkgutil.itermodules (), instead of direct filesystem access. pkgutil. itermodules() uses the package's path list, which exists on implicit namespace packages. As a result, the file check is no longer needed, and in fact prevents migrate from working on namespace packages (implicit or otherwise). Related work:

# Force a reload if it's already loaded (tests need this)                 if was_loaded:                     reload(module)            self.migrated_apps.add(app_config.label)             migration_names = {                 name for _, name, is_pkg in pkgutil.iter_modules(module.__path__)                 if not is_pkg and name[0] not in '_~'             }            if migration_names or self.ignore_no_migrations:                self.migrated_apps.add(app_config.label)            else:                self.unmigrated_apps.add(app_config.label)             # Load migrations             for migration_name in migration_names:                 migration_path = '%s.%s' % (module_name, migration_name)


Question: Allow ValidationErrors to equal each other when created identically Description (last modified by kamni) Currently ValidationErrors () that have identical messages don't equal each other, which is counter-intuitive, and can make certain kinds of testing more complicated. Please add an eq method that allows two ValidationErrors to be compared. Ideally, this would be more than just a simple self.messages == other.messages. It would be most helpful if the comparison were independent of the order in which errors were raised in a field or in nonfielderrors.

""" Global Django exception and warning classes. """<ins>import operatorfrom django.utils.hashable import make_hashable</ins>   class FieldDoesNotExist(Exception):


Question: Allow ValidationErrors to equal each other when created identically Description (last modified by kamni) Currently ValidationErrors () that have identical messages don't equal each other, which is counter-intuitive, and can make certain kinds of testing more complicated. Please add an eq method that allows two ValidationErrors to be compared. Ideally, this would be more than just a simple self.messages == other.messages. It would be most helpful if the comparison were independent of the order in which errors were raised in a field or in nonfielderrors.

def __repr__(self):         return 'ValidationError(%s)' % self <ins>    def __eq__(self, other):        if not isinstance(other, ValidationError):            return NotImplemented        return hash(self) == hash(other)    def __hash__(self):        # Ignore params and messages ordering.        if hasattr(self, 'message'):            return hash((                self.message,                self.code,                tuple(sorted(make_hashable(self.params))) if self.params else None,            ))        if hasattr(self, 'error_dict'):            return hash(tuple(sorted(make_hashable(self.error_dict))))        return hash(tuple(sorted(self.error_list, key=operator.attrgetter('message'))))</ins>  class EmptyResultSet(Exception):     """A database query predicate is impossible."""


Question: Add support for itemcomments to syndication framework Description Add comments argument to feed.additem() in so that itemcomments can be defined directly without having to take the detour via itemextra_kwargs . Additionally, comments is already explicitly mentioned in the feedparser, but not implemented in the view.

author_name=author_name,                 author_email=author_email,                 author_link=author_link,<ins>                comments=self._get_dynamic_attr('item_comments', item),</ins>                 categories=self._get_dynamic_attr('item_categories', item),                 item_copyright=self._get_dynamic_attr('item_copyright', item),                 **self.item_extra_kwargs(item)


Question: The attribute of image fields doesn't point to concrete model. Description In Django 3.1 and before, one could use the model attribute of image fields to find the concrete model the image field belongs to. This isn't possible in 3.2 anymore, and I bisected the change to the fix of . I found this while investigating a CI failure of django-imagefield https://travis- I'm not sure whether this is a bug or whether it is an intentional change. If it is the later, is there an alternative to find the concrete model an image field belongs to? I'm classifying this as a bug because the change made model and field introspection harder than it was before. Also, since behavior changed may possibly not be classified as a cleanup/optimization anymore...

file.save(file.name, file.file, save=False)         return file <ins>    def contribute_to_class(self, cls, name, **kwargs):        super().contribute_to_class(cls, name, **kwargs)        setattr(cls, self.attname, self.descriptor_class(self))</ins>     def generate_filename(self, instance, filename):         """         Apply (if callable) or prepend (if a string) upload_to to the filename,


Question: RenameField with dbcolumn should be a noop. Description (last modified by Iuri de Silvio) RenameField with dbcolumn should be a noop because it is only the Django column that changed, the database still have the same db_column.

If `strict` is True, raise errors if the old column does not match         `old_field` precisely.         """<ins>        if not self._field_should_be_altered(old_field, new_field):            return</ins>         # Ensure this field is even column-based         old_db_params = old_field.db_parameters(connection=self.connection)         old_type = old_db_params['type']


Question: RenameField with dbcolumn should be a noop. Description (last modified by Iuri de Silvio) RenameField with dbcolumn should be a noop because it is only the Django column that changed, the database still have the same db_column.

output.append(self._create_index_sql(model, [field]))         return output     def _field_should_be_altered(self, old_field, new_field):        # Don't alter when changing only a field name.        return (            old_field.column != new_field.column or            old_field.deconstruct()[1:] != new_field.deconstruct()[1:]        )     def _field_should_be_indexed(self, model, field):         return field.db_index and not field.unique diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py-- a/django/db/backends/sqlite3/schema.py++ b/django/db/backends/sqlite3/schema.py


Question: RenameField with dbcolumn should be a noop. Description (last modified by Iuri de Silvio) RenameField with dbcolumn should be a noop because it is only the Django column that changed, the database still have the same db_column.

super().alter_db_table(model, old_db_table, new_db_table)      def alter_field(self, model, old_field, new_field, strict=False):<ins>        if not self._field_should_be_altered(old_field, new_field):            return</ins>         old_field_name = old_field.name         table_name = model._meta.db_table         _, old_column_name = old_field.get_attname_column()


Question: AlterField with dbcolumn addition should be a noop. Description (last modified by Iuri de Silvio) When I change pink = models.Integer(default=0) to pink = models.Integer(default=0, dbcolumn="pink") the migration drop/create the same constraints when it is an FK or even reconstruct the table (SQLite), but nothing really changed. The constraint drop/create is a blocking operation for PostgreSQL, so it is an undesirable and unexpected behavior.

return output      def _field_should_be_altered(self, old_field, new_field):        # Don't alter when changing only a field name.        _, old_path, old_args, old_kwargs = old_field.deconstruct()        _, new_path, new_args, new_kwargs = new_field.deconstruct()        # Don't alter when:        # - changing only a field name        # - adding only a db_column and the column name is not changed        old_kwargs.pop('db_column', None)        new_kwargs.pop('db_column', None)         return (             old_field.column != new_field.column or            old_field.deconstruct()[1:] != new_field.deconstruct()[1:]            (old_path, old_args, old_kwargs) != (new_path, new_args, new_kwargs)         )      def _field_should_be_indexed(self, model, field):


Question: Change Settings to raise ImproperlyConfigured on SECRETKEY; not initialization Description Since ticket , initializing settings without a SECRETKEY raises a an ImproperlyConfigured during settings initialization. Instead, I think the error should be raised when the setting is accessed as Settings.SECRETKEY. My use case, my project has a number of management commands that run in a non-production, minimally configured environment. These management commands do not require SECRETKEY, however, the environment is forced to provide one. As a workaround this environment has been generating a random secret key each run. If Django were to instead raise the error on SECRET_KEY access, this workaround would not be necessary.

# This is done here for performance reasons so the modified value is cached.         if name in {'MEDIA_URL', 'STATIC_URL'} and val is not None:             val = self._add_script_prefix(val)<ins>        elif name == 'SECRET_KEY' and not val:            raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")</ins>          self.__dict__[name] = val         return val


Question: Change Settings to raise ImproperlyConfigured on SECRETKEY; not initialization Description Since ticket , initializing settings without a SECRETKEY raises a an ImproperlyConfigured during settings initialization. Instead, I think the error should be raised when the setting is accessed as Settings.SECRETKEY. My use case, my project has a number of management commands that run in a non-production, minimally configured environment. These management commands do not require SECRETKEY, however, the environment is forced to provide one. As a workaround this environment has been generating a random secret key each run. If Django were to instead raise the error on SECRET_KEY access, this workaround would not be necessary.

setattr(self, setting, setting_value)                 self._explicit_settings.add(setting)         if not self.SECRET_KEY:            raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")         if self.is_overridden('PASSWORD_RESET_TIMEOUT_DAYS'):             if self.is_overridden('PASSWORD_RESET_TIMEOUT'):                 raise ImproperlyConfigured(diff --git a/django/contrib/auth/tokens.py b/django/contrib/auth/tokens.py-- a/django/contrib/auth/tokens.py++ b/django/contrib/auth/tokens.py


Question: Change Settings to raise ImproperlyConfigured on SECRETKEY; not initialization Description Since ticket , initializing settings without a SECRETKEY raises a an ImproperlyConfigured during settings initialization. Instead, I think the error should be raised when the setting is accessed as Settings.SECRETKEY. My use case, my project has a number of management commands that run in a non-production, minimally configured environment. These management commands do not require SECRETKEY, however, the environment is forced to provide one. As a workaround this environment has been generating a random secret key each run. If Django were to instead raise the error on SECRET_KEY access, this workaround would not be necessary.

"""     key_salt = "django.contrib.auth.tokens.PasswordResetTokenGenerator"     algorithm = 'sha256'    secret = settings.SECRET_KEY    secret = None    def __init__(self):        self.secret = self.secret or settings.SECRET_KEY      def make_token(self, user):         """diff --git a/django/core/checks/security/base.py b/django/core/checks/security/base.py-- a/django/core/checks/security/base.py++ b/django/core/checks/security/base.py


Question: Change Settings to raise ImproperlyConfigured on SECRETKEY; not initialization Description Since ticket , initializing settings without a SECRETKEY raises a an ImproperlyConfigured during settings initialization. Instead, I think the error should be raised when the setting is accessed as Settings.SECRETKEY. My use case, my project has a number of management commands that run in a non-production, minimally configured environment. These management commands do not require SECRETKEY, however, the environment is forced to provide one. As a workaround this environment has been generating a random secret key each run. If Django were to instead raise the error on SECRET_KEY access, this workaround would not be necessary.

from django.conf import settings<ins>from django.core.exceptions import ImproperlyConfigured</ins>  from .. import Error, Tags, Warning, register


Question: Change Settings to raise ImproperlyConfigured on SECRETKEY; not initialization Description Since ticket , initializing settings without a SECRETKEY raises a an ImproperlyConfigured during settings initialization. Instead, I think the error should be raised when the setting is accessed as Settings.SECRETKEY. My use case, my project has a number of management commands that run in a non-production, minimally configured environment. These management commands do not require SECRETKEY, however, the environment is forced to provide one. As a workaround this environment has been generating a random secret key each run. If Django were to instead raise the error on SECRET_KEY access, this workaround would not be necessary.

@register(Tags.security, deploy=True) def check_secret_key(app_configs, **kwargs):    passed_check = (        getattr(settings, 'SECRET_KEY', None) and        len(set(settings.SECRET_KEY)) >= SECRET_KEY_MIN_UNIQUE_CHARACTERS and        len(settings.SECRET_KEY) >= SECRET_KEY_MIN_LENGTH    )    try:        secret_key = settings.SECRET_KEY    except (ImproperlyConfigured, AttributeError):        passed_check = False    else:        passed_check = (            len(set(secret_key)) >= SECRET_KEY_MIN_UNIQUE_CHARACTERS and            len(secret_key) >= SECRET_KEY_MIN_LENGTH        )     return [] if passed_check else [W009]


Question: JSONField's contains and containedby lookups don't work with nested values on SQLite. Description SQLite doesn't provide a native way for testing containment of JSONField. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object". I'm not sure if it's feasible to emulate it in Python. Some (not really complicated) examples that don't work: diff --git index .. --- +++ -449,9 +449,14 class TestQuerying(TestCase): tests = [ ({}, [2:5] + [6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [[7]]), ({'baz': {'a': 'b'}}, [[7]]), ({'baz': {'c': 'd'}}, [[7]]), ({'k': True, 'l': False}, [[6]]), ({'d': ['e', {'f': 'g'}]}, [[4]]), ({'d': ['e']}, [[4]]), ([1, [2]], [[5]]), ([1], [[5]]), ([[2]], [[5]]), ({'n': [None]}, [[4]]), ({'j': None}, [[4]]), ]

has_native_json_field = False     # Does the backend use PostgreSQL-style JSON operators like '->'?     has_json_operators = False    # Does the backend support __contains and __contained_by lookups for    # a JSONField?    supports_json_field_contains = True      def __init__(self, connection):         self.connection = connectiondiff --git a/django/db/backends/oracle/features.py b/django/db/backends/oracle/features.py-- a/django/db/backends/oracle/features.py++ b/django/db/backends/oracle/features.py


Question: JSONField's contains and containedby lookups don't work with nested values on SQLite. Description SQLite doesn't provide a native way for testing containment of JSONField. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object". I'm not sure if it's feasible to emulate it in Python. Some (not really complicated) examples that don't work: diff --git index .. --- +++ -449,9 +449,14 class TestQuerying(TestCase): tests = [ ({}, [2:5] + [6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [[7]]), ({'baz': {'a': 'b'}}, [[7]]), ({'baz': {'c': 'd'}}, [[7]]), ({'k': True, 'l': False}, [[6]]), ({'d': ['e', {'f': 'g'}]}, [[4]]), ({'d': ['e']}, [[4]]), ([1, [2]], [[5]]), ([1], [[5]]), ([[2]], [[5]]), ({'n': [None]}, [[4]]), ({'j': None}, [[4]]), ]

allows_multiple_constraints_on_same_fields = False     supports_boolean_expr_in_select_clause = False     supports_primitives_in_json_field = False    supports_json_field_contains = False      @cached_property     def introspected_field_types(self):diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py-- a/django/db/backends/sqlite3/base.py++ b/django/db/backends/sqlite3/base.py


Question: JSONField's contains and containedby lookups don't work with nested values on SQLite. Description SQLite doesn't provide a native way for testing containment of JSONField. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object". I'm not sure if it's feasible to emulate it in Python. Some (not really complicated) examples that don't work: diff --git index .. --- +++ -449,9 +449,14 class TestQuerying(TestCase): tests = [ ({}, [2:5] + [6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [[7]]), ({'baz': {'a': 'b'}}, [[7]]), ({'baz': {'c': 'd'}}, [[7]]), ({'k': True, 'l': False}, [[6]]), ({'d': ['e', {'f': 'g'}]}, [[4]]), ({'d': ['e']}, [[4]]), ([1, [2]], [[5]]), ([1], [[5]]), ([[2]], [[5]]), ({'n': [None]}, [[4]]), ({'j': None}, [[4]]), ]

import decimal import functools import hashlib<del>import json</del> import math import operator import re


Question: JSONField's contains and containedby lookups don't work with nested values on SQLite. Description SQLite doesn't provide a native way for testing containment of JSONField. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object". I'm not sure if it's feasible to emulate it in Python. Some (not really complicated) examples that don't work: diff --git index .. --- +++ -449,9 +449,14 class TestQuerying(TestCase): tests = [ ({}, [2:5] + [6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [[7]]), ({'baz': {'a': 'b'}}, [[7]]), ({'baz': {'c': 'd'}}, [[7]]), ({'k': True, 'l': False}, [[6]]), ({'d': ['e', {'f': 'g'}]}, [[4]]), ({'d': ['e']}, [[4]]), ([1, [2]], [[5]]), ([1], [[5]]), ([[2]], [[5]]), ({'n': [None]}, [[4]]), ({'j': None}, [[4]]), ]

create_deterministic_function('DEGREES', 1, none_guard(math.degrees))         create_deterministic_function('EXP', 1, none_guard(math.exp))         create_deterministic_function('FLOOR', 1, none_guard(math.floor))<del>        create_deterministic_function('JSON_CONTAINS', 2, _sqlite_json_contains)</del>         create_deterministic_function('LN', 1, none_guard(math.log))         create_deterministic_function('LOG', 2, none_guard(lambda x, y: math.log(y, x)))         create_deterministic_function('LPAD', 3, _sqlite_lpad)


Question: JSONField's contains and containedby lookups don't work with nested values on SQLite. Description SQLite doesn't provide a native way for testing containment of JSONField. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object". I'm not sure if it's feasible to emulate it in Python. Some (not really complicated) examples that don't work: diff --git index .. --- +++ -449,9 +449,14 class TestQuerying(TestCase): tests = [ ({}, [2:5] + [6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [[7]]), ({'baz': {'a': 'b'}}, [[7]]), ({'baz': {'c': 'd'}}, [[7]]), ({'k': True, 'l': False}, [[6]]), ({'d': ['e', {'f': 'g'}]}, [[4]]), ({'d': ['e']}, [[4]]), ([1, [2]], [[5]]), ([1], [[5]]), ([[2]], [[5]]), ({'n': [None]}, [[4]]), ({'j': None}, [[4]]), ]

@none_guard def _sqlite_rpad(text, length, fill_text):     return (text + fill_text * length)[:length]@none_guarddef _sqlite_json_contains(haystack, needle):    target, candidate = json.loads(haystack), json.loads(needle)    if isinstance(target, dict) and isinstance(candidate, dict):        return target.items() >= candidate.items()    return target == candidatediff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py-- a/django/db/backends/sqlite3/features.py++ b/django/db/backends/sqlite3/features.py


Question: JSONField's contains and containedby lookups don't work with nested values on SQLite. Description SQLite doesn't provide a native way for testing containment of JSONField. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object". I'm not sure if it's feasible to emulate it in Python. Some (not really complicated) examples that don't work: diff --git index .. --- +++ -449,9 +449,14 class TestQuerying(TestCase): tests = [ ({}, [2:5] + [6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [[7]]), ({'baz': {'a': 'b'}}, [[7]]), ({'baz': {'c': 'd'}}, [[7]]), ({'k': True, 'l': False}, [[6]]), ({'d': ['e', {'f': 'g'}]}, [[4]]), ({'d': ['e']}, [[4]]), ([1, [2]], [[5]]), ([1], [[5]]), ([[2]], [[5]]), ({'n': [None]}, [[4]]), ({'j': None}, [[4]]), ]

supports_aggregate_filter_clause = Database.sqlite_version_info >= (3, 30, 1)     supports_order_by_nulls_modifier = Database.sqlite_version_info >= (3, 30, 0)     order_by_nulls_first = True    supports_json_field_contains = False      @cached_property     def supports_atomic_references_rename(self):diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py-- a/django/db/models/fields/json.py++ b/django/db/models/fields/json.py


Question: JSONField's contains and containedby lookups don't work with nested values on SQLite. Description SQLite doesn't provide a native way for testing containment of JSONField. The current implementation works only for basic examples without supporting nested structures and doesn't follow "the general principle that the contained object must match the containing object as to structure and data contents, possibly after discarding some non-matching array elements or object key/value pairs from the containing object". I'm not sure if it's feasible to emulate it in Python. Some (not really complicated) examples that don't work: diff --git index .. --- +++ -449,9 +449,14 class TestQuerying(TestCase): tests = [ ({}, [2:5] + [6:8]), ({'baz': {'a': 'b', 'c': 'd'}}, [[7]]), ({'baz': {'a': 'b'}}, [[7]]), ({'baz': {'c': 'd'}}, [[7]]), ({'k': True, 'l': False}, [[6]]), ({'d': ['e', {'f': 'g'}]}, [[4]]), ({'d': ['e']}, [[4]]), ([1, [2]], [[5]]), ([1], [[5]]), ([[2]], [[5]]), ({'n': [None]}, [[4]]), ({'j': None}, [[4]]), ]

postgres_operator = '@>'      def as_sql(self, compiler, connection):        if not connection.features.supports_json_field_contains:            raise NotSupportedError(                'contains lookup is not supported on this database backend.'            )         lhs, lhs_params = self.process_lhs(compiler, connection)         rhs, rhs_params = self.process_rhs(compiler, connection)         params = tuple(lhs_params) + tuple(rhs_params)         return 'JSON_CONTAINS(%s, %s)' % (lhs, rhs), params     def as_oracle(self, compiler, connection):        raise NotSupportedError('contains lookup is not supported on Oracle.')  class ContainedBy(PostgresOperatorLookup):     lookup_name = 'contained_by'     postgres_operator = '<@'      def as_sql(self, compiler, connection):        if not connection.features.supports_json_field_contains:            raise NotSupportedError(                'contained_by lookup is not supported on this database backend.'            )         lhs, lhs_params = self.process_lhs(compiler, connection)         rhs, rhs_params = self.process_rhs(compiler, connection)         params = tuple(rhs_params) + tuple(lhs_params)         return 'JSON_CONTAINS(%s, %s)' % (rhs, lhs), params     def as_oracle(self, compiler, connection):        raise NotSupportedError('contained_by lookup is not supported on Oracle.')  class HasKeyLookup(PostgresOperatorLookup):     logical_operator = None


Question: Filtering on a field named raises a TypeError Description Filtering on a model with a field named negate raises a TypeError. For example: class Foo(models.Model): negate = models.BooleanField() (negate=True) raises TypeError: filterorexclude() got multiple values for argument 'negate' negate is not documented as a reserved argument for .filter(). I'm currently using .filter(negate_exact=True) as a workaround.

def query(self):         if self._deferred_filter:             negate, args, kwargs = self._deferred_filter            self._filter_or_exclude_inplace(negate, *args, **kwargs)            self._filter_or_exclude_inplace(negate, args, kwargs)             self._deferred_filter = None         return self._query


Question: Filtering on a field named raises a TypeError Description Filtering on a model with a field named negate raises a TypeError. For example: class Foo(models.Model): negate = models.BooleanField() (negate=True) raises TypeError: filterorexclude() got multiple values for argument 'negate' negate is not documented as a reserved argument for .filter(). I'm currently using .filter(negate_exact=True) as a workaround.

set.         """         self._not_support_combined_queries('filter')        return self._filter_or_exclude(False, *args, **kwargs)        return self._filter_or_exclude(False, args, kwargs)      def exclude(self, *args, **kwargs):         """


Question: Filtering on a field named raises a TypeError Description Filtering on a model with a field named negate raises a TypeError. For example: class Foo(models.Model): negate = models.BooleanField() (negate=True) raises TypeError: filterorexclude() got multiple values for argument 'negate' negate is not documented as a reserved argument for .filter(). I'm currently using .filter(negate_exact=True) as a workaround.

set.         """         self._not_support_combined_queries('exclude')        return self._filter_or_exclude(True, *args, **kwargs)        return self._filter_or_exclude(True, args, kwargs)     def _filter_or_exclude(self, negate, *args, **kwargs):    def _filter_or_exclude(self, negate, args, kwargs):         if args or kwargs:             assert not self.query.is_sliced, \                 "Cannot filter a query once a slice has been taken."


Question: Filtering on a field named raises a TypeError Description Filtering on a model with a field named negate raises a TypeError. For example: class Foo(models.Model): negate = models.BooleanField() (negate=True) raises TypeError: filterorexclude() got multiple values for argument 'negate' negate is not documented as a reserved argument for .filter(). I'm currently using .filter(negate_exact=True) as a workaround.

self._defer_next_filter = False             clone._deferred_filter = negate, args, kwargs         else:            clone._filter_or_exclude_inplace(negate, *args, **kwargs)            clone._filter_or_exclude_inplace(negate, args, kwargs)         return clone     def _filter_or_exclude_inplace(self, negate, *args, **kwargs):    def _filter_or_exclude_inplace(self, negate, args, kwargs):         if negate:             self._query.add_q(~Q(*args, **kwargs))         else:


Question: Filtering on a field named raises a TypeError Description Filtering on a model with a field named negate raises a TypeError. For example: class Foo(models.Model): negate = models.BooleanField() (negate=True) raises TypeError: filterorexclude() got multiple values for argument 'negate' negate is not documented as a reserved argument for .filter(). I'm currently using .filter(negate_exact=True) as a workaround.

clone.query.add_q(filter_obj)             return clone         else:            return self._filter_or_exclude(False, **filter_obj)            return self._filter_or_exclude(False, args=(), kwargs=filter_obj)      def _combinator_query(self, combinator, *other_qs, all=False):         # Clone the query to inherit the select list and everything


Question: AlterOrderWithRespectTo() with ForeignKey crash when order is included in Index(). Description class Meta: dbtable = 'lookimage' orderwithrespectto = 'look' indexes = [ models.Index(fields=['look', 'order']), models.Index(fields=['createdat']), models.Index(fields=['updatedat']), ] migrations.CreateModel( name='LookImage', fields=[ ('id', models.AutoField(autocreated=True, primarykey=True, serialize=False, verbosename='ID')), ('look', models.ForeignKey(, relatedname='images', to='posts.Look', verbosename='LOOK')), ('imageurl', models.URLField(blank=True, maxlength=, null=True)), ('image', models.ImageField(maxlength=2000, uploadto='')), ('deleted', models.DateTimeField(editable=False, null=True)), ('createdat', models.DateTimeField(autonowadd=True)), ('updatedat', models.DateTimeField(autonow=True)), ], ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['look', 'order'], name='lookimagelookideaff30idx'), ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['createdat'], name='lookimagecreatedf746cfidx'), ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['updatedat'], name='lookimageupdatedaceaf9idx'), ), migrations.AlterOrderWithRespectTo( name='lookimage', orderwithrespectto='look', ), I orderswithrespectto in new model class's Meta class and also made index for 'order' field by combining with other field. And a new migration file based on the model looks like the code above. The problem is operation AlterOrderWithRespectTo after AddIndex of 'order' raising error because 'order' field had not been created yet. It seems to be AlterOrderWithRespectTo has to proceed before AddIndex of '_order'.

self.generate_removed_fields()         self.generate_added_fields()         self.generate_altered_fields()        self.generate_altered_order_with_respect_to()         self.generate_altered_unique_together()         self.generate_altered_index_together()         self.generate_added_indexes()         self.generate_added_constraints()         self.generate_altered_db_table()        self.generate_altered_order_with_respect_to()          self._sort_migrations()         self._build_migration_list(graph)


Question: AlterOrderWithRespectTo() with ForeignKey crash when order is included in Index(). Description class Meta: dbtable = 'lookimage' orderwithrespectto = 'look' indexes = [ models.Index(fields=['look', 'order']), models.Index(fields=['createdat']), models.Index(fields=['updatedat']), ] migrations.CreateModel( name='LookImage', fields=[ ('id', models.AutoField(autocreated=True, primarykey=True, serialize=False, verbosename='ID')), ('look', models.ForeignKey(, relatedname='images', to='posts.Look', verbosename='LOOK')), ('imageurl', models.URLField(blank=True, maxlength=, null=True)), ('image', models.ImageField(maxlength=2000, uploadto='')), ('deleted', models.DateTimeField(editable=False, null=True)), ('createdat', models.DateTimeField(autonowadd=True)), ('updatedat', models.DateTimeField(autonow=True)), ], ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['look', 'order'], name='lookimagelookideaff30idx'), ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['createdat'], name='lookimagecreatedf746cfidx'), ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['updatedat'], name='lookimageupdatedaceaf9idx'), ), migrations.AlterOrderWithRespectTo( name='lookimage', orderwithrespectto='look', ), I orderswithrespectto in new model class's Meta class and also made index for 'order' field by combining with other field. And a new migration file based on the model looks like the code above. The problem is operation AlterOrderWithRespectTo after AddIndex of 'order' raising error because 'order' field had not been created yet. It seems to be AlterOrderWithRespectTo has to proceed before AddIndex of '_order'.

dependencies=list(set(dependencies)),                 )             # Generate other opns<ins>            if order_with_respect_to:                self.add_operation(                    app_label,                    operations.AlterOrderWithRespectTo(                        name=model_name,                        order_with_respect_to=order_with_respect_to,                    ),                    dependencies=[                        (app_label, model_name, order_with_respect_to, True),                        (app_label, model_name, None, True),                    ]                )</ins>             related_dependencies = [                 (app_label, model_name, name, True)                 for name in sorted(related_fields)


Question: AlterOrderWithRespectTo() with ForeignKey crash when order is included in Index(). Description class Meta: dbtable = 'lookimage' orderwithrespectto = 'look' indexes = [ models.Index(fields=['look', 'order']), models.Index(fields=['createdat']), models.Index(fields=['updatedat']), ] migrations.CreateModel( name='LookImage', fields=[ ('id', models.AutoField(autocreated=True, primarykey=True, serialize=False, verbosename='ID')), ('look', models.ForeignKey(, relatedname='images', to='posts.Look', verbosename='LOOK')), ('imageurl', models.URLField(blank=True, maxlength=, null=True)), ('image', models.ImageField(maxlength=2000, uploadto='')), ('deleted', models.DateTimeField(editable=False, null=True)), ('createdat', models.DateTimeField(autonowadd=True)), ('updatedat', models.DateTimeField(autonow=True)), ], ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['look', 'order'], name='lookimagelookideaff30idx'), ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['createdat'], name='lookimagecreatedf746cfidx'), ), migrations.AddIndex( modelname='lookimage', index=models.Index(fields=['updatedat'], name='lookimageupdatedaceaf9idx'), ), migrations.AlterOrderWithRespectTo( name='lookimage', orderwithrespectto='look', ), I orderswithrespectto in new model class's Meta class and also made index for 'order' field by combining with other field. And a new migration file based on the model looks like the code above. The problem is operation AlterOrderWithRespectTo after AddIndex of 'order' raising error because 'order' field had not been created yet. It seems to be AlterOrderWithRespectTo has to proceed before AddIndex of '_order'.

),                     dependencies=related_dependencies                 )<del>            if order_with_respect_to:                self.add_operation(                    app_label,                    operations.AlterOrderWithRespectTo(                        name=model_name,                        order_with_respect_to=order_with_respect_to,                    ),                    dependencies=[                        (app_label, model_name, order_with_respect_to, True),                        (app_label, model_name, None, True),                    ]                )</del>             # Fix relationships if the model changed from a proxy model to a             # concrete model.             if (app_label, model_name) in self.old_proxy_keys:


Question: Instantiating an abstract model with a string ForeignKey fails with TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types Description Trying to instantiate an abstract model with a foreign key worked without throwing any warnings in Django 1.8. In Django 1.9.8, this code: class UserProfile(Model): user = models.ForeignKey('') class Meta(object): applabel = 'core' abstract = True UserProfile() raises this exception: Traceback (most recent call last): File "<ipython-input-7-", line 2, in <moduleUserProfile() File "", line 432, in init val = field.getdefault() File "", line 905, in getdefault if isinstance(fielddefault, ): TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types While the code mentions that abstract models can not be instantiated [1], I couldn't find mention of this in the docs. Abstract models without foreign keys can still be instantiated perfectly fine. I couldn't find any description of this change in the Release Notes, so not sure if I missed it there or if this is maybe an undocumented backwards-incompatible change. [1]

opts = self._meta         _setattr = setattr         _DEFERRED = DEFERRED<ins>        if opts.abstract:            raise TypeError('Abstract models cannot be instantiated.')</ins>          pre_init.send(sender=cls, args=args, kwargs=kwargs)


Question: Session data cannot be decoded during the transition to Django 3.1. Description In () we've changed format for session data, that's why setting DEFAULTHASHINGALGORITHM to 'sha1' is not enough to support running multiple instances of the same project during the transition to Django 3.1. We could use the legacy encode() when DEFAULTHASHINGALGORITHM == 'sha1' (it's a bit hacky).

def encode(self, session_dict):         "Return the given session dictionary serialized and encoded as a string."<ins>        # RemovedInDjango40Warning: DEFAULT_HASHING_ALGORITHM will be removed.        if settings.DEFAULT_HASHING_ALGORITHM == 'sha1':            return self._legacy_encode(session_dict)</ins>         return signing.dumps(             session_dict, salt=self.key_salt, serializer=self.serializer,             compress=True,


Question: Session data cannot be decoded during the transition to Django 3.1. Description In () we've changed format for session data, that's why setting DEFAULTHASHINGALGORITHM to 'sha1' is not enough to support running multiple instances of the same project during the transition to Django 3.1. We could use the legacy encode() when DEFAULTHASHINGALGORITHM == 'sha1' (it's a bit hacky).

except Exception:             return self._legacy_decode(session_data) <ins>    def _legacy_encode(self, session_dict):        # RemovedInDjango40Warning.        serialized = self.serializer().dumps(session_dict)        hash = self._hash(serialized)        return base64.b64encode(hash.encode() + b':' + serialized).decode('ascii')</ins>     def _legacy_decode(self, session_data):         # RemovedInDjango40Warning: pre-Django 3.1 format will be invalid.         encoded_data = base64.b64decode(session_data.encode('ascii'))