Рубрики
Без рубрики

Как построить веб-приложение Django с нуля (Учебное пособие)

Добро пожаловать на то, что я надеюсь, будет очень подробным и полезным руководством по созданию веб-приложения Django из … Теги с Джанго, Python.

Добро пожаловать на то, что я надеюсь, будет очень подробным и полезным руководством по созданию веб-приложения Django с нуля к производству. Разработав десятки проектов Django PROCES, я приобрел определенные советы и трюки для повышения эффективности в каждом проекте Django, что я представлю в форме учебника. Этот учебник является пошаговым процессом того, как я иду по созданию надежных приложений Django. Наслаждаться!

Вы можете проверить развертывание здесь: Живая ссылка

Демо:

Для этого образца проекта мы пойдем за пределы простого приложения TODO или в блоге – мы создадим приложение для рецепта пищевых рецептов с полной аутентификацией пользователя, функциями Crud, а также развертывая приложение для живой продукции на Heroku.

Каталог

Первый шаг в любом новом проекте устанавливает каталог. Если вы хотите, чтобы ваш проект Django в определенном каталоге перейдите к нему, прежде чем запустить команду StartProject. Создайте новый проект Django со следующей командой:

Django-admin StartProject [ProjectName]

Это должно генерировать файловую структуру как таковую:

├─ foodanic (our sample project title)
│  ├─ __init__.py
│  ├─ asgi.py
│  ├─ settings.py
│  ├─ urls.py
│  ├─ wsgi.py
├─ manage.py

Давайте быстро добавим папку с названием Шаблоны в каталог с пищевым/и управлением.

Окружающая среда

Следующим решающим шагом является виртуальная среда для содержения всех наших зависимостей в одном модуле.

Создать новую виртуальную среду:

virtualenv env

Примечание: [ENV] может быть все, что вы хотите назвать вашу виртуальную среду Активировать окружающую среду:

source env/bin/activate

Чтобы деактивировать окружающую среду:

deactivate 

После того, как вы создадите и активируйте среду, тег (ENV) появится в вашем терминале рядом с именем каталога.

Настройки:

Это шаг, который вы должны запомнить для всех будущих проектов, потому что правильные начальные настройки настройки предотвратывают ошибки в будущем. В вашем settings.py Файл, в верхней части, добавить Импорт ОС Далее прокрутите вниз до Шаблоны раздел и сделайте следующие изменения в Дирижер :

import os

'DIRS': [os.path.join(BASE_DIR, 'templates')],

Это позволяет пересылать корневой шаблон проекта к главному каталогу шаблонов, для будущего ссылки на base.html файл.

Пока мы на этом, давайте установим Django в наше приложение с помощью:

pip install django

Далее мы установим промежуточное программное обеспечение, которое помогает изображениям Heroku Process Process для приложений Django под названием Whitenoise Отказ

Для установки зависимости запустить:

pip install whitenoise

Добавьте белкуаз на свой Промежуточное программное обеспечение :

# settings.py
MIDDLEWARE = [
   ...
   'whitenoise.middleware.WhiteNoiseMiddleware',
]

Каждый раз, когда мы добавляем новую зависимость в проект, вы захотите заправить их в файл под названием требования .txt Отказ

Сделать этот бег:

pip freeze > requirements.txt

Статические и СМИ

Статические и СМИ будут служить изображениям в нашем приложении.

Ниже определенного Static_url в настройках .py, добавлять

#settings.py

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_TMP = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
os.makedirs(STATIC_TMP, exist_ok=True)
os.makedirs(STATIC_ROOT, exist_ok=True)
os.makedirs(MEDIA_ROOT, exist_ok=True)

Это устанавливает наши статические и средства массовой информации в наиболее оптимальном способе обслуживания нашего приложения.

.gitignore.

Другим важным шагом в начале проекта Django является файл .gitignore, который будет игнорировать каталоги/файлы, перечисленные там.

