将ImageField默认值设置为Django中的图像列表中的随机图像

时间:2015-04-09 09:07:10

标签: python django random django-models imagefield

我在静态目录中有一些图像,并且想要创建一个具有ImageField的模型。我想将默认字段设置为这些图像中的任何一个。我试过用这个 -

def randomImage():
    return ImageFile('media/blog/image/' + str(random.randrange(1, 15, 1)) + '.jpg')

# ----------------------- Model for each post in the blog-------------------
class Post(models.Model):
    heading = models.CharField(max_length=150)
    author = models.ForeignKey(User)
    postBody = models.TextField()
    postDate = models.DateTimeField('posting date')
    postImage = models.ImageField(upload_to='media/blog/image/'+str(int(time.time())), default=randomImage)

2 个答案:

答案 0 :(得分:5)

这里我有一些假设,
1.您的 默认图像 位于 static 目录中
2.在 static 目录中, 所有文件均为图像

什么是 主要技巧

Django仅需要有效文件路径来创建或更新 文件条目 (图像也是文件)。因此,我们在这里要做的是,列出所有 文件 (假设这些只是图像),然后使用random.choice()随机选择一个条目并重新调整 {em> (类似于static/my_img.jpg)到 default 自变量的路径

import time
from random import choice
from os.path import join as path_join
from os import listdir
from os.path import isfile


def random_img():
    dir_path = 'static'
    files = [content for content in listdir(dir_path) if isfile(path_join(dir_path, content))]
    return path_join(dir_path, choice(files))


class Post(models.Model):
    # other fields
    postImage = models.ImageField(
        upload_to='media/blog/image/' + str(int(time.time())),
        default=random_img)



UPDATE-1

我已经在 Django 2.1.1 中创建了一个最小的示例,可以在下面的git repo中找到
重播链接-> django2X
1.克隆存储库,创建虚拟环境并安装依赖项(已提供requirements.txt文件)
2.创建一个新的超级用户或使用我的超级用户(用户名-> admin,通过-> jerin123@
3.运行服务器并登录django admin:(screenshot-1
4.再次创建一个新的Post实例

而已

UPDATE-2

最小示例中,我所做的更改很少,
1.在每次django启动时创建一个简单的对象创建(此处为 Post 模型对象) (结帐{{1} })
2.将 sample/app.py MEDIA_ROOT 添加到MEDIA_URL文件中

现在,启动您的项目(每次启动将创建3个对象),然后转到http://127.0.0.1:8000/admin/sample/post/
然后打开任何实例,然后单击图像链接(screenshot-2),它将打开图片(screenshot-3

答案 1 :(得分:1)

我的解决方案是覆盖模型保存方法,并检查是否是首次创建模型,还要检查postImage image字段是否为空。如果是这样,用Radom图片的内容填充postImage字段。 Django将处理其余的

如果我们直接在模型中使用Radom图像的路径,则最终会像从媒体文件夹中提供一些后期模型文件,而从静态目录中提供一些其他模型一样(不建议这样做)。相反,我们将图像文件的内容输入到postImage字段,而Django会将图像保存到media文件夹,因此我们可以从media文件夹本身提供所有模型图像。沃拉

代码

以下代码已在 Python 3.6 中进行了测试 请将代码添加到您的 models.py

from pathlib import Path
from random import randint
import time
from django.core.files import File
from django.db import models

allowed_image_extensions = ['.jpg', '.png', '.jpeg']


def get_file_extension(file_path):
    return Path(file_path).suffix


def get_files_in_directory(directory, absolute_path=False):
    from os import listdir
    from os.path import isfile
    only_files = [f for f in listdir(directory) if isfile("{}/{}".format(directory, f))]

    if not absolute_path:
        return only_files

    else:
        return ["{}/{}".format(directory, file_) for file_ in only_files]


def get_random_image_from_directory(directory_path, image_extension=None):
    files_in_directory_path = get_files_in_directory(directory_path, absolute_path=True)

    if image_extension:
        allowed_file_types = [image_extension]
    else:
        allowed_file_types = allowed_image_extensions

    # filter out files of type other than required file types
    filtered_files_list = [_file for _file in files_in_directory_path if
                       get_file_extension(_file).lower() in allowed_file_types]

   random_index = randint(0, len(filtered_files_list) - 1)
   random_file_path = filtered_files_list[random_index]
   random_file_content = File(open(random_file_path, 'rb'))

   return random_file_content


def get_post_image_path(instance, filename):
    path_first_component = 'posts'
    ext = get_file_extension(filename)
    current_time_stamp = int(time.time())
    file_name = '{}/posts_{}_{}{}'.format(path_first_component, instance.id, current_time_stamp, ext)
    full_path = path_first_component + file_name
    return full_path

class Post(models.Model):
    heading = models.CharField(max_length=150)
    author = models.ForeignKey(User)
    postBody = models.TextField()
    postDate = models.DateTimeField('posting date')
    postImage = models.ImageField(blank=True, null=True, upload_to=get_post_image_path)

    # override model save method
    def save(self, *args, **kwargs):

        # check model is new and postImage is empty
        if self.pk is None and not self.postImage:
            random_image = get_random_image_from_directory(settings.STATIC_ROOT)
            self.postImage = random_image
            random_image.close()


    super(Post, self).save(*args, **kwargs)

也无需在upload_to路径中设置“ / media”。 Django将从设置变量中读取媒体路径

最佳做法是将这些默认图像集从静态目录移到另一个文件夹(可能是另一个具有名称资源或其他有意义名称的文件夹),因为静态目录的内容会随着项目的增长而频繁更改