Создайте экран предварительного просмотра в Django

#python #django #django-views #django-templates #frontend

Вопрос:

У меня есть форма Django, которая получает текст (который я копирую из класса Google: кучу комментариев студентов). Я использую эти комментарии для оценки посещаемости студентов. Чего я хочу достичь, так это:

  1. Доступ /insertion/ к URL-адресу через GET пользователь получает форму страницы в качестве ответа, чтобы выбрать класс (class01, class02 и т.д.) И пропустить текст
  2. Когда пользователь нажимает представить в таком виде (метод POST), это перенаправить на тот же /insertion/ URL, но теперь форма будет привязана к данным, прислана, и страницы показывает превью страницы (на основе логической переменной я, проходя через контекста), показывая, что студенты присутствуют, а какие отсутствуют на основе текста прошлого года. На этой странице под текстом типа «если все в порядке, нажмите кнопку»ОК», появится новая кнопка «Отправить».
  3. После нажатия этой кнопки » ОК » будет сгенерирован pdf-файл, и пользователь будет перенаправлен на /files/ URL-адрес, чтобы просмотреть сгенерированный pdf-файл и предыдущий сгенерированный pdf-файл.

views.py

 def insertion(request):

    context = {}

    if request.method == 'GET':
        form = AttendanceDataForm()
        context.update({"form": form})

    if request.method == 'POST':
        form = AttendanceDataForm(request.POST)
        context.update({"form": form})
        if form.is_valid():
            lesson = form.cleaned_data['lesson']
            raw_text = form.cleaned_data['raw_text']
            # Get course students
            course_students = md.Student.objects.filter(course_id=lesson.course_id)
            # Get present students based on raw text informed
            present_students = [s for s in course_students if s.full_name in raw_text]
            # Get absent students based on raw text informed
            absent_students = [s for s in course_students if s.full_name not in raw_text]
            context.update({
                "present_students": present_students,
                "absent_students": absent_students,
                "render_preview": True
            })


    context.update({"active_freq": True})

    return render(request, 'core/insertion.html', context)


def files(request):
    context = {}
    if request.method == 'POST':
    
    # How can I access all expensive calculation I did in the previous view?
        

    context.update({"active_gen": True})

    return render(request, "core/files.html", context)

 

insertion.html

 <div class="row">
    <div class="col-12 col-md-6">
        <h3>Informar Frequência</h3>
        {% crispy form %}
    </div>
    <div class="col-12 col-md-6">
        {% if render_preview %}
            <div class="container">
                <div class="row p-4 bg-white rounded mt-4">
                    <div class="col-12 col-sm-6">
                        <h5>Alunos presentes</h5>
                        <ul class="previewer-list">
                            {% for student in present_students %}
                                <li>{{ student.id }} - {{ student.full_name }}</li>
                            {% endfor %}
                        </ul>
                    </div>
                    <div class="col-12 col-sm-6">
                        <h5>Alunos ausentes</h5>
                        <ul class="previewer-list">
                        {% for student in absent_students %}
                            <li>{{ student.id }} - {{ student.full_name }}</li>
                        {% endfor %}
                        </ul>
                    </div>
                </div>
                <p class="mt-3">If everything's ok, hit the OK button</p>
                <form method="post" action="{% url "core:files" %}">
                    {% csrf_token %}
                    <button type="submit" class="btn btn-primary">OK</button>
                </form>
            </div>
        {% endif %}
    </div>
</div>

 

Я мог бы приступить к реализации 1 и 2, но 3 сейчас-это загадка. Чего я не мог понять, так это того, как я могу получить доступ к дорогостоящим расчетам, которые я делал в insertion представлении в files представлении. Как я могу это сделать?

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

1. Вы можете достичь этого с FormPreview помощью from django-formtools docs

Ответ №1:

Вот решение с использованием session фреймворка.

Мы сохраним вычисления в сеансе и позже получим доступ к этим значениям в другом представлении.

Для начала мы просто сохраним идентификаторы ( pk ) учащихся вместо экземпляров учащихся, потому что они не сериализуемы в формате JSON [См. Примечание ниже].

 def insertion(request):
    # do expensive calucations ...

    present_ids = [s.pk for s in present_students]
    absent_ids = [s.pk for s in absent_students]

    request.session['attendance_data'] = {
        'present_ids': present_ids,
        'absent_ids': absent_ids
    }


def files(request):
    attendance_data = request.session.get('attendance_data')

    if not attendance_data:
        # show error or something else ...
        pass

    present_students = md.Student.objects.filter(
        pk__in=attendance_data['present_ids']
    )
    
    absent_students = md.Student.objects.filter(
        pk__in=attendance_data['absent_ids']
    )

    # generate the pdf ...
 

Примечание: При желании вы также можете сохранить экземпляры учащихся в сеансе, но вам придется изменить SESSION_SERIALIZER настройки, чтобы использовать PickleSerializer . См.Примечания о сериализации сеанса.

Ответ №2:

Вы можете отправить первичные ключи в виде данных формы в скрытых полях. Просто выберите подходящий разделитель на основе вашего первичного ключа (например, не разделяйте дефисом, если вы используете первичный ключ GUID).

 <form method="post" action="{% url "core:files" %}">
    {% csrf_token %}
    <input type="hidden" 
           name="present" 
           value="{% for s in present_students %}{{ s.pk }},{% endfor %}"
    >
    <input type="hidden"
           name="absent" 
           value="{% for s in absent_students %}{{ s.pk }},{% endfor %}"
    >
    <button type="submit" class="btn btn-primary">OK</button>
</form>
 

Затем в представлении вы можете выбрать PKS в представлении из данных формы, а затем запросить.

 def files(request):
    context = {}
    if request.method == 'POST':
        present_pks = request.POST.pop('present').split(',')[:-1]
        absent_pks = request.POST.pop('absent').split(',')[:-1]
        # do type conversions if needed
        ...

        # Because we already have the pks separated, we can combine them
        # for the query in order to do just 1 query
        course_students = md.Student.objects.filter(pk__in=present_pks   absent_pks).all()
        absent_students = []
        present_students = []
        for student in course_students:
            if student.pk in absent_pks:
                absent_students.append(student)
            else:
                present_students.append(student)