3

背景: SellingItem と SellingItemImages の 2 つのモデルがあります。SellingItemImages には、複数のファイルを取得できるカスタム FileField があります。1 つの要素 (enctype="multipart/form-data") の下に 2 つのフォーム (itemform と imageform) を配置することで、ユーザーが複数の画像をアップロードできるようにしました。ここで、クライアント側の画像の最適化とより良い UI を組み込みたいと考えています。filepond を試してみましたが、いくつかの課題に直面しています。この投稿を整理しました

  1. filepond なしで django コードを表示する
  2. filepond what でコードを表示する
  3. これまでにfilepondで達成しました
  4. 次に何をすべきかについての質問

** 1) filepond なしの django コード。** models.py

# models.py
class SellingItem(models.Model):
    seller = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    description = models.CharField(max_length= 500, null=True, blank=True)
    price = models.IntegerField(default=0)


class SellingItemImages(models.Model):
    sellingitem = models.ForeignKey(SellingItem, default = None, on_delete=models.CASCADE, related_name='images')
    image = ContentTypeRestrictedFileField(content_types=['image/png', 'image/jpeg','image/jpg'],blank=True, 
                                   max_upload_size=5242880) 
    #ContentTypeRestrictedFileField is a custom FileField. 

ここにforms.pyがあります

class SellingItemForm(forms.ModelForm):

    class Meta:
        model = SellingItem
        fields = ('name', 'description', 'price')

class SellingItemImagesForm(forms.ModelForm):

    class Meta:
        model = SellingItemImages
        fields= ('image',)
        widgets = {
            'image': forms.FileInput(attrs={'multiple':True,}),
        }

これがviews.pyです

@login_required
def post_newitem(request):

    if request.method == 'POST':

        itemform = SellingItemForm(request.POST)
        imageform = SellingItemImagesForm(request.POST, request.FILES)

        if '_cancel' in request.POST:
            itemform = SellingItemForm()
            imageform = SellingItemImagesForm()
            return render(request, 'market/post_newitem.html',
                  {'itemform': itemform, 'imageform': imageform})

        else:
            if '_publish' in request.POST:  
                print('hit publish')  
                if itemform.is_valid() and imageform.is_valid():
                    print('two forms are valid')
                    sellingitem = itemform.save(commit=False)
                    sellingitem.seller = request.user
                    sellingitem.published_date = timezone.now()
                    sellingitem.save()

                    files = request.FILES.getlist('image')
                    for f in files:
                        photo = SellingItemImages(sellingitem=sellingitem, image=f)
                        photo.save()
                    return redirect('market_home')    
                else:
                    print(itemform.errors, imageform.errors)    

    else:
        itemform = SellingItemForm()
        imageform = SellingItemImagesForm(request.POST)
    return render(request, 'market/post_newitem.html',
                  {'itemform': itemform, 'imageform': imageform})

ここにテンプレート post_newitem.html があります。ここでは、1 つの要素の下に 2 つのフォームを配置します。

{% extends 'market/marketbase.html' %}
{% block content %}
    <form id="post_form" method="post" action="" enctype="multipart/form-data">

    {% csrf_token %}

    {% for hidden in itemform.hidden_fields %}
        {{ hidden }}
    {% endfor %}

    {% load widget_tweaks %}
        <table>
            <tr>
                <td>{{ itemform.name |add_class:"name_form_field"}}</td>
            </tr>
            <tr>
                <td>{{ itemform.description |add_class:"description_form_field" }}</td>
            </tr>
            <tr>
                <td>{{ itemform.price |add_class:"price_form_field" }}</td>
            </tr>

        {% for hidden in imageform.hidden_fields %}
            {{ hidden }}
        {% endfor %}
            <tr>
                <td>
                    {{ imageform.image |add_class:"image_form_field" }}
                </td>
            </tr>
        </table>

    <input class='edit-delete-buttons' type="submit" name="_publish">
    <input class='edit-delete-buttons' type="submit" name="_cancel">
    </form>
{% endblock %}

上記のコードは、ユーザーが複数の画像をアップロードできるようにするために機能します。前述のように、より優れた UI とクライアント側の画像の最適化を実現するために、この素​​敵な JavaScript ライブラリである filepond に目を向けました。

2) filepond を使用したコード

<script>
document.addEventListener('DOMContentLoaded', function() {

    // Create FilePond object
    const inputElement = document.querySelector('input[type="file"]');
    const pond = FilePond.create(inputElement, {
        // track addfile event
        onaddfile: (err, fileItem) => {
        console.log(err, fileItem.getMetadata('resize'));
        },
        // to see whether all files are processed
        onprocessfiles: () => {
            console.log('process finished for all files');
        },
        // show when a file is reverted
        onprocessfilerevert: (fileItem) => {
            console.log(fileItem + 'is reverted');
        },

    });
});

    FilePond.registerPlugin(
        FilePondPluginImagePreview,
        FilePondPluginImageCrop,
        FilePondPluginImageTransform,
        FilePondPluginFileValidateType,
        FilePondPluginImageResize);

    var csrf_token="{{ csrf_token }}";

    FilePond.setOptions({
        imagePreviewHeight: 100,
        allowMultiple: true,
        imageCropAspectRatio: 1,
        imageResizeTargetWidth: 256,
        imageResizeMode: 'contain',
        imageTransformOutputQuality: 80,
        maxFiles: 4,

        server: {
            // url, none, because endpoints located on the same server
            process: {
                headers: {"X-CSRFToken":csrf_token,},
                url: '/media/',
                method: 'POST',
            },
            revert: {
                headers: {
                "X-CSRFToken":csrf_token,
                },
                url: '/media/',
                method: 'DELETE',
            },
            fetch: null,
            load: null,
        }
        });
    </script>

3) これまでに filepond で達成したこと

上記のコードで、できました。a. filepond ドロップ ドラッグ エリアを表示します。画像プレビューを表示 c.次の画像に示すように、アップロードが完了したことを示す filepond d. Chrome 開発ツール コンソールで、「すべてのファイルのプロセスが終了しました」と表示される

2 つのファイルを選択した後の filepond ドロップ領域を示す画像

4) 次に何をすべきかについての質問

a: サーバー関連:「アップロードが完了しました」と表示された緑色のハイライトはユーザー向けであることを理解しています。これは、必ずしもファイルがサーバーにアップロードされることを意味するわけではありません。

ファイルはサーバーにアップロードされましたか? 私のサーバー構成です。正しい?ファイルが (コンソールを使用して) サーバーにアップロードされているかどうかを知るにはどうすればよいですか?

b: django 関連: ファイルがサーバーにアップロードされたら、これらのファイルを取得して適切な django モデル (私の場合、SellingItemsImages) を指すにはどうすればよいですか?

この投稿に示されているように files=request.FILES.getlist('filepond') を試しましたが、ファイルは空のリストを返しました。これがこのスニペットが機能しないためなのか、それとも最初からファイルをアップロードしていないためなのかはわかりません。

c: django フォーム関連: 背景で述べたように、2 つのフォームがあり、1 つは名前、価格などを含む通常のフォームです。画像をアップロードするための別のもの。filepond がなければ、1 つの post_newitem ビューで 1 つの送信ボタンを使用して両方のフォームを送信していました。filepond では、いくつかのオプションがあると思います。- オプション 2: filepond に (transformplugin を介して) 画像を最適化し、画像とその他のフォーム領域 (名前、価格など) を FormData として送信します。

これら 2 つのオプションの長所と短所、およびこれら 2 つのオプションをどのように進めていくかについて、何らかの情報を得たいと考えています。

4

1 に答える 1