姜戈。覆盖模型的保存

Posted

技术标签:

【中文标题】姜戈。覆盖模型的保存【英文标题】:Django. Override save for model 【发布时间】:2011-05-15 06:03:13 【问题描述】:

在保存模型之前,我会重新调整图片大小。但是如何检查是否添加了新图片或仅更新了描述,以便每次保存模型时都可以跳过重新缩放?

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if self.image:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

我只想在加载新图像或更新图像时重新缩放,而不是在描述更新时重新缩放。

【问题讨论】:

您是否将大小调整为 100x100 的固定尺寸? 你可能会发现django-imagekit很有用 【参考方案1】:

一些想法:

class Model(model.Model):
    _image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()

    def set_image(self, val):
        self._image = val
        self._image_changed = True

        # Or put whole logic in here
        small = rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)

    def get_image(self):
        return self._image

    image = property(get_image, set_image)

    # this is not needed if small_image is created at set_image
    def save(self, *args, **kwargs):
        if getattr(self, '_image_changed', True):
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

不确定它是否能与所有伪自动 django 工具(例如:ModelForm、contrib.admin 等)配合使用。

【讨论】:

看起来不错。但我无法将图像重命名为 _image。这很重要吗? 好的,我用 db_column='image' 解决了这个问题。但它钢铁不起作用! 这是非常有趣的方法..我不完全理解。你能更详细地解释一下吗?还是播种文章? 这对我也不起作用,。 set_image 从未调用过。看起来像这样一些 Django 没有官方支持的东西【参考方案2】:

检查模型的 pk 字段。如果是 None,那么它是一个新对象。

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if 'form' in kwargs:
            form=kwargs['form']
        else:
            form=None

        if self.pk is None and form is not None and 'image' in form.changed_data:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

编辑:我在 form.changed_data 中添加了对“图像”的检查。这假设您正在使用管理站点来更新您的图像。您还必须覆盖默认的 save_model 方法,如下所示。

class ModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.save(form=form)

【讨论】:

我认为你是对的......假设他正在使用管理站点,他可以覆盖他的 AdminModel 中的 save_model 以传递表单以保存,并检查“图像”是否在表单中。更改数据。我会尽快更新。 这仅适用于您所说的新对象。如果您上传新图片,则不会触发重新缩放。 "self.pk is None" 如果指定 id 则不起作用,因此:Model.objects.get_or_create(id=234,...) 在此解决方案中不起作用【参考方案3】:

您可以提供额外的参数来确认已发布新图片。 比如:

def save(self, new_image=False, *args, **kwargs):
    if new_image:
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

或传递请求变量

def save(self, request=False, *args, **kwargs):
    if request and request.FILES.get('image',False):
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

我认为这些在简单调用时不会破坏你的保存。

您可以将它放在您的 admin.py 中,以便它也可以与管理站点一起使用(对于上述第二个解决方案):

class ModelAdmin(admin.ModelAdmin):

    ....
    def save_model(self, request, obj, form, change): 
        instance = form.save(commit=False)
        instance.save(request=request)
        return instance

【讨论】:

它告诉我:'WSGIRequest' 对象没有属性'FILE' sry 它的 FILES 而不是 FILE,更新为 request.FILES.get('image',False) 而不是 request.FILES['image'],这样可以避免异常【参考方案4】:

我为实现目标所做的就是做到这一点..

# I added an extra_command argument that defaults to blank
def save(self, extra_command="", *args, **kwargs):

save() 方法下面是这个..

# override the save method to create an image thumbnail
if self.image and extra_command != "skip creating photo thumbnail":
    # your logic here

所以当我编辑一些字段但不编辑图像时,我把这个..

Model.save("skip creating photo thumbnail")

您可以将"skip creating photo thumbnail" 替换为"im just editing the description" 或更正式的文本。

希望这个有帮助!

【讨论】:

【参考方案5】:

在数据库中查询具有相同 PK 的现有记录。比较新图像和现有图像的文件大小和校验和,看看它们是否相同。

【讨论】:

【参考方案6】:

新版本是这样的:

def validate(self, attrs):
    has_unknown_fields = set(self.initial_data) - set(self.fields.keys())
    if has_unknown_fields:
        raise serializers.ValidationError("Do not send extra fields")
    return attrs

【讨论】:

【参考方案7】:

我找到了另一种将数据存储到数据库中的简单方法

models.py

class LinkModel(models.Model):
    link = models.CharField(max_length=500)
    shortLink = models.CharField(max_length=30,unique=True)

在数据库中我只有 2 个变量

views.py

class HomeView(TemplateView):
    def post(self,request, *args, **kwargs):
        form = LinkForm(request.POST)

        if form.is_valid():
            text = form.cleaned_data['link'] # text for link

        dbobj = LinkModel()
        dbobj.link = text
        self.no = self.gen.generateShortLink() # no for shortLink
        dbobj.shortLink = str(self.no)
        dbobj.save()         # Saving from views.py

在此我仅在views.py 中创建了模型实例,并将数据放入/保存到仅来自视图的2 个变量中。

【讨论】:

以上是关于姜戈。覆盖模型的保存的主要内容,如果未能解决你的问题,请参考以下文章

Django - 覆盖模型保存()

如何以 django 模型形式覆盖保存方法

保存自定义用户模型时 Django ManyToMany 覆盖

Django 抽象父模型保存覆盖

Django:覆盖保存(模型或管理部分)

使用覆盖保存为抽象模型扩展 Django ModelForm