"Видеоурок"

Код на Гитхабе

В этом видео мы собираемся закончить нашу систему заказов, добавив несколько полей для имени, электронной почты и адреса. Мы также добавим модальное окно с просьбой подтвердить свой заказ перед отправкой. Наконец, мы добавим функцию отправки пользователю электронного письма с подтверждением после отправки заказа. Это даст нам гораздо больше функциональности для системы заказов, что сделает ее более удобной для пользователя, а также позволит получить некоторые важные детали, которые мы не получили в прошлый раз.

Во-первых, нам нужно обновить наш файл models.py для этих дополнительных полей:

class OrderModel(models.Model):
    created_on = models.DateTimeField(auto_now_add=True)
    price = models.DecimalField(max_digits=7, decimal_places=2)
    items = models.ManyToManyField('MenuItem', related_name='order', blank=True)
    name = models.CharField(max_length=50, blank=True)
    email = models.EmailField(max_length=50, blank=True)
    street = models.CharField(max_length=50, blank=True)
    city = models.CharField(max_length=50, blank=True)
    state = models.CharField(max_length=15, blank=True)
    zip_code = models.IntegerField(blank=True, null=True)
    def __str__(self):
        return f'Order: {self.created_on.strftime("%b %d %Y %I:%M %p")}'

Теперь, когда эти поля добавлены, давайте перейдем к нашему шаблону orders.html и добавим несколько полей внизу перед отправкой и сразу после окончания цикла for для наших напитков:

<div class="form-group pt-3">
                    <label for="name">Full Name</label>
                    <input required class="form-control" type="text" placeholder="Your Name" name="name" />
                </div>
                <div class="form-group pt-3">
                    <label for="email">Email Address</label>
                    <input required class="form-control" type="text" placeholder="[email protected]" name="email" />
                </div>
                <div class="form-group pt-3">
                    <label for="street">Street Address</label>
                    <input required class="form-control" type="text" placeholder="1234 Main St" name="street" />
                </div>
                
                <div class="row">
                    <div class="col-md-4 col-sm-12">
                        <div class="form-group pt-3">
                            <label for="city">City</label>
                            <input required class="form-control" type="text" placeholder="San Francisco" name="city" />
                        </div>
                    </div>
                    <div class="col-md-4 col-sm-12">
                        <div class="form-group pt-3">
                            <label for="state">State</label>
                            <input required class="form-control" type="text" placeholder="CA" name="state" />
                        </div>
                    </div>
                    <div class="col-md-4 col-sm-12">
                        <div class="form-group pt-3">
                            <label for="zip">Zip Code</label>
                            <input required class="form-control" type="text" placeholder="94117" name="zip" />
                        </div>
                    </div>
                </div>

Все, что мы здесь делаем, это добавляем несколько текстовых полей ввода и метку. Важно отметить, что мы также добавляем атрибут имени. Этот атрибут имени мы будем использовать для извлечения значения в нашем коде Python в файле views.py, поэтому убедитесь, что этот атрибут имени соответствует тому, что вы введете в файл представлений позже. Мы также добавляем «required», что приведет к ошибке, если мы попытаемся отправить заказ с пустым полем, bootstrap будет обрабатывать стили для этого без необходимости что-либо делать.

Теперь, когда мы добавили эти поля, давайте добавим модальное окно для отправки формы. Таким образом, вместо того, чтобы иметь кнопку отправки заказа там, где она есть, мы собираемся изменить ее на модальное окно, которое просит нас отправить еще раз, чтобы убедиться, что клиент готов. Сначала добавим кнопку для открытия модального окна:

<button type="button" class="btn btn-dark" data-toggle="modal" data-target="#submitModal">Submit Order
</button>

Теперь добавим наш модал:

<!-- Modal -->
                  <div class="modal fade" id="submitModal" tabindex="-1" role="dialog" aria-labelledby="submitModalLabel" aria-hidden="true">
                    <div class="modal-dialog" role="document">
                      <div class="modal-content">
                        <div class="modal-header">
                          <h5 class="modal-title" id="submitModalLabel">Submit Your Order!</h5>
                          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                          </button>
                        </div>
                        <div class="modal-footer">
                          <button type="button" class="btn btn-light" data-dismiss="modal">Go Back</button>
                          <button type="submit" class="btn btn-dark">Place Order!</button>
                        </div>
                      </div>
                    </div>
                  </div>

Теперь мы должны иметь возможность щелкнуть первую кнопку, которая открывает модальное окно с фактической кнопкой отправки для отправки формы.

Теперь, когда мы добавили эти две функции, давайте добавим изменения в наш метод post в файле views.py:

def post(self, request, *args, **kwargs):
        # Get input fields at the bottom of the order template
        name = request.POST.get('name')
        email = request.POST.get('email')
        street = request.POST.get('street')
        city = request.POST.get('city')
        state = request.POST.get('state')
        zip_code = request.POST.get('zip')
        order_items = {
            'items': []
        }
        items = request.POST.getlist('items[]')
        for item in items:
            menu_item = MenuItem.objects.get(pk__contains=int(item))
            item_data = {
                'id': menu_item.pk,
                'name': menu_item.name,
                'price': menu_item.price,
            }
            order_items['items'].append(item_data)
        
        price = 0
        item_ids = []
        for item in order_items['items']:
            price += item['price']
            item_ids.append(item['id'])
        
        order = OrderModel.objects.create(
            price=price,
            name=name,
            email=email,
            street=street,
            city=city,
            state=state,
            zip_code=zip_code
        )
        order.items.add(*item_ids)
        # After everything is done, send confirmation email to user
        body = ('Thank you for your order!  Your food is being made and will be delivered soon!\n'
        f'Your total: {price}\n'
        'Thank you again for your order!')
        send_mail(
            'Thank You For Your Order!',
            body,
            '[email protected]',
            [email],
            fail_silently=False
        )
        context = {
            'items': order_items['items'],
            'price': price
        }
        return render(request, 'customer/order_confirmation.html', context)

Вверху мы используем request.POST.get() для получения значений из почтового запроса. То, что мы передаем в эту функцию, соответствует атрибуту имени в полях ввода в нашей форме. После этого у нас есть весь наш код из последнего урока, а затем мы создаем фактический объект OrderModel. Мы передаем все наши данные из формы. Мы используем OrderModel.objects.create(), который не требует от нас явного сохранения объекта в базе данных, это обрабатывается автоматически.

Наконец, нам нужно импортировать функцию send_mail:

from django.core.mail import send_mail

Ниже при создании объекта мы отправляем электронное письмо с помощью send_mail, передавая тему, некоторый основной текст, электронное письмо «от» и «кому». Чтобы это работало правильно, нам либо нужно настроить параметры SMTP в файле settings.py, либо мы можем добавить строку для отправки электронной почты на консоль. Поскольку мы только в разработке, а не в производстве, мы просто отправим его на консоль. Итак, давайте откроем или settings.py и добавим это:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Вы можете добавить эту строку в любом месте файла, я добавил ее в самый низ.

Это все, что нам нужно сделать, чтобы эти функции заработали, мы вернемся в будущем, чтобы добавить больше к этому приложению, но на сегодня мы остановимся здесь.