Создайте .gitignore с:

touch .gitignore

Добавим виртуальную среду, которую мы создали к нему, так что она не забирает дополнительное облачное пространство на Github.

# .gitignore
env/

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

Создайте новое приложение с:

python manage.py startapp app
python manage.py startapp users

Добавьте приложение к настройкам .py:

# settings.py
INSTALLED_APPS = [
    'app',
    'users',
     ...
]

Теперь, чтобы наши приложения были правильно маршруты в нашем веб-приложении, нам нужно включить наши другие приложения в главной Пищевой URLS.PY Отказ

# foodanic/urls.py

from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
    path('u/', include('users.urls')),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

Программы

Внутри нового каталога приложений и пользователей давайте добавим два файла и две папки.

Files to add:         Folders to add:  (for each respectively)
- urls.py             - app/templates/app       
- forms.py            - users/templates/users

Новое приложение и каталог пользователей будут выглядеть так:

├─ app
│  ├─ migrations/
|  ├─ templates
|  |  └── app/
│  ├─ __init__.py
│  ├─ admin.py
│  ├─ apps.py
│  ├─ forms.py
│  ├─ models.py
│  ├─ tests.py
│  ├─ urls.py
│  └── views.py
│
├─ users
│  ├─ migrations/
|  ├─ templates
|  |  └── users/
│  ├─ __init__.py
│  ├─ admin.py
│  ├─ apps.py
│  ├─ forms.py
│  ├─ models.py
│  ├─ tests.py
│  ├─ urls.py
│  └── views.py

Аутентификация пользователя

Для нашего удобства мы будем использовать основную систему аутентификации Django.

В наших настройках .py Нам нужно будет указать логин и выйти из перенаправления, например:

# foodanic/settings.py

...

LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
LOGIN_URL = 'login'

В нашем недавно созданном приложении пользователей отправляйтесь на URL-адреса для включения видов аутентификации Django.

# users/urls.py

from django.urls import path
from django.conf.urls.static import static
from django.conf import settings
from django.contrib.auth import views as auth_views
from .views import *

