Django"另存为新"并保留图像字段

Zap*_*tta 7 django

我有一个带有多个ImageFields的Django模型.

在我设置的ModelAdmin类中save_as = True,这意味着管理页面有一个"另存为新"按钮,该按钮允许复制现有项目并将其另存为新项目.

但是,使用此按钮时,ImageFields不会重复,并且在新项目上保留为空白.

查看POST请求,我发现这些字段在发布数据中是空白的.

我已经考虑过覆盖Model类的save方法,并自己复制旧对象中的图像.但据我所知,我没办法告诉对象是"新的".我似乎也没有旧项目的ID,所以我无法从中获取旧图像.

有没有办法让这些图像字段重复?

编辑: 按请求添加示例代码.

仅使用一个模型创建了一个简约的应用程序.验证问题仍然存在.

models.py示例:

from django.db import models

class Person(models.Model):
    face_image = models.ImageField(upload_to='images', 
                                   null=False, 
                                   blank=True)
Run Code Online (Sandbox Code Playgroud)

示例admin.py:

from django.contrib import admin
from testapp.models import Person

class PersonAdmin(admin.ModelAdmin):
    save_as = True

admin.site.register(Person, PersonAdmin)
Run Code Online (Sandbox Code Playgroud)

Zap*_*tta 7

我找到了一些解决方法:

我已经覆盖了原始的管理表单(请参阅此处),以便在"另存为新的"POST请求中包含旧的模型ID.我通过为该模型创建一个特殊的管理员,并在其中添加一个隐藏的输入来做到这一点:

<input type="hidden" name="my_objectid" value="{{ object_id }}">
Run Code Online (Sandbox Code Playgroud)

之后我让ModelAdmin类加载了特定的html.然后我重写AdminModel类的save_model方法,这样它也会复制图像.

所以新的admin.py应如下所示:

from django.contrib import admin
from testapp.models import Person

from django.db.models.fields.files import ImageFieldFile #added to be used later

class PersonAdmin(admin.ModelAdmin):
    save_as=True
    change_form_template = 'admin/person_change_form.html';
    def save_model(self, request, obj, form, change):       

        if '_saveasnew' in request.POST: #Django always sends this when "Save as new is clicked"
            origObjId = request.POST['my_objectid']; #Get the ID that is new posted after overriding the form. 
            originalPerson = Person.objects.get(id=origObjId); #Use the Id to get the old object
            for prop, value in vars(originalPerson).iteritems(): #iterate through all it's properties
                if isinstance(getattr(originalPerson,prop), ImageFieldFile): #if the property is an Image (don't forget to import ImageFieldFile!)
                    setattr(obj,prop,getattr(originalPerson,prop)) #Copy it!

        obj.save()

admin.site.register(Person, PersonAdmin)
Run Code Online (Sandbox Code Playgroud)


小智 6

这个响应的基础上,这是一种更通用的方法来实现相同的结果:

from django.core.urlresolvers import resolve
from django.db.models.fields.files import FieldFile

class PersonAdmin(admin.ModelAdmin):
    save_as = True

    def save_model(self, request, obj, form, change):
        # Django always sends this when "Save as new is clicked"
        if '_saveasnew' in request.POST:
            # Get the ID from the admin URL
            original_pk = resolve(request.path).args[0]
            # Get the original object
            original_obj = obj._meta.concrete_model.objects.get(id=original_pk)

            # Iterate through all it's properties
            for prop, value in vars(original_obj).iteritems():
                # if the property is an Image (don't forget to import ImageFieldFile!)
                if isinstance(getattr(original_obj, prop), FieldFile):
                    setattr(obj,prop,getattr(original_obj, prop)) # Copy it!
        obj.save()
Run Code Online (Sandbox Code Playgroud)

这适用于任何模型和任何文件类型.它也不需要编辑表单或模板.这是拉出请求合并后不应该需要的解决方法:https://github.com/django/django/pull/2246.