Django 1.10:子类如何手动设置父类auto_now_add属性的created_at字段
created_at in a Django Subclass Let's break down how to properly override the save method in your Item class to set created_at manually, since the base field uses auto_now_add=True which normally locks the value to the first save time.
The Core Issue
When a field has auto_now_add=True, Django automatically sets it to the current datetime on initial creation and ignores any manual values you try to assign—unless you temporarily bypass this behavior for the specific instance.
Complete Solution Code
Here's the adjusted save method for your Item class, assuming you want to pull created_at from an existing item with the same identifier:
from django.utils import timezone class BaseModel(models.Model): created_at = models.DateTimeField(db_index=True, auto_now_add=True) class Item(BaseModel): title = models.CharField(max_length=200) identifier = models.CharField(max_length=15) def save(self, *args, **kwargs): # Only adjust created_at for new instances (not updates) if not self.pk: try: # Fetch the existing item using your custom queryset existing_item = Item.objects.active_and_deleted().get(identifier=self.identifier) # Temporarily disable auto_now_add to allow manual assignment created_at_field = self._meta.get_field('created_at') original_auto_now_add = created_at_field.auto_now_add created_at_field.auto_now_add = False # Set created_at to match the existing item self.created_at = existing_item.created_at # Save the instance super().save(*args, **kwargs) # Restore the original auto_now_add setting to avoid breaking other uses created_at_field.auto_now_add = original_auto_now_add except Item.DoesNotExist: # No existing item found—fall back to the default auto_now_add behavior super().save(*args, **kwargs) else: # For existing items, let the base class handle save logic super().save(*args, **kwargs)
Key Details to Note
- Temporary Field Adjustment: We only turn off
auto_now_addfor the specific instance being saved, so other models inheriting fromBaseModelwon't be affected. - Error Handling: The
try/exceptblock ensures we gracefully handle cases where no existing item with the sameidentifierexists—falling back to the default behavior in that scenario. - Create vs Update: We check
if not self.pkto target only new instances, sinceauto_now_addonly applies to initial creation anyway.
Alternative: Simplify the Base Model
If you expect to override created_at in multiple subclasses, consider modifying the BaseModel to use default instead of auto_now_add:
class BaseModel(models.Model): created_at = models.DateTimeField(db_index=True, default=timezone.now)
This removes the need for temporary field modifications entirely—Django will set the current datetime by default, but you can easily override it in any subclass. The only tradeoff is that created_at will be set when the instance is initialized, not when it's saved, but this is acceptable for most use cases.
内容的提问来源于stack exchange,提问作者user2880391

