如何保存具有多个图像的 django 模型?

Posted

技术标签:

【中文标题】如何保存具有多个图像的 django 模型?【英文标题】:How to save a django model with multiple images? 【发布时间】:2021-11-30 05:35:02 【问题描述】:

我已经赌了一个小时,但显然我不明白什么。有一个任务是用 django 管理面板编写一个刮板,一切都很好,可以在这里工作。现在我需要将所有数据保存到数据库中,这就是问题所在,django 管理面板中只出现了一张照片,但所有内容都下载到了媒体文件夹中。

# models.py
from django.db import models


class Apartment(models.Model):
    rooms = models.CharField('кол-во комнат', max_length=64)
    price = models.CharField('цена', max_length=10)
    address = models.CharField('Адрес', max_length=256)
    desc = models.TextField('описание')
    floor = models.CharField('этаж', max_length=5)

    def __str__(self):
        return self.address

    class Meta:
        verbose_name = 'квартира'
        verbose_name_plural = 'квартиры'


class Image(models.Model):
    apartment = models.ForeignKey(Apartment, on_delete=models.CASCADE)
    img = models.ImageField(upload_to='media/')

    class Meta:
        verbose_name = 'фото'
        verbose_name_plural = 'фото'


class Url(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    url = models.URLField('ссылка')

    def __str__(self):
        return self.url

    class Meta:
        verbose_name = 'ссылка'
        verbose_name_plural = 'ссылки'
        ordering = ['-created']

#scraper
@receiver(post_save, sender=Url)
def saved_url(instance, created, **kwargs):
    apartments = []

    if created:
        url = instance.url
        soup = make_request(url)
        for link in soup.find_all('div', attrs='data-name': 'LinkArea'):
            url = link.find('a').get('href')
            driver.get(url)
            time.sleep(1)
            try:
                rooms = driver.find_element(By.XPATH, '//div[1][@data-name="OfferTitle"]/h1').text
            except:
                rooms = None
            try:
                price = driver.find_element(By.XPATH, '//div[1]/div/span/span[1][@itemprop="price"]').text
            except:
                price = None
            try:
                address = driver.find_element(By.XPATH,
                                              '//section/div/div[1]/div[2]/span[@itemprop="name"]').get_attribute(
                    'content')
            except:
                address = None
            try:
                desc = driver.find_element(By.XPATH, '//div/span/p[@itemprop="description"]').text
            except:
                desc = None
            try:
                floor = driver.find_element(By.XPATH, '//div/div[4]/div[1][@data-testid="object-summary-description-value"]').text
            except:
                floor = None
            try:
                photos = [img.get_attribute('src') for img in driver.find_elements(By.CLASS_NAME, 'fotorama__img')]
            except:
                photos = None
            
            apartments.append(
                
                    'rooms': rooms,
                    'price': price,
                    'address': address,
                    'desc': desc,
                    'floor': floor,
                    'photos': photos,
                
            )

            save_data(apartments)

#save function 
def save_data(apartments_list):

    for ap in apartments_list:
        im = Image()
        try:
            apartment = Apartment.objects.create(
                rooms=ap['rooms'],
                price=ap['price'],
                address=ap['address'],
                desc=ap['desc'],
                floor=ap['floor'],
            )
            for image in ap['photos']:
                pic = urllib.request.urlretrieve(image, image.split('/')[-1])[0]
                im.img = im.img.save(pic, File(open(pic, 'rb')))
                im.apartment = apartment
        except Exception as e:
            print(e)
            break

【问题讨论】:

能否分享您在apartments_list 中的数据样本? 您需要为每个要保存的图像创建一个新的Image。您目前正在一次又一次地重复使用和更新同一个 Image 对象 现已添加刮板功能 @IainShelvington 好的,但是我该怎么做,因为 ap ['photos'] 是一个 url 列表 【参考方案1】:

您的问题是您实际上并未保存图像。尝试更改此设置

def save_data(apartments_list):

    for ap in apartments_list:
        im = Image()
        try:
            apartment = Apartment.objects.create(
                rooms=ap['rooms'],
                price=ap['price'],
                address=ap['address'],
                desc=ap['desc'],
                floor=ap['floor'],
            )
            for image in ap['photos']:
                pic = urllib.request.urlretrieve(image, image.split('/')[-1])[0]
                im.img = im.img.save(pic, File(open(pic, 'rb')))
                im.apartment = apartment
        except Exception as e:
            print(e)
            break

def save_data(apartments_list):

    for ap in apartments_list:
        
        try:
            apartment = Apartment.objects.create(
                rooms=ap['rooms'],
                price=ap['price'],
                address=ap['address'],
                desc=ap['desc'],
                floor=ap['floor'],
            )
            for image in ap['photos']:
                im = Image()
                pic = urllib.request.urlretrieve(image)[0]            
                im.img.save(image, File(open(pic, 'rb')))
                im.apartment = apartment
                im.save() #new
        except Exception as e:
            print(e)
            break

【讨论】:

谢谢,但我已经尝试过了,然后我在管理面板中得到了一个图像对象 @Evgeny 你得到了哪个图像对象?你能告诉我你得到了什么吗?如果你得到 Image Object[..] 这意味着你没有在你的模型中指定def __str__(self) 例如图像对象 (189),没有图像,只有一个可用。但是有15张图片 @Evgeny 当您在详细信息页面中单击该对象时,您会看到什么。 是的!它现在正在工作!

以上是关于如何保存具有多个图像的 django 模型?的主要内容,如果未能解决你的问题,请参考以下文章

如果没有给出图像,则 Django 模型函数保存图像字段 = 异常

Django 模型 - 至少多对多之一

扩展后无法在 Django 模型上保存图像

如何在 django 中将多个图像一起发布?

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

Django REST:上传和序列化多个图像