Как я могу сохранять файлы изображений в Django

  1. Я хочу получить несколько групп изображений в одной форме и сохранить их. Я хочу сохранить каждую группу изображений с одинаковым основным заголовком и разными заголовками. Как я могу сохранить и нацелить файлы изображений в файле views.py?

  2. Я не передавал форму запросу из views.py, потому что пользователь мог добавлять и удалять содержимое. Есть ли способ использовать тег формы, когда я хочу получить данные, количество которых мне неизвестно?

    .

  3. enter image description here

    views.py

    def debate_create(request):
        if request.method == "POST":
            content = request.POST.items()
            for k,v in content:
                if k == 'sup_title':
                    sup_title = SuperTitle()
                    sup_title.author = request.user
                    sup_title.super_title = v
                    sup_title.save()
                    sup_title_id = sup_title.id
                elif 'img' not in k and 'opt' not in k and 'section' in k:
                    sub_title = Subtitle()
                    sub_title.super_title = get_object_or_404(SuperTitle, pk = sup_title_id)
                    sub_title.sub_title = v
                    sub_title.save()
                elif 'img' in k and v != '':
                    stg = Images()
                    # imgs = request.FILES.getlist("?????")
                    # for image in imgs
                    stg.sub_title = get_object_or_404(Subtitle, pk = sub_title.id)
                    stg.save()
                elif 'section' in k and 'opt' in k:
                    opt = SelectOption()
                    opt.sub_title = get_object_or_404(Subtitle, pk = sub_title.id)
                    opt.option = v
                    opt.save()
            return render(request, 'polls/test.html')
        else:
            pass
    

    html

    <form method="POST" id="debate_form" action="{% url 'polls:debate_create' %}">
            {% csrf_token %}
            <input type='text' name='sup_title' placeholder='제목'>
            <div id="form_container">
                <section id='section_1'>
                    <input type="text" name="section_1">
                    <input type="file" name="img_section_1" multiple>
                    <div id="section_1_div">
                        <input type="text" name="section_1_opt_1" value="찬성">
                        <input type="text" name="section_1_opt_2" value="반대">
                    </div>
                    <input type="button" value="선택지 추가하기" onclick='add_option(this.id)' id="section_1">
                    <input type="button" value="선택지 삭제하기" onclick='sub_option(this.id)' id="section_1">
                </section>
            </div>
            <input type="button" value='질문 추가하기' onclick='add_content()'>
            <input type="button" value='질문 삭제하기' onclick='sub_content()'>
            <input type="submit">
        </form>
    

    В Django, конечно, есть способ достичь этого, и он называется model formsets.

    Предположим, что ваши модели определены следующим образом

    # models.py
    from django.db import models
    
    class SuperTitle(models.Model):
        super_title = models.CharField(max_length=50)
        author = models.ForeignKey(User, on_delete=models.PROTECT)
    
    class Subtitle(models.Model):
        super_title = models.ForeignKey(SuperGroup, on_delete=models.CASCADE)
        subtitle = models.CharField(max_length=50)
        image = models.ImageField(upload_to='path/to/uploads/')
        # I changed opt from a model to a field of Subtitle, 
        # since it has only 2 values in your example.
        # Feel free to change it back. 
        opt = models.IntegerField(choices=[(1,"찬성"), (2, "반대")])
    

    Тогда в ваших взглядах

    # views.py
    from django import forms
    from .models import SuperTitle, Subtitle
    
    def debate_create(request):
        SuperTitleForm = forms.modelform_factory(SuperTitle, fields=['super_title'])
        SubtitleFormSet = forms.modelformset_factory(Subtitle, fields=['subtitle', 'image', 'opt'])
        if request.method == 'POST':
            super_title_form = SuperTitleForm(request.POST)
            # NOTE uploaded files are available in request.FILES
            subtitle_formset = SubtitleFormSet(request.POST, request.FILES, queryset=Subtitle.objects.none())
            if super_title_form.is_valid() and subtitle_formset.is_valid():
                super_title = super_title_form.save()
                subtitles = subtitle_forms.save(commit=False)
                for subtitle in subtitles:
                    subtitle.super_title = super_title
                Subtitle.objects.bulk_create(subtitles)
        else:
            super_title_form = SuperTitleForm()
            subtitle_formset = SubtitleFormSet(queryset=Subtitle.objects.filter(super_title__author=request.user))
        context = {
            'super_title_form': super_title_form,
            'subtitle_formset': subtitle_formset,
        }
        return render(request, 'polls/test.html', context)
    

    Обратите внимание, что я передаю queryset=Subtitle.objects.none() в formset. Это заставит formset работать только с новыми субтитрами. Если вы хотите редактировать или даже удалять существующие субтитры, измените queryset, например, на queryset=Subtitle.objects.filter(super_title__author=request.user). Django рекомендует упорядочить queryset.

    И, вероятно, вам нужно сделать что-то подобное super_title_form, чтобы он знал, какой суперзаголовок вы редактируете.

    Обратите также внимание, что при ручном рендеринге набора форм есть два обязательных скрытых поля:

    {{ subtitle_formset.management_form.TOTAL_FORMS }}
    {{ subtitle_formset.management_form.INITIAL_FORMS }}
    

    Лично я люблю ставить эти 2 рядом с {% csrf_token %}, чтобы не забыть их.

    Отредактировано: еще одна вещь для вашего первого вопроса

    Вы можете настроить путь к хранилищу изображений следующим образом

    def subtitle_image_path(instance, filename):
        return f'uploads/{instance.super_title.id}/{filename}'
    class Subtitle(models.Model):
        ..
        image = models.ImageField(upload_to=subtitle_image_path)
    

    и django автоматически сохранит изображение, скажем, в uploads/1/img01.png при вызове form.save() (или subtitle.save() в данном случае).

    Вернуться на верх