Python 姜戈。覆盖模型的保存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4269605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Django. Override save for model
提问by Pol
Before saving model I'm re-size a picture. But how can I check if new picture added or just description updated, so I can skip rescaling every time the model is saved?
在保存模型之前,我要重新调整图片大小。但是如何检查是否添加了新图片或仅更新了描述,以便每次保存模型时都可以跳过重新缩放?
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)
I want to rescale only if new image loaded or image updated, but not when description updated.
我只想在加载新图像或更新图像时重新缩放,而不是在描述更新时重新缩放。
采纳答案by petraszd
Some thoughts:
一些想法:
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)
Not sure if it would play nice with all pseudo-auto django tools (Example: ModelForm, contrib.admin etc).
不确定它是否适用于所有伪自动 django 工具(例如:ModelForm、contrib.admin 等)。
回答by Ignacio Vazquez-Abrams
Query the database for an existing record with the same PK. Compare the file sizes and checksums of the new and existing images to see if they're the same.
在数据库中查询具有相同 PK 的现有记录。比较新图像和现有图像的文件大小和校验和,看看它们是否相同。
回答by crodjer
You may supply extra argument for confirming a new image is posted.
Something like:
您可以提供额外的参数来确认已发布新图像。
就像是:
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)
or pass request variable
或传递请求变量
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)
I think these wont break your save when called simply.
我认为这些在简单调用时不会破坏您的保存。
You may put this in your admin.py so that this work with admin site too (for second of above solutions):
你可以把它放在你的 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
回答by DM Graves
Check the model's pk field. If it is None, then it is a new object.
检查模型的 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)
Edit: I've added a check for 'image' in form.changed_data. This assumes that you're using the admin site to update your images. You'll also have to override the default save_model method as indicated below.
编辑:我在 form.changed_data 中添加了对“图像”的检查。这假设您正在使用管理站点来更新您的图像。您还必须覆盖默认的 save_model 方法,如下所示。
class ModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.save(form=form)
回答by bonbon.langes
What I did to achieve the goal was to make this..
我为实现目标所做的就是使这个..
# I added an extra_command argument that defaults to blank
def save(self, extra_command="", *args, **kwargs):
and below the save() method is this..
在 save() 方法下面是这个..
# override the save method to create an image thumbnail
if self.image and extra_command != "skip creating photo thumbnail":
# your logic here
so when i edit some fields but not editing the image, I put this..
所以当我编辑一些字段但不编辑图像时,我把这个..
Model.save("skip creating photo thumbnail")
you can replace the "skip creating photo thumbnail"with "im just editing the description"or a more formal text.
你可以替换"skip creating photo thumbnail"使用"im just editing the description"或者更正式的文本。
Hope this one helps!
希望这个有帮助!
回答by Dan Goriaynov
In new version it is like this:
在新版本中是这样的:
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
回答by Devendra Bhat
I have found one another simple way to store the data into the database
我找到了另一种将数据存储到数据库中的简单方法
models.py
模型.py
class LinkModel(models.Model):
link = models.CharField(max_length=500)
shortLink = models.CharField(max_length=30,unique=True)
In database I have only 2 variables
在数据库中我只有 2 个变量
views.py
视图.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
In this I have created the instance of model in views.py only and putting/saving data into 2 variables from views only.
在此,我仅在 views.py 中创建了模型实例,并且仅从视图将数据放入/保存到 2 个变量中。
回答by panchicore
Django 3: Overriding predefined model methods
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()
It's important to remember to call the superclass method – that's that
super().save(*args, **kwargs)business – to ensure that the object still gets saved into the database. If you forget to call the superclass method, the default behavior won't happen and the database won't get touched.
重要的是要记住调用超类方法——这就是
super().save(*args, **kwargs)业务——以确保对象仍然保存到数据库中。如果您忘记调用超类方法,则不会发生默认行为,也不会触及数据库。

