sch*_*eck 34 django django-models
我有一个模特:
class MyModel(models.Model):
...
def save(self):
print "saving"
...
def delete(self):
print "deleting"
...
Run Code Online (Sandbox Code Playgroud)
save() - 方法被触发,但delete()不是.我使用最新的svn-Version(Django 1.2版pre-alpha SVN-11593),关于http://www.djangoproject.com/documentation/models/save_delete_hooks/上的文档,这应该可行.有任何想法吗?
Dom*_*ger 72
我认为您可能正在使用管理员的批量删除功能,并且正在遇到管理员的批量删除方法未调用的事实delete()(请参阅相关的故障单).
我在过去通过编写用于删除模型的自定义管理操作来解决这个问题.
如果您没有使用管理员的批量删除方法(例如,您单击对象编辑页面上的删除按钮),则会发生其他事情.
请在此处查看警告:
QuerySet.delete()出于效率原因,"删除所选对象"操作会使用,这有一个重要的警告:delete()不会调用模型的方法.如果您希望覆盖此行为,只需编写一个自定义操作,以您首选的方式完成删除 - 例如,通过调用
Model.delete()每个选定的项目.有关批量删除的更多背景信息,请参阅有关对象删除的文档.
我的自定义管理模型如下所示:
from photoblog.models import PhotoBlogEntry
from django.contrib import admin
class PhotoBlogEntryAdmin(admin.ModelAdmin):
actions=['really_delete_selected']
def get_actions(self, request):
actions = super(PhotoBlogEntryAdmin, self).get_actions(request)
del actions['delete_selected']
return actions
def really_delete_selected(self, request, queryset):
for obj in queryset:
obj.delete()
if queryset.count() == 1:
message_bit = "1 photoblog entry was"
else:
message_bit = "%s photoblog entries were" % queryset.count()
self.message_user(request, "%s successfully deleted." % message_bit)
really_delete_selected.short_description = "Delete selected entries"
admin.site.register(PhotoBlogEntry, PhotoBlogEntryAdmin)
Run Code Online (Sandbox Code Playgroud)
Dav*_*ett 34
我知道这个问题很古老,但我刚刚再遇到这个问题,并希望补充一点,您可以随时将代码移动到pre_delete或post_delete信号,如下所示:
from django.db.models.signals import pre_delete
from django.dispatch.dispatcher import receiver
@receiver(pre_delete, sender=MyModel)
def _mymodel_delete(sender, instance, **kwargs):
print("deleting")
Run Code Online (Sandbox Code Playgroud)
它适用于管理员的批量删除操作(至少从1.3.1开始).
管理员调用的批量操作queryset.delete().
您可以覆盖查询集的.delete()方法,因此它始终执行1对1的对象删除.例如:
在managers.py中:
from django.db import models
from django.db.models.query import QuerySet
class PhotoQueryMixin(object):
""" Methods that appear both in the manager and queryset. """
def delete(self):
# Use individual queries to the attachment is removed.
for photo in self.all():
photo.delete()
class PhotoQuerySet(PhotoQueryMixin, QuerySet):
pass
class PhotoManager(PhotoQueryMixin, models.Manager):
def get_query_set(self):
return PhotoQuerySet(self.model, using=self._db)
Run Code Online (Sandbox Code Playgroud)
在models.py中:
from django.db import models
class Photo(models.Model):
image = models.ImageField(upload_to='images')
objects = PhotoManager()
def delete(self, *args, **kwargs):
# Note this is a simple example. it only handles delete(),
# and not replacing images in .save()
super(Photo, self).delete(*args, **kwargs)
self.image.delete()
Run Code Online (Sandbox Code Playgroud)
使用django v2.2.2,我用下面的代码解决了这个问题
模型.py
class MyModel(models.Model):
file = models.FileField(upload_to=<path>)
def save(self, *args, **kwargs):
if self.pk is not None:
old_file = MyModel.objects.get(pk=self.pk).file
if old_file.path != self.file.path:
self.file.storage.delete(old_file.path)
return super(MyModel, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
ret = super(MyModel, self).delete(*args, **kwargs)
self.file.storage.delete(self.file.path)
return ret
Run Code Online (Sandbox Code Playgroud)
管理文件
class MyModelAdmin(admin.ModelAdmin):
def delete_queryset(self, request, queryset):
for obj in queryset:
obj.delete()
Run Code Online (Sandbox Code Playgroud)
对于 DefaultAdminSite,如果用户具有正确的权限,则调用 delete_queryset,唯一的区别是原始函数调用queryset.delete()不会触发模型delete方法。这效率较低,因为不再是批量操作,但它保持文件系统干净 =)
| 归档时间: |
|
| 查看次数: |
20462 次 |
| 最近记录: |