mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.6.x] Fixed #21146 - DatabaseCache converts expires to python value
DatabaseCache uses raw cursors to bypass the ORM. This prevents it from
being used by database backends that require special handling of datetime
values.
There is no easy way to test this, so no tests added.
Backport of d5606b5763 from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Anssi Kääriäinen
						Anssi Kääriäinen
					
				
			
			
				
	
			
			
			
						parent
						
							d1047c8b4c
						
					
				
				
					commit
					a979a2fea5
				
			
							
								
								
									
										21
									
								
								django/core/cache/backends/db.py
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								django/core/cache/backends/db.py
									
									
									
									
										vendored
									
									
								
							| @@ -11,6 +11,7 @@ except ImportError: | ||||
| from django.conf import settings | ||||
| from django.core.cache.backends.base import BaseCache, DEFAULT_TIMEOUT | ||||
| from django.db import connections, transaction, router, DatabaseError | ||||
| from django.db.backends.utils import typecast_timestamp | ||||
| from django.utils import timezone, six | ||||
| from django.utils.encoding import force_bytes | ||||
|  | ||||
| @@ -65,8 +66,13 @@ class DatabaseCache(BaseDatabaseCache): | ||||
|         if row is None: | ||||
|             return default | ||||
|         now = timezone.now() | ||||
|  | ||||
|         if row[2] < now: | ||||
|         expires = row[2] | ||||
|         if connections[db].features.needs_datetime_string_cast and not isinstance(expires, datetime): | ||||
|             # Note: typecasting is needed by some 3rd party database backends. | ||||
|             # All core backends work without typecasting, so be careful about | ||||
|             # changes here - test suite will NOT pick regressions here. | ||||
|             expires = typecast_timestamp(str(expires)) | ||||
|         if expires < now: | ||||
|             db = router.db_for_write(self.cache_model_class) | ||||
|             cursor = connections[db].cursor() | ||||
|             cursor.execute("DELETE FROM %s " | ||||
| @@ -112,12 +118,21 @@ class DatabaseCache(BaseDatabaseCache): | ||||
|         if six.PY3: | ||||
|             b64encoded = b64encoded.decode('latin1') | ||||
|         try: | ||||
|             # Note: typecasting for datetimes is needed by some 3rd party | ||||
|             # database backends. All core backends work without typecasting, | ||||
|             # so be careful about changes here - test suite will NOT pick | ||||
|             # regressions. | ||||
|             with transaction.atomic(using=db): | ||||
|                 cursor.execute("SELECT cache_key, expires FROM %s " | ||||
|                                "WHERE cache_key = %%s" % table, [key]) | ||||
|                 result = cursor.fetchone() | ||||
|                 if result: | ||||
|                     current_expires = result[1] | ||||
|                     if (connections[db].features.needs_datetime_string_cast and not | ||||
|                             isinstance(current_expires, datetime)): | ||||
|                         current_expires = typecast_timestamp(str(current_expires)) | ||||
|                 exp = connections[db].ops.value_to_db_datetime(exp) | ||||
|                 if result and (mode == 'set' or (mode == 'add' and result[1] < now)): | ||||
|                 if result and (mode == 'set' or (mode == 'add' and current_expires < now)): | ||||
|                     cursor.execute("UPDATE %s SET value = %%s, expires = %%s " | ||||
|                                    "WHERE cache_key = %%s" % table, | ||||
|                                    [b64encoded, exp, key]) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user