Django загрузка нескольких изображений
Здравствуйте, я довольно новичок в Django и пытаюсь позволить пользователю загружать несколько изображений в проект. Документация Django enter link description here показывает, как это сделать в generell, но я думаю, что я отображаю свою форму иначе, чем они это делают. Поэтому я не знаю, как добавить атрибут 'multiple' в поле ввода. Кроме того, у них есть дополнительный класс в их views.py и внутри него функция. Спасибо за помощь.
views.py
def createProject(request):
form = ProjectForm()
if request.method == 'POST':
form = ProjectForm(request.POST, request.FILES)
if form.is_valid():
project = form.save(commit=False)
project.save()
context = {'form':form}
return render(request, 'projects/project_form.html', context)
models.py
class Project(models.Model):
title = models.CharField(max_length=200)
featured_images = models.ImageField(null=True, blank=True, default="default.jpg")
forms.py
class ProjectForm(ModelForm):
class Meta:
model = Project
fields = ['title', 'featured_images']
project_form.html
<form class="form" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="form__field">
<label for="formInput#text">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
</form>
Сначала вам нужно немного подкорректировать форму, чтобы она позволяла загружать несколько файлов:
# forms.py
class ProjectForm(ModelForm):
class Meta:
featured_images = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
model = Project
fields = ['title', 'featured_images']
Затем в представлении нужно захватить несколько записей:
# views.py
def createProject(request):
form = ProjectForm()
if request.method == 'POST':
form = ProjectForm(request.POST, request.FILES.getlist('featured_images'))
if form.is_valid():
project = form.save(commit=False)
project.save()
context = {'form':form}
return render(request, 'projects/project_form.html', context)
Пожалуйста, дайте мне знать, если это сработает.
В Django существует несколько способов привязать несколько изображений к одному полю. Мне нравится следующий способ:
- Сначала создайте две модели, одну для того, что вам нужно (в данном случае Project), а другую для изображений.
class MyModel(models.Model):
field = models.CharField(max_lenght=255)
class MyModelImage(models.Model):
image = models.ImageField(upload_to="/where_you_want_to")
field = models.ForeignKey(MyModel,related_name="images",on_delete=models.CASECADE)
- Затем, используя Django inline formset, вы можете добавить несколько изображений одновременно.
Надеюсь, это вам поможет
Исходя из того, что вы используете представление на основе функций, вам стоит последовать руководству по загрузке нескольких изображений от "Very Academy", хотя он не объяснил некоторые вещи и оставил вас разбираться, как реализовать это в реальном проекте. Я покажу, что работает сейчас, вдохновленный этим учебником:
forms.py (скрипт, определенный в папке app)
from *APP*.models import DashboardModel, Image
#The main form in forms.py
class RecordForm(ModelForm):
class Meta:
model = DashboardModel # (.....whatever you named it)
fields = (
#...all fields you defined in your database model
)
labels = {
#....labels including:
"img_name" : "",
"img_slug" : "",
"img_description" : "",
}
widgets = {
#....widgets including:
"img_name" : forms.TextInput(attrs={'class':'form-control', 'placeholder':'Name'}),
"img_slug" : forms.TextInput(attrs={'class':'form-control', 'placeholder':'Slug'}),
"img_description" : forms.Textarea(attrs={'class':'form-control', 'placeholder':'Description'}),
}
class ImageForm(forms.ModelForm):
class Meta:
model = Image
fields = ("image",)
labels = {"image" : "Image upload"}
widgets = {
'image': forms.ClearableFileInput(attrs={'class': 'file-upload-input', 'id': 'file-selector',"multiple": True})
}
models.py
class DashboardModel(models.Model):
#...all your main database fields, NOT including any image field
#A new model for creation of image associations:
class Image(models.Model):
project = models.ForeignKey(DashboardModel, on_delete=models.CASCADE)
image = models.ImageField()
def __str__(self):
return self.image.url # return something meaningful instead of "object"
settings.py
import os
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"
urls.py
urlpatterns = [
...your url paths
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
views.py
def create_project(request):
if request.method == "POST":
form = ProjectForm(request.POST)
files = request.FILES.getlist("image") # get a list of images from the image association (Image model in models.py)
if form.is_valid():
f = form.save(commit=False)
f.user = request.user
f.save()
for i in files:
Image.objects.create(project=f, image=i) #Check the Image model in models.py, this infers the fields "project" and "image"
return HttpResponseRedirect(" *your database dashboard page* ")
else:
print(form.errors)
else:
form = ProjectForm()
imageform = ImageForm()
return render(request, "create_project.html", {"form": form, "imageform": imageform})
create_project.html в папке app/templates/app
Вам нужно будет определить html-форму (как вы, возможно, уже сделали):
<form id="post_form" method="post" action="" enctype="multipart/form-data">
Затем внутри формы:
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{{ imageform.label }}
{{ form.img_name }} <br />
{{ form.img_slug }} <br />
{{ form.img_description }} <br />
{{ imageform.management_form }}
{% for form in imageform %}
{{ form }}
{% endfor %}
Поиск изображений работает путем доступа к набору изображений (получение URL-адресов изображений в данном случае):
_set - это кверисет, который обращается к изображениям на записи базы данных
record - это контекстное имя для моей основной модели (DashboardModel)
{% for path in record.image_set.all %}
{% if not forloop.first %}
<br>
{% endif %}
<img src="{{ path }}" width='600'>
{% endfor %}
Обновление изображений новыми изображениями (новая функция представления "update" в views.py) осуществляется путем добавления некоторой дополнительной логики (вы можете творчески подойти к этому):
d = DashboardModel.objects.get(id=pk)
if(d.image_set.all()): #if images are present in the record
if(files): #if new files are loaded
d.image_set.all().delete() #delete the previous images
for i in files:
Image.objects.update_or_create(project=f, image=i) #create the new images
else:
pass
else: #no images already present in the record
for i in files:
Image.objects.create(project=f, image=i)