【问题标题】:How and where should I store the conversion code for image files in Django?我应该如何以及在哪里存储 Django 中图像文件的转换代码?
【发布时间】:2019-08-11 19:19:02
【问题描述】:

我在 Django 中创建了一个简单的表单,它只包含一个表单输入字段,即图像字段。我的目标是允许用户上传图像文件,即 JPEG、JPG、SVG、PNG。上传后,我想编写一些代码将图像文件转换为 PNG,然后将其存储在我的数据库中。我应该如何编写这段代码以及在哪里编写它?您可以在下面查看我当前的代码。我是 Django 的初学者,需要一些帮助。

settings.py

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

网站/urls.py:

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')),

]

urlpatterns = urlpatterns + static(settings.STATIC_URL, 
document_root=settings.STATIC_ROOT)
urlpatterns = urlpatterns + static(settings.MEDIA_URL, 
document_root=settings.MEDIA_ROOT)

models.py

from django.db import models

class Image(models.Model):
"""Image upload model"""
image = models.ImageField(upload_to = 'media', default = 'media/sample.png')
created_date = models.DateTimeField(auto_now = True)

def __str__(self):
    return str(self.id)

forms.py

from django import forms

from myapp.models import Image

class ImageForm(forms.ModelForm):
    """Image upload form"""
    class Meta:
        model = Image
        exclude = ('created_date',)

views.py

from django.shortcuts import render
from django.db import models
from django.views.generic import TemplateView, CreateView
from myapp.forms import ImageForm
from django.urls import reverse_lazy
from PIL import Image

class BaseView(TemplateView):
    template_name = "base.html"

class ImageView(CreateView):
    template_name = "insert_image.html"
    form_class = ImageForm
    success_url = reverse_lazy("base")

insert_image.html

{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
    <title> Insert an image </title>
</head>
<body>

    <h1> Please upload an image below </h1>

    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        {{form.as_p}}
        <button type="submit"> Submit </button>
    </form>
</body>
</html>

base.html

<!DOCTYPE html>
<html>
<head>
    <title> Thanks! </title>
</head>
<body>

    <h1> Thanks for uploading! </h1>
    <button> <a href = '{% url "insert_image" %}' style="text-decoration: 
    none;"> Return </button> </a>

</body>
</html>

【问题讨论】:

    标签: python django image


    【解决方案1】:

    答案是“pyrsvg”——librsvg 的 Python 绑定。

    有一个 Ubuntu python-rsvg 包提供它。用 Google 搜索它的名字很糟糕,因为它的源代码似乎包含在“gnome-python-desktop”Gnome 项目 GIT 存储库中。

    我制作了一个极简主义的“hello world”,将 SVG 渲染到 cairo 表面并将其写入磁盘:

    from django.db import models
    import os
    from PIL import Image
    
    class Image(models.Model):
    """Image upload model"""
    image = models.ImageField(upload_to = get_directory_path, default = 'media/sample.png')
    created_date = models.DateTimeField(auto_now = True)
    
    def __str__(self):
        return str(self.id)
    
    def get_directory_path(instance, filename):
        # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
        file_extension = os.path.splitext(filename)
        if file_extension[1] in ['.jpg','.png','.jpeg','.svg']:
            if file_extension[1] != '.svg':
                filename=file_extension[0]+'.png'
                dir = 'Images'
            else:
    
                import cairo
                import rsvg
    
                img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 640,480)
    
                ctx = cairo.Context(img)
    
                ## handle = rsvg.Handle(<svg filename>)
                # or, for in memory SVG data:
                handle= rsvg.Handle(None, str(<svg data>))
    
                handle.render_cairo(ctx)
                filename=img.write_to_png("svg.png")
                dir = 'Images'
    
        else:
            dir="others"
        path = '{0}/{1}'.format(dir, filename)
        return path
    

    更新:截至 2014 年,Fedora Linux 发行版所需的软件包是:gnome-python2-rsvg。上面的 sn-p 列表仍然按原样工作。

    【讨论】:

      【解决方案2】:

      在您的 ImageView 类中,您可以覆盖 form_valid

      class ImageView(CreateView):
      [...]
      def form_valid(self, form):
              uploaded_image = form.instance
              [do your convert code here]
              return super(ImageView, self).form_valid(form)
      

      你也可以使用 post_save 信号。

      【讨论】:

        【解决方案3】:

        这是您可以做的确切方式,如果您遇到任何问题,请回复并投票给我的答案:--

        from django.db import models
        import os
        from PIL import Image
        
        class Image(models.Model):
        """Image upload model"""
        image = models.ImageField(upload_to = get_directory_path, default = 'media/sample.png')
        created_date = models.DateTimeField(auto_now = True)
        
        def __str__(self):
            return str(self.id)
        
        def get_directory_path(instance, filename):
            # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
            file_extension = os.path.splitext(filename)
            if file_extension[1] in ['.jpg','.png','.jpeg']:
                filename=file_extension[0]+'.png'
                dir = 'Images'
            else:
                dir="others"
            path = '{0}/{1}'.format(dir, filename)
            return path
        

        【讨论】:

        • 不,它不起作用。你能解释一下你的代码吗?为什么在条件语句中给出 dir = 'Images' 或 'others' ?
        • 我收到一条错误消息:'NameError: 'get_directory_path' is not defined。'
        • 在你的模型类中使用 get_directory_path 并检查拼写
        • 赋予dir=image或dir=others的目的是为了将image目录中的image和其他目录中的doc文件隔离
        • 我仍然遇到同样的错误:NameError: name 'get_directory_path' is not defined。我认为您应该在调用该方法时传递一些参数。或者,我们可以改用属性方法吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-18
        • 1970-01-01
        • 1970-01-01
        • 2016-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多