Django的。覆盖保存为模型


133

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

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的固定尺寸?
2010年

3
您可能会发现django-imagekit很有用
vikingosegundo

Answers:


133

一些想法:

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等)。


1
看起来不错。但是我不能将图像重命名为_image。那重要吗?
波尔

好的,我用db_column ='image'解决了。但是它不起作用!
Pol 2010年

1
这是非常有趣的方法..我不完全了解。您能更详细地解释一下吗?还是播一些文章?
Pol 2010年

这对我也不起作用。set_image从未调用过。一些像这样的Django就没有官方支持的东西
伊万Borshchov

16

检查模型的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来传递表单进行保存,并检查“ image”是否在form.changed_data中。如果有时间,我会尽快更新。
DM格雷夫斯2010年

如您所说,这仅在对象是新对象时有效。如果您上传新照片,则不会触发重新缩放。
乔纳森(Jonathan)

2
如果指定了id,则“ self.pk为None”将不起作用,因此:Model.objects.get_or_create(id = 234,...)在此解决方案中将不起作用
螺母

6

您可以提供额外的参数来确认发布新图像。
就像是:

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”
波兰

将其FILES代替FILE,更新为request.FILES.get('image',False)代替request.FILES ['image'],这样可以避免出现异常
crodjer 2010年

3

我要做的就是实现这一目标。

# 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"或者更正式的文本。

希望这对您有所帮助!



1

Django 3:覆盖预定义的模型方法

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, *args, **kwargs):
        do_something()
        super().save(*args, **kwargs)  # Call the "real" save() method.
        do_something_else()

重要的是要记住要调用超类方法(就是这样), super().save(*args, **kwargs)以确保仍然将对象保存到数据库中。如果您忘记调用超类方法,则默认行为不会发生,并且数据库也不会受到影响。


0

在新版本中,它是这样的:

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

0

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

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个变量中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.