如何使用 Django 信号(Pre_save,Post_save)从“B”模型的 ImageField 设置“A”模型的 ImageField

Posted

技术标签:

【中文标题】如何使用 Django 信号(Pre_save,Post_save)从“B”模型的 ImageField 设置“A”模型的 ImageField【英文标题】:How to set 'A' model's ImageField from 'B' model's ImageField Using Django signal(Pre_save,Post_save) 【发布时间】:2021-04-24 05:02:42 【问题描述】:

这是我的模型

from django.db import models
from django.utils import timezone

# Create your models here.
class send_message_model(models.Model):
    mail = models.EmailField(max_length=100)
    msg = models.TextField(max_length=500)


class projectmodel(models.Model):
    project_name = models.CharField(max_length=100)
    project_url = models.URLField()
    project_desc = models.CharField(max_length=200)
    project_short_desc = models.CharField(max_length=100,default='')
    project_date = models.DateField(default=timezone.now)
    rate = models.IntegerField()
    project_thumb = models.ImageField(blank=True)
    def __str__(self):
        return f'self.id'


class projectimage(models.Model):
    project_id = models.ForeignKey(projectmodel,on_delete=models.CASCADE,blank=True,null=True)
    project_pic = models.FileField(upload_to = 'imgs/')
    time = models.DateTimeField( auto_now=False, auto_now_add=True)

    def __str__(self):
        return f"self.project_id"

我想将ProjectImage's 图像设置为我的projectmodel 图像字段,同时保存projectmodel

我试过了,

from django.contrib.auth.models import User
from Portfolio.models import projectimage,projectmodel
from django.db.models.signals import post_save,pre_save

from django.dispatch import receiver

def do_something(sender,instance,**kwargs):
    print("User Saved")
    print(sender)
    print(instance)
    # print(created)

pre_save.connect(do_something,sender = User)

@receiver(pre_save,sender=projectmodel)
def add_image(sender,instance,**kwargs):
    if not instance.project_thumb:
        print("Image Empty")
        instance_id = instance.id
        img = projectimage.objects.filter(id = instance_id).order_by('id')[0]
        print(img)
        print(type(img))
        

        thumb = projectmodel.objects.filter(id = instance_id)

        thumb_save = thumb(project_thumb = img)
        thumb_save.save()
    else:
        print("Image here")
       

但它不起作用, 显示此错误,

TypeError at /admin/Portfolio/projectmodel/4/change/

'QuerySet' object is not callable

Request Method:     POST
Request URL:    http://127.0.0.1:8000/admin/Portfolio/projectmodel/4/change/
Django Version:     3.1.4
Exception Type:     TypeError
Exception Value:    

'QuerySet' object is not callable

Exception Location:     C:\Django Python\SecondPortfolio\Portfolio\signals.py, line 27, in add_image
Python Executable:  C:\Program Files\Python38\python.exe
Python Version:     3.8.2
Python Path:    

['C:\\Django Python\\SecondPortfolio',
 'C:\\Program Files\\Python38\\python38.zip',
 'C:\\Program Files\\Python38\\DLLs',
 'C:\\Program Files\\Python38\\lib',
 'C:\\Program Files\\Python38',
 'C:\\Users\\Rak1b\\AppData\\Roaming\\Python\\Python38\\site-packages',
 'C:\\Program Files\\Python38\\lib\\site-packages']

Server time:    Tue, 19 Jan 2021 20:39:51 +0000

解决后 出现了一个新问题

AttributeError at /admin/Portfolio/projectmodel/1/change/

'projectimage' object has no attribute '_committed'

Request Method:     POST
Request URL:    http://127.0.0.1:8000/admin/Portfolio/projectmodel/1/change/
Django Version:     3.1.4
Exception Type:     AttributeError
Exception Value:    

'projectimage' object has no attribute '_committed'

Exception Location:     C:\Users\Rak1b\AppData\Roaming\Python\Python38\site-packages\django\db\models\fields\files.py, line 305, in pre_save
Python Executable:  C:\Program Files\Python38\python.exe
Python Version:     3.8.2
Python Path:    

['C:\\Django Python\\SecondPortfolio',
 'C:\\Program Files\\Python38\\python38.zip',
 'C:\\Program Files\\Python38\\DLLs',
 'C:\\Program Files\\Python38\\lib',
 'C:\\Program Files\\Python38',
 'C:\\Users\\Rak1b\\AppData\\Roaming\\Python\\Python38\\site-packages',
 'C:\\Program Files\\Python38\\lib\\site-packages']

Server time:    Tue, 19 Jan 2021 22:31:15 +0000
        
    

这将非常有帮助,如果有人给我想法,如何在另一个模型上设置图像

【问题讨论】:

【参考方案1】:

filter() 返回 QuerySet 并使用 img.project_pic 代替 img

最好使用get()

from django.core.files.base import ContentFile

...
def add_image(sender,instance,**kwargs):

    ...

    thumb = projectmodel.objects.get(id=instance_id)
    thumb.project_thumb.save(img.project_pic.name, ContentFile(img.project_pic.read()), save=False)
    thumb.save()

...
def add_image(sender,instance,**kwargs):

    ...

    thumb = projectmodel.objects.get(id=instance_id)
    thumb.project_thumb = img.project_pic
    thumb.save()

如果你想使用filter()而不是还必须使用update()

thumb.update(...)

【讨论】:

谢谢兄弟,但这对我不起作用,显示这个 'projectmodel' 对象不可调用。,我试过,通过这样做,instance.project_thumb= img 它适用于文本字段,但不是为imgs工作, 我现在已经在我的本地主机上尝试了这个代码。效果很好。 更新你的问题,看看你做了什么。 'projectimage' 对象没有属性 '_committed' 请检查此错误。 @MdRakibulIslam,我已经更新了我的答案,所有方法都适合我。

以上是关于如何使用 Django 信号(Pre_save,Post_save)从“B”模型的 ImageField 设置“A”模型的 ImageField的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 pre_save 信号在 django 模型中保存相关对象

将pre_save信号更改为post_save?Django

Django:信号的使用

Django signal 信号机制的使用

Django信号

Django 信号