如何以编程方式在 django oscar 中添加产品图片?
How to programatically add product images in django oscar?
我目前正在以编程方式将产品导入我的产品目录,但是,我无法为每个产品上传图片。这是我的代码的样子:
# frobshop/custom_utils/product_importer.py
from oscar.apps.catalogue.models import Product
...
for product in my_product_import_list:
...
product_entry = Product()
product_entry.title = my_product_title
product_entry.product_class = my_product_class
product_entry.category = my_category
product_entry.primary_image = "product_images/my_product_filename.jpg"
product_entry.save()
使用开发服务器查看时,产品名称和产品class等详细信息已成功保存,但是我不确定如何为每个产品设置图像。
整个 product_images
文件夹最初位于我的 media
目录之外,但由于我没有得到任何结果,我将我的图像的整个文件夹复制粘贴到 media
目录,但仍然没有结果。我假设跳过了相当多的步骤,也许有一个关于如何在媒体目录中排列图像的约定。但是,我不确定在哪里可以找到这些步骤和约定。
这是我的 settings.py
文件中处理我安装的应用程序、媒体目录和静态文件的部分:
# frobshop/frobshop/settings.py
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.flatpages',
'compressor',
'widget_tweaks',
] + get_core_apps(['custom_apps.shipping', 'custom_apps.payment', 'custom_apps.checkout'])
...
STATIC_ROOT = 'static'
STATIC_URL = '/static/'
MEDIA_ROOT = 'media'
MEDIA_URL = '/media/'
为进一步说明,这是我的 urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
from oscar.app import application
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^i18n/', include('django.conf.urls.i18n')),
path('admin/', admin.site.urls),
url(r'', application.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
我想你可以这样使用 File
class:
from django.core.files import File
for product in my_product_import_list:
...
product_entry = Product()
product_entry.title = my_product_title
product_entry.product_class = my_product_class
product_entry.category = my_category
image = File(open("product_images/my_product_filename.jpg", 'rb'))
product_entry.primary_image = image
product_entry.save()
更新
可能你应该在设置中使用 OSCAR_MISSING_IMAGE_URL
:
OSCAR_MISSING_IMAGE_URL = "product_images/my_product_filename.jpg" # relative path from media root
或者,您可以使用 ProductImage
,像这样:
from oscar.apps.catalogue.models import ProductImage
product_entry = Product()
product_entry.title = my_product_title
product_entry.product_class = my_product_class
product_entry.category = my_category
product_entry.save()
product_image = ProductImage()
image = File(open("product_images/my_product_filename.jpg", 'rb'))
product_image.original = image
product_image.caption = "Some Caption"
product_image.product = product_entry
product_image.save()
因为 ProductImage
与 Product
模型有 ForignKey 关系,而 primary_image
是 Product
模型中的一个方法,它从 ProductImage 模型中获取图像,并且 returns第一个(ProductImage
对象按display_order
字段排序)
不完全确定这对任何人有多大帮助,但我在使用@ruddra 的 时收到 SuspiciousFileOperation
异常,即使我在媒体根目录中使用临时文件。 .
File "/Users/user/Documents/project/venv/lib/python3.7/site-packages/django/core/files/utils.py", line 19, in validate_file_name
"Detected path traversal attempt in '%s'" % name
django.core.exceptions.SuspiciousFileOperation: Detected path traversal attempt in '/Users/user/Documents/project/media/images/tmp6xem6hvs'
通过先保存图像(从 this SO answer 得到的想法),然后保存产品图像来修复:
import tempfile
from django.core.files.images import ImageFile
...
lf = tempfile.NamedTemporaryFile(dir='media')
f = open('<full_path_to_project>/media/images/my_product_filename.jpg', 'rb')
lf.write(f.read())
image = ImageFile(lf)
product_image = ProductImage()
product_image.caption = "some caption"
product_image.product = product_entry
product_image.original = image
product_image.original.save('my_product_filename.jpg', image) # <-----
product_image.save()
...
我目前正在以编程方式将产品导入我的产品目录,但是,我无法为每个产品上传图片。这是我的代码的样子:
# frobshop/custom_utils/product_importer.py
from oscar.apps.catalogue.models import Product
...
for product in my_product_import_list:
...
product_entry = Product()
product_entry.title = my_product_title
product_entry.product_class = my_product_class
product_entry.category = my_category
product_entry.primary_image = "product_images/my_product_filename.jpg"
product_entry.save()
使用开发服务器查看时,产品名称和产品class等详细信息已成功保存,但是我不确定如何为每个产品设置图像。
整个 product_images
文件夹最初位于我的 media
目录之外,但由于我没有得到任何结果,我将我的图像的整个文件夹复制粘贴到 media
目录,但仍然没有结果。我假设跳过了相当多的步骤,也许有一个关于如何在媒体目录中排列图像的约定。但是,我不确定在哪里可以找到这些步骤和约定。
这是我的 settings.py
文件中处理我安装的应用程序、媒体目录和静态文件的部分:
# frobshop/frobshop/settings.py
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.flatpages',
'compressor',
'widget_tweaks',
] + get_core_apps(['custom_apps.shipping', 'custom_apps.payment', 'custom_apps.checkout'])
...
STATIC_ROOT = 'static'
STATIC_URL = '/static/'
MEDIA_ROOT = 'media'
MEDIA_URL = '/media/'
为进一步说明,这是我的 urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
from oscar.app import application
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^i18n/', include('django.conf.urls.i18n')),
path('admin/', admin.site.urls),
url(r'', application.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
我想你可以这样使用 File
class:
from django.core.files import File
for product in my_product_import_list:
...
product_entry = Product()
product_entry.title = my_product_title
product_entry.product_class = my_product_class
product_entry.category = my_category
image = File(open("product_images/my_product_filename.jpg", 'rb'))
product_entry.primary_image = image
product_entry.save()
更新
可能你应该在设置中使用 OSCAR_MISSING_IMAGE_URL
:
OSCAR_MISSING_IMAGE_URL = "product_images/my_product_filename.jpg" # relative path from media root
或者,您可以使用 ProductImage
,像这样:
from oscar.apps.catalogue.models import ProductImage
product_entry = Product()
product_entry.title = my_product_title
product_entry.product_class = my_product_class
product_entry.category = my_category
product_entry.save()
product_image = ProductImage()
image = File(open("product_images/my_product_filename.jpg", 'rb'))
product_image.original = image
product_image.caption = "Some Caption"
product_image.product = product_entry
product_image.save()
因为 ProductImage
与 Product
模型有 ForignKey 关系,而 primary_image
是 Product
模型中的一个方法,它从 ProductImage 模型中获取图像,并且 returns第一个(ProductImage
对象按display_order
字段排序)
不完全确定这对任何人有多大帮助,但我在使用@ruddra 的 SuspiciousFileOperation
异常,即使我在媒体根目录中使用临时文件。 .
File "/Users/user/Documents/project/venv/lib/python3.7/site-packages/django/core/files/utils.py", line 19, in validate_file_name
"Detected path traversal attempt in '%s'" % name
django.core.exceptions.SuspiciousFileOperation: Detected path traversal attempt in '/Users/user/Documents/project/media/images/tmp6xem6hvs'
通过先保存图像(从 this SO answer 得到的想法),然后保存产品图像来修复:
import tempfile
from django.core.files.images import ImageFile
...
lf = tempfile.NamedTemporaryFile(dir='media')
f = open('<full_path_to_project>/media/images/my_product_filename.jpg', 'rb')
lf.write(f.read())
image = ImageFile(lf)
product_image = ProductImage()
product_image.caption = "some caption"
product_image.product = product_entry
product_image.original = image
product_image.original.save('my_product_filename.jpg', image) # <-----
product_image.save()
...