首页 > 解决方案 > 如何使用 Django 信号(Pre_save,Post_save)从“B”模型的 ImageField 设置“A”模型的 ImageField

问题描述

这是我的模型

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图像设置为我的projectmodelimageField,同时保存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
        
    

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

标签: djangodjango-modelsdjango-signals

解决方案


filter()返回 aQuerySet并使用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(...)

推荐阅读