Загрузка отдельных изображений через несколько входных данных HTML-форм без форм Django

#python #html #django #image

Вопрос:

Я пытаюсь создавать цифровые визитные карточки — создаю пользовательский визуальный редактор с различными вводами HTML-форм для загрузки различных изображений, таких как профиль, фон, логотип и т.д., Без форм Django. Я могу заставить его работать с бэкэндом Django, который использует два поля — одно для имени изображения, а другое-URL-адрес изображения. Я надеялся повторить этот процесс для каждого изображения, пока не доберусь до раздела слайдера. Я все еще работаю над этим, поэтому дизайн не завершен и использует тестовые данные. Я включил изображение для справки о том, чего я пытаюсь достичь, так же глупо, как и данные теста.

urls.py

 from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^icards/icard/edit/(?P<pk>d )/

views.py

 def icard_edit(request, pk):

    icard = Icard.objects.get(pk=pk)

    if request.method == 'POST':
        try:
            print("Try function reached")
            myfile = request.FILES['myfile']
            bg_myfile = request.FILES['bg_myfile']
            fs = FileSystemStorage()
            filename = fs.save(myfile.name, myfile)
            url = fs.url(filename)
            bg_filename = fs.save(bg_myfile.name, bg_myfile)
            bg_url = fs.url(bg_filename)

            if str(myfile.content_type).startswith("image") amp; str(bg_myfile.content_type).startswith("image"):

                if myfile.size < 5000000 amp; bg_myfile.size < 5000000:

                    b = Icard.objects.get(pk=pk)

                    fss = FileSystemStorage()
                    fss.delete(icard.logo)
                    fss.delete(icard.bg_image)

                    b.name = name
                    b.category = category
                    b.logo = filename
                    b.logo_url = url
                    b.bg_image = bg_filename
                    b.bg_url = bg_url
                    b.feature_one = feature_one

                    b.save()
                    print("func: Icard Data Edit Saved")
                    return redirect('icard_list')

                else:
                    fs = FileSystemStorage()
                    fs.delete(filename)
                    fs.delete(bg_filename)

                    error = "your File is Larger than 5 MB"
                    return render(request, 'back/error.html', {'error': error})

            else:
                fs = FileSystemStorage()
                fs.delete(filename)
                fs.delete(bg_filename)

                error = "Your File is not supported"
                return render(request, 'back/error.html', {'error': error})

        except:
            return redirect('icard_edit')

    return render(request, 'back/icards/icard_edit.html', {'pk': pk, 'icard': icard})
 

back/icards/icard_edit.html

 <form action="{% url 'icard_edit' pk=pk %}"
      method="post"
      enctype="multipart/form-data"
      class="form">
    {% csrf_token %}

    <div class="form-body">
        <div class="form-group">
            <label>Logo Image</label>
            <div class="input-group">

                <div class="custom-file">
                    <input type="file"
                           class="custom-file-input"
                           id="myfile"
                           name="myfile">
                    <label class="custom-file-label"
                           for="myfile">{{ icard.logo_url }}</label>
                </div>
            </div>
        </div>

        <div class="form-group text-right">
            <label><small>Background</small></label>
            <div class="input-group">

                <div class="custom-file text-left">
                    <input type="file"
                           class="custom-file-input"
                           id="bg_myfile"
                           name="bg_myfile">
                    <label class="custom-file-label"
                           for="bg_myfile">{{ icard.bg_url }}
                    </label>
                </div>
            </div>
        </div>
    </div>

    <div class="row">
        <div class="form-group">
            <button type="submit"
                    class="btn btn-outline-success">Submit</button>
        </div>
    </div>
</form>
 

Ошибка:

 Request Method: POST
Request URL: http://127.0.0.1:8000/icards/icard/edit/3/

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/utils/datastructures.py", line 76, in __getitem__
    list_ = super().__getitem__(key)

During handling of the above exception ('myfile'), another exception occurred:
  File "/Volumes/1TB_Rocket/PycharmProjects/ibizcard_v1/icards/views.py", line 341, in icard_edit
    myfile = request.FILES['myfile']
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/utils/datastructures.py", line 78, in __getitem__
    raise MultiValueDictKeyError(key)