urlpatterns = [
    path('signup/', signup, name='signup'),
    path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
    path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
    path('change-password/', auth_views.PasswordChangeView.as_view(template_name='users/change-password.html'), name="change-password"),
    path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='users/password_reset_done.html'), name='password_change_done'),
    path('password_reset/', auth_views.PasswordResetView.as_view(template_name='users/forgot-password.html', subject_template_name='users/password_reset_subject.txt', html_email_template_name='users/password_reset_email.html'), name='password_reset'),
    path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='users/password_reset_done.html'), name='password_reset_done'),
    path('reset///', auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'), name='password_reset_confirm'),
    path('reset/done/', auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'), name='password_reset_complete'),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

Теперь это была тонна новых URL-адресов, которые мы только что добавили, давайте убедитесь, что у нас есть необходимые шаблоны. Линия ниже создаст все необходимые шаблоны, учитывая, что вы находитесь в базовом каталоге (пищевой).

touch users/templates/users/login.html && touch users/templates/users/logout.html && touch users/templates/users/change-password.html && touch users/templates/users/password_reset_done.html && touch users/templates/users/forgot-password.html && touch users/templates/users/password_reset_done.html && touch users/templates/users/password_reset_confirm.html && touch users/templates/users/password_reset_complete.html && touch users/templates/users/password_reset_email.html && touch users/templates/users/password_reset_subject.txt && touch users/templates/users/signup.html && touch users/templates/users/style.html

Теперь мы можем настроить каждый шаблон для рендера с базы и отображать соответствующую форму. Кредит на Этот кодепен для дизайна Bootstrap.

Пользователи/style.html.


Пользователи/login.html.



{% extends 'base.html' %}

{% block content %}
{% load crispy_forms_tags %}


{% include 'users/style.html' %} {% endblock %}

Пользователи/logout.html.


{% extends 'base.html' %}

{% block content %}

You have successfully logged out of Foodanic. Log back in ->

{% endblock %}

Пользователи/feignup.html.



{% extends 'base.html' %}

{% block content %}
{% load crispy_forms_tags %}


{% include 'users/style.html' %} {% endblock %}

Пользователи/Change-Password.html



{% extends 'base.html' %}

{% block content %}
{% load crispy_forms_tags %}


{% include 'users/style.html' %} {% endblock %}

Пользователи/Password_reset_done.html.



{% extends 'base.html' %}

{% block title %}Email Sent{% endblock %}

{% block content %}


Check your inbox.

We've emailed you instructions for setting your password. You should receive the email shortly!

{% endblock %}

Пользователи/Забыли пароль .html



{% extends 'base.html' %}
{% block content %}
{% load static %}
{% load crispy_forms_tags %}



  

Forgot Your Password?

We get it, stuff happens. Just enter your email address below and we'll send you a link to reset your password!

{% csrf_token %}


{% endblock %}

Пользователи/Password_reset_subject.txt.

Foodanic Password Reset

Пользователи/Password_reset_email.html.



{% autoescape off %}

Hi, {{ user.username }}.


We received a request for a password reset. If this was you, follow the link below to reset your password. If this wasn't you, no action is needed.

{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

If clicking the link above doesn't work, please copy and paste the URL in a new browser window instead.

Sincerely,
Foodanic {% endautoescape %}

Пользователи/Password_reset_done.html.

{% extends 'base.html' %}

{% block title %}Email Sent{% endblock %}

{% block content %}


Check your inbox.

We've emailed you instructions for setting your password. You should receive the email shortly!

{% endblock %}

Password_reset_confirm.html.

{% extends 'base.html' %}

{% block title %}Enter new password{% endblock %}
{% load crispy_forms_tags %}
{% block content %}

{% if validlink %}


Set a new password

{% csrf_token %} {{ form|crispy }}
{% else %}

The password reset link was invalid, possibly because it has already been used. Please request a new password reset.

{% endif %} {% endblock %}

Пользователи/Password_reset_complete.html.

{% extends 'base.html' %}

{% block title %}Password reset complete{% endblock %}

{% block content %}


Password reset complete

Your new password has been set. You can now log in.

{% endblock %}

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

Если вы хотите создать учетную запись администратора для вашего сайта, вы можете сделать это с:

python manage.py createsuperuser

Основное приложение

Вот где приходит веселая часть, мы построим операции Crud of App.

Взгляды

Просмотры контролируют логику приложения, рендурирующие функции и выполнение необходимых операций на формах, шаблонах и что-либо еще, имеющие отношение к вашему приложению.

Во-первых, мы выпишем функции, над которыми мы будем работать.

# views.py

from django.shortcuts import render

def home(request):
    context = {}
    return render(request, 'app/index.html', context)

def detail(request, id):
    context = {}
    return render(request, 'app/detail.html', context)

def create(request):
    context = {}
    return render(request, 'app/create.html', context)

def update(request, id):
    context = {}
    return render(request, 'app/update.html', context)

def delete(request, id):
    context = {}
    return render(request, 'app/delete.html', context)

Далее давайте добавим их в URLS.PY Файл в приложении в дополнение к URL-адресу носителя и root для обработки наших будущих изображений:

# app/urls.py
from django.urls import path
from .views import *
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('', home, name='home'),
    path('detail//', detail, name='detail'),
    path('new/', create, name='create'),
    path('update//', update, name='update'),
    path('delete//', delete, name='delete'),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

Для того, чтобы наши URL в приложении работать должным образом, нам нужно добавить их в наш основной файл URLS.PY. Кроме того, также добавьте URL-адрес носителя и корни к основным URL-адресам.

# foodanic/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
    path('u/', include('users.urls')),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

Пользователи/Views.py.

from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm, AuthenticationForm

def signup(request):
    context = {}
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password1')
            user = request.user
            if user is not None:
                return redirect('login')
            else:
                print('user is none')
        else:
            form = UserCreationForm()
            context['form'] = form
            return render(request, 'users/signup.html', context)
        # context['form'] = form
    if request.method == 'GET':
        form = UserCreationForm()
        context['form'] = form
        return render(request, 'users/signup.html', context)

Беги миграции и сервера

Теперь мы готовы начать разработку нашего веб-приложения. Давайте запустим миграции, чтобы создать начальную базу данных и запустить наше приложение.

Беги миграции с:

python manage.py migrate

Запустите сервер с:

python manage.py runserver [OPTIONAL: PORT]

Примечание. Дополнительный порт может использоваться как таковой: Python Manage.py Runserver 8000 Python Manage.py Runserver 1234

Модель

Теперь мы можем настроить нашу модель, которая будет хранить каждый рецепт.

В моделях .py Добавьте следующий код:

# app/models.py
from django.db import models
from datetime import datetime, timedelta
from markdownx.models import MarkdownxField
from django.contrib.auth.models import User

class Recipe(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField()
    prep = models.CharField(max_length=255)
    cook = models.CharField(max_length=255)
    servings = models.IntegerField(default=1, null=True, blank=True)
    image = models.ImageField(upload_to='media/')
    ingredients = MarkdownxField()
    directions = MarkdownxField()
    notes = models.TextField(null=True, blank=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

    @property
    def formatted_ingredients(self):
        return markdownify(self.ingredients)

    @property
    def formatted_directions(self):
        return markdownify(self.directions)

Несколько вещей, которые следует отметить здесь: у нас есть 9 полей, которые будут проводить информацию для модели рецепта. Мы будем использовать django markdownx (GitHub Link) Для двух полей для приятного взгляда. @Property Создает тег свойства, который мы можем использовать в наших шаблонах, чтобы рендерировать поля Markdown.

Чтобы установить Django Markdown, запустите:

pip install django-markdownx

Добавьте его на settings.py:

# settings.py

INSTALLED_APPS = [
   'markdownx',
   ...
]

Добавьте его к требованиям с:

pip freeze > requirements.txt

Добавьте его к главному URLS.PY:

# foodanic/urls.py

urlpatterns = [
    path('markdownx/', include('markdownx.urls')),
]

Теперь, когда у нас есть наша модель, мы можем идти вперед и запустить миграцию. Примечание. Вы должны запускать миграции с каждым изменением, которые вы делаете в модели, чтобы база данных обновлена.

python manage.py makemigrations && python manage.py migrate

Если все прошло хорошо, вы должны увидеть вывод, аналогичный этому и совершенно новой миграции в вашем приложении миграции/ папка.

(env) ➜  foodanic git:(master) ✗ python manage.py makemigrations && python manage.py migrate
Migrations for 'app':
  app/migrations/0001_initial.py
    - Create model Recipe
Operations to perform:
  Apply all migrations: admin, app, auth, contenttypes, sessions
Running migrations:
  Applying app.0001_initial... OK
(env) ➜  foodanic git:(master) ✗ 

Для того, чтобы наша модель успешно отображается в администрате Django, нам нужно зарегистрировать его в файл admin.py, который так:

# app/admin.py
from django.contrib import admin
from .models import *

admin.site.register(Recipe)

Основная форма

Чтобы быстро пройти данные в нашу базу данных, мы будем использовать модефом Django на нашей модели.

Составьте следующие изменения в файл форм:

# app/forms.py
from django import forms
from .models import *
from durationwidget.widgets import TimeDurationWidget

class RecipeForm(forms.ModelForm):
    prep = forms.DurationField(widget=TimeDurationWidget(show_days=False, show_hours=True, show_minutes=True, show_seconds=False), required=False)
    cook = forms.DurationField(widget=TimeDurationWidget(show_days=False, show_hours=True, show_minutes=True, show_seconds=False), required=False)

    class Meta:
        model = Recipe
        fields = '__all__'
        exclude = ('author',)

С этой формой мы сможем рендерировать все поля в модели рецепта. Кроме того, если вы хотите включить только определенные поля, вы перечислите их в массиве как таковых: поля = [«Имя», «Изображение»,] Или если вы хотите исключить определенные поля, вы бы перечисляли их как таковые: Исключить = («Имя», «Изображение»,) Отказ

Возможно, вы заметили, что мы добавили новую библиотеку, чтобы помочь нам сделать поле продолжительности для подготовки и времени готовить. Кроме того, давайте установим другой модуль, мы будем использовать позже, чтобы помочь нам с формой, Джанго хрустящие формы Отказ

Установите его с помощью PIP:

pip install django-durationwidget
pip install django-crispy-forms

Добавьте его в настройки:

# settings.py
INSTALLED_APPS = [
    'durationwidget',
    'crispy_forms',
]

TEMPLATES = [
    'APP_DIRS': True,        # set to True
]

# on the bottom of settings.py
CRISPY_TEMPLATE_PACK = 'bootstrap4'

И давайте заморожем требования к сохранению зависимости:

pip freeze > requirements.txt

Грубый

Теперь мы готовы начать писать логику наших взглядов.

Давайте начнем с C в Круд Что означает (создавать, чтение, обновление, удалить)

Создавать

В наших представлениях, давайте импомнем формы, модели и визуализацию формы для получения запроса GET и POST. Запрос Get будет представлять, когда пользователь отправляется на странице, чтобы создать новый рецепт, тогда как пост будет обрабатывать логику формы после отправки.

# app/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.core.files.storage import FileSystemStorage
from datetime import datetime, timedelta
from .models import *
from .forms import *

@login_required
def create(request):
    context = {}
    if request.method == 'GET':
        form = RecipeForm()
        context['form'] = RecipeForm()
        return render(request, 'app/create.html', context)
    elif request.method == 'POST' and request.FILES != None:
        form = RecipeForm(request.POST, request.FILES)
        if form.is_valid():
            new = Recipe()
            user = request.user
            new.author = user
            new.name = form['name'].value()
            new.description = form['description'].value()
            new.prep = form['prep'].value()
            new.cook = form['cook'].value()
            new.servings = form['servings'].value()
            new.ingredients = form['ingredients'].value()
            new.directions = form['directions'].value()
            new.notes = form['notes'].value()
            theimg = request.FILES['image']
            fs = FileSystemStorage()
            filename = fs.save(theimg.name, theimg)
            file_url = fs.url(filename)
            new.image = filename
            new.save()
            return redirect('home')
        else:
            form = RecipeForm()
            context['form'] = RecipeForm()
            return render(request, 'app/create.html', context)
    return render(request, 'app/create.html', context)

WOAH, это целый код Лотта – давайте сломаемся, поэтому мы понимаем, что это делает.

IF Заявление обрабатывает логику того, какой шаблон для рендеринга, если get и где перенаправлять пользователя после отправки, пост. запрос. Файлы В форме для нашего поля изображения. По сути, если представленная форма проходит наши параметры, мы создаем новый экземпляр модели рецепта и сохранить содержимое формы к значениям модели соответственно.

Теперь мы должны сделать шаблон для формы. Для этого нам нужно будет создать base.html Файл в наших базовых шаблонах. Я добавлю самую современную версию Bootstrap, которая является 5 – поэтому, если вы читаете этот учебник позже, обязательно обновить соответствующий CDN для Bootstrap, найден в getbootstrap.com Отказ

Пищевые/шаблоны/base.html





    
    
    
    Foodanic
    
    


    {% block content %}

    {% endblock %}

    


Теперь у нас есть наша настройка Base.html, и мы можем оказывать другие шаблоны без ненужного контента. Я загрузил create.html Страница к прошедшему формату, но не стесняйтесь изменить дизайн, однако вы, пожалуйста.

приложение/create.html.

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}



New Recipe

Note: The Ingredients and Directions fields are Markdown Supported. Learn more about markdown here.


{% csrf_token %}
{{ form.name|as_crispy_field }} {{ form.image|as_crispy_field }}
{{ form.description|as_crispy_field }}

{{ form.prep|as_crispy_field }}
{{ form.cook|as_crispy_field }}
{{ form.servings|as_crispy_field }}

{{ form.ingredients|as_crispy_field }}
{{ form.directions|as_crispy_field }}
{{ form.notes|as_crispy_field }}
{{ form.media }}
{% endblock %}

В начале вы можете увидеть, что мы визуализируем информацию в тегах блока контента на основе base.html файл мы создали. Мы загружаем хрудку с тегом и установите каждое поле в виде хрустящего поля. {{form.media}} Тег оказывает контент для полей MarkDownx. В качестве альтернативы вы можете сделать всю форму как хрустящую, как это: {{form | crispy}} Отказ

Новый маршрут должен выглядеть что-то подобное:

Читать

Часть чтения CRUD связана с возможностью просмотра каждого отдельного объекта в нашей базе данных. Во-первых, мы сделаем один рецепты, тогда мы потянем весь набор нашей индексной страницы.

приложение/просмотр .py.py.

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.core.files.storage import FileSystemStorage
from datetime import datetime, timedelta
from markdownx.utils import markdownify   # new
from .models import *
from .forms import *

def home(request):
    recipes = Recipe.objects.all()
    context = {
        'recipes': recipes,
    }
    return render(request, 'app/index.html', context)

def detail(request, id):
    recipe = get_object_or_404(Recipe, id=id)
    recipe.ingredients = markdownify(recipe.ingredients)
    recipe.directions = markdownify(recipe.directions)

    context = {
        'recipe': recipe,
    }
    return render(request, 'app/detail.html', context)

Шаблон ниже зачисляется пользователю Ариэлозам на кодепене.

Приложение/Detail.html.

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}


{{ recipe.name|capfirst }} Recipe {% if user.is_authenticated and request.user == recipe.author %} {% endif %}

by {{recipe.author}}

Description:

{{recipe.description}}



Servings: {{ recipe.servings }}
Prep: {{ recipe.prep }}
Cook: {{ recipe.cook }}
{{ recipe.ingredients|safe }}
{{ recipe.directions|safe }}
{% endblock %}

Новый шаблон должен выглядеть так:

Теперь пришло время получить все наши рецепты для отображения на нашей домашней странице.

App/index.html.

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}

    

  

A Warm Welcome!

Browse through our collection of various recipes.


{% for recipe in recipes %}
{{recipe.name}}

{{recipe.name}} Recipe

{{recipe.description|truncatechars:65}}

Prep Time: {{recipe.prep}}
Cook Time: {{recipe.cook}}

{% endfor %}



Copyright © Foodanic 2021

{% endblock %}

С несколькими рецептами выборки вот как домашняя страница выходит на:

Обновлять

Обзор обновления будет захватывать экземпляр объекта, который мы хотим обновить и сохранить новую информацию.

приложение/просмотр .py.py.

@login_required
def update(request, id):
    recipe = get_object_or_404(Recipe, id=id)
    context = {
        'recipe': recipe
    }
    if request.method == 'GET':
        form = RecipeForm(instance=recipe)
        context['form'] = form
        return render(request, 'app/update.html', context)
    elif request.method == 'POST' and request.FILES != None:
        form = RecipeForm(request.POST, request.FILES, instance=recipe)
        if form.is_valid():
            form.save()
            return redirect('detail', recipe.id)
        else:
            form = RecipeForm(instance=recipe)
            context['form'] = form
            return render(request, 'app/update.html', context)
    return render(request, 'app/update.html', context)

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

app/update.html.

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}


Update Recipe

Note: The Ingredients and Directions fields are Markdown Supported. Learn more about markdown here.


{% csrf_token %}
{{ form.name|as_crispy_field }} {{ form.image|as_crispy_field }}
{{ form.description|as_crispy_field }}

{{ form.prep|as_crispy_field }}
{{ form.cook|as_crispy_field }}
{{ form.servings|as_crispy_field }}

{{ form.ingredients|as_crispy_field }}
{{ form.directions|as_crispy_field }}
{{ form.notes|as_crispy_field }}
{{ form.media }}
{% endblock %}

Продолжайте и дайте ему попробовать, ваша форма должна отображать вам данные объекта и правильно сохранить ее в базу данных.

Удалить

Как больно удалять объекты базы данных, иногда это то, что пользователь или мы хотим сделать.

приложение/просмотр .py.py.

@login_required
def delete(request, id):
    recipe = get_object_or_404(Recipe, id=id)
    if not request.user == recipe.author:
        return redirect('detail', recipe.id)
    else:
        name = recipe.name
        recipe.delete()
        context = {
            'name': name
        }
        return render(request, 'app/delete.html', context)

приложение/delete.html.

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}


