8

複数の ImageFields を持つ Django モデルがあります。

私が設定したModelAdminクラスでsave_as = True、つまり、管理ページには「新規として保存」ボタンがあり、既存のアイテムを複製して新規として保存できます。

ただし、このボタンを使用すると、ImageFields は複製されず、新しいアイテムでは空白のままになります。

POST リクエストを見ると、投稿データでこれらのフィールドが空白になっていることがわかります。

Model クラスの save メソッドをオーバーライドして、古いオブジェクトから自分で画像をコピーすることを考えました。しかし、私が把握できる限り、オブジェクトが「新品として」保存されていることを伝える方法はありません。また、古いアイテムのIDを持っていないようなので、古い画像を取得できません。

これらの画像フィールドも複製する方法はありますか?

編集: リクエストによりサンプルコードを追加しました。

モデルが 1 つだけのミニマルなアプリを作成しました。確認済みの問題がまだ発生する。

サンプルの models.py:

from django.db import models

class Person(models.Model):
    face_image = models.ImageField(upload_to='images', 
                                   null=False, 
                                   blank=True)

サンプル admin.py:

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

class PersonAdmin(admin.ModelAdmin):
    save_as = True

admin.site.register(Person, PersonAdmin)
4

5 に答える 5

9

この応答に基づいて、同じ結果を達成するためのより一般的な方法を次に示します。

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()

これは、任意のモデルおよび任意のファイル タイプで機能するはずです。また、フォームやテンプレートを編集する必要もありません。これは、プル リクエストがマージされると必要ない回避策です: https://github.com/django/django/pull/2246

于 2014-06-11T11:41:16.060 に答える
7

私はいくつかの回避策を見つけることができました:

元の管理フォーム(こちらを参照)をオーバーライドして、「新規保存」POST リクエストに古いモデルの ID も含めるようにしました。そのモデルの特別な管理者を作成し、その中に非表示の入力を追加することでそれを行いました:

<input type="hidden" name="my_objectid" value="{{ object_id }}">

その後、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)
于 2013-09-03T15:44:56.000 に答える
3

これとまったく同じ問題を説明するチケットは次の とおりです。

このバグを修正する 2014 年 2 月 9 日からのプル リクエストがあります。早く合併してほしい。

于 2014-02-09T20:57:36.140 に答える