During handling of the above exception ('myfile'), another exception occurred:
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Volumes/1TB_Rocket/PycharmProjects/ibizcard_v1/icards/views.py", line 397, in icard_edit
    return redirect('icard_edit')
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/shortcuts.py", line 41, in redirect
    return redirect_class(resolve_url(to, *args, **kwargs))
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/shortcuts.py", line 131, in resolve_url
    return reverse(to, args=args, kwargs=kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/urls/base.py", line 87, in reverse
    return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/urls/resolvers.py", line 677, in _reverse_with_prefix
    raise NoReverseMatch(msg)

Exception Type: NoReverseMatch at /icards/icard/edit/3/
Exception Value: Reverse for 'icard_edit' with no arguments not found. 1 pattern(s) tried: ['icards/icard/edit/(?P<pk>\d )/

введите описание изображения здесь


Комментарии:

1. да это на главной ветке здесь github.com/xxroninCabxx/ibizcards/tree/main

2. Ну, проблема в том, что я должен загрузить и логотип, и фоновое изображение одновременно, иначе это приведет к ошибке. Мне нравится иметь возможность загружать изображения независимо друг от друга, или, если одно из них уже загружено, оно видит его и его не нужно загружать. Поэтому я думаю, что мне нужно переработать код с помощью другого оператора if и try за пределами того места, где он находится сейчас.

Ответ №1:

Используйте request.FILES.get() if инструкции и для обработки необязательных загрузок изображений.

 # myfile = request.FILES['myfile']
# bg_myfile = request.FILES['bg_myfile']

myfile = request.FILES.get('myfile')
bg_myfile = request.FILES.get('bg_myfile')
 
 # fss.delete(icard.logo)
# fss.delete(icard.bg_image)

# b.logo = filename
# b.logo_url = url
# b.bg_image = bg_filename
# b.bg_url = bg_url

if myfile:
    fss.delete(icard.logo)
    b.logo = filename
    b.logo_url = url

if bg_myfile:
    fss.delete(icard.bg_image)
    b.bg_image = bg_filename
    b.bg_url = bg_url
 

Обработка нескольких загрузок изображений

Для более удобной обработки нескольких загрузок изображений:

  • избегайте вложенных if операторов для проверок "не поддерживается" и "слишком большие".
  • сохраняйте файлы после проверок (которые не зависят от сохраненных файлов) вместо удаления в случае сбоя проверок.
  • возвращает имена файлов, которые не прошли проверку, чтобы помочь пользователю узнать, что нужно решить.
  • отложите fs.delete() , чтобы существующие изображения не удалялись в случае icard.save() сбоя.
 try:
    print("Try function reached")
    myfile = request.FILES.get('myfile')
    bg_myfile = request.FILES.get('bg_myfile')

    files_to_check = filter(None, [myfile, bg_myfile])

    filenames_not_supported = [file.name for file in files_to_check if not str(myfile.content_type).startswith("image")]
    if filenames_not_supported:
        error = "Your File is not supported: {}".format(filenames_not_supported)
        return render(request, 'back/error.html', {'error': error})

    filenames_too_large = [file.name for file in files_to_check if file.size >= 5000000]
    if filenames_too_large:
        error = "your File is Larger than 5 MB: {}".format(filenames_too_large)
        return render(request, 'back/error.html', {'error': error})

    fs = FileSystemStorage()
    filenames_to_delete = []

    if myfile:
        filenames_to_delete.append(icard.logo)
        icard.logo = fs.save(myfile.name, myfile)
        icard.logo_url = fs.url(icard.logo)

    if bg_myfile:
        filenames_to_delete.append(icard.bg_image)
        icard.bg_image = fs.save(bg_myfile.name, bg_myfile)
        icard.bg_url = fs.url(icard.bg_image)

    icard.name = name
    icard.category = category
    icard.feature_one = feature_one

    icard.save()
    print("func: Icard Data Edit Saved")

    for filename in filenames_to_delete:
        fs.delete(filename)

    return redirect('icard_list')

except Exception:
    return redirect('icard_edit', pk)
 

Тогда обработка загрузки нового изображения будет простой и понятной:

 profile = request.FILES.get('profile')

# files_to_check = filter(None, [myfile, bg_myfile])
files_to_check = filter(None, [myfile, bg_myfile, profile])

# ...

if profile:
    filenames_to_delete.append(icard.profile)
    icard.profile = fs.save(profile.name, profile)
    icard.profile_url = fs.url(icard.profile)
 

Об NoReverseMatch ошибке

Требуется шаблон URL r'^icards/icard/edit/(?P<pk>d )/$' pk -адреса .

 # return redirect('icard_edit')
return redirect('icard_edit', pk)
 

Комментарии:

1. О, чувак, Аарон, это отлично работает. Оооочень большое вам спасибо, я попробую загрузить и другие изображения позже! Спасибо!

, views.icard_edit, name='icard_edit'),
]
views.py


back/icards/icard_edit.html


Ошибка:


введите описание изображения здесь

Комментарии:

1. да это на главной ветке здесь github.com/xxroninCabxx/ibizcards/tree/main