You have successfully deleted the {{name|capfirst}} Recipe



{% endblock %}

Часть 3 🚗.

Сейчас мы готовы к нашему живому развертыванию к Heroku. На данный момент, пожалуйста, отправляйтесь на Github Создайте и нажимайте свой код на новый репозиторий, чтобы мы могли провести его на Heroku. Кроме того, если у вас еще нет учетной записи Heroku, отправляйтесь на Heroku Home создать один.

Кроме того, Heroku нуждается в Gunicorn, чтобы запустить, поэтому мы устанавливаем его с PIP.

pip install gunicorn
pip freeze > requirements.txt

Далее нам нужен Procfile Итак, Хероку знает, чтобы запустить наше приложение с гурущим.

web: gunicorn foodanic.wsgi --log-file -

Убедитесь, что вы вошли в Heroku в своем терминале с:

heroku login

Создайте новое приложение Heroku с:

heroku create
# or
heroku create [app-name]

После того, как вы погрузитесь и совершаете, беги

git push heroku HEAD:master

Когда вы получаете сообщение о успехе, заявив, что ваше приложение (со ссылкой) было развернуто на Heroku, мы должны убедиться, что наше приложение принимает эту ссылку.

Питанец/Настройки

ALLOWED_HOSTS = ['[your-app].herokuapp.com']

Обязательно замените [«ваше приложение»] с соответствующим именем приложения для вашего приложения Heroku.

Затем повторить фиксацию и …

git push heroku HEAD:master

Конец

Если вы достигли конца этого учебника, вы потрясающие! Если вы столкнулись с любыми ошибками/ошибками на протяжении всего руководства, пожалуйста, не стесняйтесь публиковать их в комментариях, чтобы я мог бы быстро исправить их, прежде чем кто-то еще испытывает их. Программирование – это совместное усилие после всех 😁

Ссылки на проект:

Github repo: Ссылка Live: Ссылка на сайт

Ресурсы:

Деталь страницы кодепена: Ссылка User Auth Page CodePen: Ссылка Домашняя страница Шаблон Bootstrap: Ссылка Django Markdownx.: Ссылка Джанго хрустящие формы: Ссылка на сайт

Слияние Если есть определенные проекты/темы, которые вы хотели бы, чтобы я погрузился, бросьте их в комментарии ниже, и я сделаю все возможное, чтобы исследовать его. Спасибо за чтение 🙂

Оригинал: “https://dev.to/vladyslavnua/how-to-build-a-django-web-app-from-scratch-tutorial-5bp0”