2. Ну, проблема в том, что я должен загрузить и логотип, и фоновое изображение одновременно, иначе это приведет к ошибке. Мне нравится иметь возможность загружать изображения независимо друг от друга, или, если одно из них уже загружено, оно видит его и его не нужно загружать. Поэтому я думаю, что мне нужно переработать код с помощью другого оператора if и try за пределами того места, где он находится сейчас.

Ответ №1:

Используйте request.FILES.get() if инструкции и для обработки необязательных загрузок изображений.



Обработка нескольких загрузок изображений

Для более удобной обработки нескольких загрузок изображений:

  • избегайте вложенных if операторов для проверок "не поддерживается" и "слишком большие".
  • сохраняйте файлы после проверок (которые не зависят от сохраненных файлов) вместо удаления в случае сбоя проверок.
  • возвращает имена файлов, которые не прошли проверку, чтобы помочь пользователю узнать, что нужно решить.
  • отложите fs.delete() , чтобы существующие изображения не удалялись в случае icard.save() сбоя.

Тогда обработка загрузки нового изображения будет простой и понятной:


Об NoReverseMatch ошибке

Требуется шаблон URL r'^icards/icard/edit/(?P<pk>d )/$' pk -адреса .


Комментарии:

1. О, чувак, Аарон, это отлично работает. Оооочень большое вам спасибо, я попробую загрузить и другие изображения позже! Спасибо!

]
введите описание изображения здесь

Комментарии:

1. да это на главной ветке здесь github.com/xxroninCabxx/ibizcards/tree/main

2. Ну, проблема в том, что я должен загрузить и логотип, и фоновое изображение одновременно, иначе это приведет к ошибке. Мне нравится иметь возможность загружать изображения независимо друг от друга, или, если одно из них уже загружено, оно видит его и его не нужно загружать. Поэтому я думаю, что мне нужно переработать код с помощью другого оператора if и try за пределами того места, где он находится сейчас.

Ответ №1:

Используйте request.FILES.get() if инструкции и для обработки необязательных загрузок изображений.



Обработка нескольких загрузок изображений

Для более удобной обработки нескольких загрузок изображений:

  • избегайте вложенных if операторов для проверок «не поддерживается» и «слишком большие».
  • сохраняйте файлы после проверок (которые не зависят от сохраненных файлов) вместо удаления в случае сбоя проверок.
  • возвращает имена файлов, которые не прошли проверку, чтобы помочь пользователю узнать, что нужно решить.
  • отложите fs.delete() , чтобы существующие изображения не удалялись в случае icard.save() сбоя.

Тогда обработка загрузки нового изображения будет простой и понятной:


Об NoReverseMatch ошибке

Требуется шаблон URL r'^icards/icard/edit/(?P<pk>d )/$' pk -адреса .


Комментарии:

1. О, чувак, Аарон, это отлично работает. Оооочень большое вам спасибо, я попробую загрузить и другие изображения позже! Спасибо!

, views.icard_edit, name=’icard_edit’),
]

views.py


back/icards/icard_edit.html


Ошибка:


введите описание изображения здесь

Комментарии:

1. да это на главной ветке здесь github.com/xxroninCabxx/ibizcards/tree/main

2. Ну, проблема в том, что я должен загрузить и логотип, и фоновое изображение одновременно, иначе это приведет к ошибке. Мне нравится иметь возможность загружать изображения независимо друг от друга, или, если одно из них уже загружено, оно видит его и его не нужно загружать. Поэтому я думаю, что мне нужно переработать код с помощью другого оператора if и try за пределами того места, где он находится сейчас.

Ответ №1:

Используйте request.FILES.get() if инструкции и для обработки необязательных загрузок изображений.



Обработка нескольких загрузок изображений

Для более удобной обработки нескольких загрузок изображений:

  • избегайте вложенных if операторов для проверок «не поддерживается» и «слишком большие».
  • сохраняйте файлы после проверок (которые не зависят от сохраненных файлов) вместо удаления в случае сбоя проверок.
  • возвращает имена файлов, которые не прошли проверку, чтобы помочь пользователю узнать, что нужно решить.
  • отложите fs.delete() , чтобы существующие изображения не удалялись в случае icard.save() сбоя.

Тогда обработка загрузки нового изображения будет простой и понятной:


Об NoReverseMatch ошибке

Требуется шаблон URL r'^icards/icard/edit/(?P<pk>d )/$' pk -адреса .


Комментарии:

1. О, чувак, Аарон, это отлично работает. Оооочень большое вам спасибо, я попробую загрузить и другие изображения позже! Спасибо!