Первое веб приложение на python3 и django 2

python > Первое веб приложение на python3 и django 2
04.05.2018 13:45:31


Наиболее часто встречающиеся слова в статье:

[article] [section] [приложения] [''django] [re_path] [template_name] [context] [python3] [отвечает] [создать]


Статья:

Проект — основной каталог, где будут располагаться те или иные приложения, также проект содержит основные настройки будущего сайта. Создадим корневой каталог для проекта и сам проект :

django-admin startproject mysite
Расматривать я буду в контексте  python3 и  django 2 на ubuntu server LTS 16x

Вкратце:

manage.py — отвечает за управление проектом, например, командой python manage.py runserver можно запустить сервер для тестовой разработки.

__init__.py — нужен для того, чтобы python рассматривал каталог pySite как пакет.

settings.py — файл настроек проекта: настройки языка, часового пояса, соединения с базой данных, подключаемых приложений и прочего.

urls.py — настройки URL-адресов для сайта

wsgi.py — конфигурация модуля wsgi для веб-сервера

Хорошо, когда проект расширяемый. Ещё лучше, если его легко сопровождать. Оба этих условия выполняются в Django. Чтобы расширить функционал сайта, следует создать для него какое-либо приложение: галерею, форум, блоги. Затем лишь подключить его в settings.py и подправить свой urls.py, дабы при переходе по определённому адресу пользователь перенаправлялся к страницам приложения. Поэтому давайте создадим какое-нибудь приложение. Пусть оно отвечает за публикацию новостей и хранится в том же каталоге, что и основной проект.

Настройки для сайта

Заглянем в файл settings.py и настроим его под свои скромные пока нужды.

Установка поддержки mysql

sudo apt-get install libmysqlclient-dev

pip3 install mysqlclient

В settings.py настроим его под свои скромные пока нужды пропишем БД MYSQL

DATABASES = {
''default'': {
#''ENGINE'': ''django.db.backends.sqlite3'',
#''NAME'': os.path.join(BASE_DIR, ''db.sqlite3''),
''ENGINE'': ''django.db.backends.mysql'',
''NAME'': ''mydb'',
''USER'': ''iocsha'',
''PASSWORD'': ''Пароль'',
''HOST'': ''localhost'',
''PORT'': '''',
}

Желательно сразу создать и подключить директорию, где будет храниться статика: css, javascript и изображения. Кроме того, нам понадобится директория под наши html-файлы.

STATIC_URL — относительный url для статики

STATICFILES_DIRS — директория, где расположены соответствующие файлы

TEMPLATE_LOADERS — модули для работы с шаблонами

TEMPLATE_DIRS — указание на директорию, где лежат html-шаблоны

ROOT_URLCONF — главный файл url’ов

INSTALLED_APPS — подключенные приложения, вниз добавим наш news.

Пропишем  пути для  статик  картинок;

STATIC_URL = ''/static/''
STATIC_ROOT = os.path.join(BASE_DIR,''static'')

Укажим шаблоны создадим папку в корне нашего проекта  templates

TEMPLATE_DIR = os.path.join(BASE_DIR, "templates")
TEMPLATES = [
    {
        ''BACKEND'': ''django.template.backends.django.DjangoTemplates'',
        ''DIRS'': [TEMPLATE_DIR,],
        ''APP_DIRS'': True,
        ''OPTIONS'': {
            ''context_processors'': [
                ''django.template.context_processors.debug'',
                ''django.template.context_processors.request'',
                ''django.contrib.auth.context_processors.auth'',
                ''django.contrib.messages.context_processors.messages'',
            ],
        },
    },
]

развернём статику для  админки python3 manage.py collectstatic

Шаг 1: Создание таблицы для страниц в базе данных

Сначала надо создать приложение «news».

python3 manage.py startapp news

Команда выше создаст папку «news» с необходимыми файлами.

Вкратце:

models.py — файл для взаимодействия с базой данных

urls.py — отдельный файл url’ов. Он может быть пустым, если вы решите использовать для всех адресов urls.py проекта

admin.py — создаётся вручную, нужен исключительно для удобства: настройка отображения моделей в административной панели

views.py — самое интересное, управляет логикой приложения

С приложением определились. Отлично! Пора браться за настройки.

 

Создание модели и представления, конфигурация urls.py

Следующим шагом будет настройка моделей для взаимодействия с БД, создание представления (логика приложения), настройка файла urls.py.

В примере ниже создаётся класс Post, подкласс абстрактного класса models.Model. Мы хотим видеть у нашего поста название (title), его тело (body), дату создания (timestamp) . Обратите внимание на models.*Field. Каждая модель соответствует указанному полю.

Так, models.CharField выведет несколько символов, максимальное их значение 150, этого должно хватить для названия;

models.TextField позволит вводить неограниченное число символов: полноценный текст;

Эти таблицы будут созданы в базе данных при синхронизации. В  razdel хранится список категорий , в news статьи , id_razdel ссылка на razdel

В файле news/models.py надо создать модель, которая сгенерирует таблицу в базе данных.

Модели Django отображают (грубо говоря) таблицы базы данных, и предоставляют место для инкапсулирования бизнес-логики. Все модели являются наследниками базового класса Model и содержат поля определений.

from django.db import models
from django.contrib import admin
from django.contrib.auth.models import User
 
# Create your models here.
class razdel(models.Model):
	title = models.CharField(max_length=200)
	url = models.CharField(max_length=250)
	def __str__(self):
		return self.title		
class news(models.Model):
	title = models.CharField(max_length=150)
	body = models.TextField()
	timestamp = models.DateTimeField()
	id_razdel=models.IntegerField()
	def __str__(self):
		return self.title
 

В файле settings.py в параметре INSTALLED_APPS надо добавить приложение «news» (создавалась через команду python3 manage.py startapp news).

# settings.py

INSTALLED_APPS = (
    # …
    ''news'',
)

Настройка INSTALLED_APPS содержит список приложений, используемых в проекте. Этот список содержит в себе строки, которые отображают пакеты Python. Django будет импортировать каждый из указанных пакетов, а потом смотреть модуль models

В параметре INSTALLED_APPS указаны приложения, для которых будут созданы поля в базе данных. Чтобы создать сами поля, надо выполнить следующую команду:

python3 manage.py makemigrations
python3 manage.py migrate

Имя созданной таблицы будет иметь формат «приложение_модель», т.е. для текущего примера будет создана таблица news_news news_razdel

Шаблоны

Шаблоны в Django просто замечательная вещь, особенно если учитывать то, что они могут наследоваться и определённые блоки будут переопределяться.

Создадим 3 шаблона  , news.html - вывод категорй ,  news_details.html -вывод списка статей в разделе  и article.html вывод статьи

Для  учебного теста я развенул index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Hello Django</title>
</head>
<body>
    <h1>Welcome to Django!</h1>
	<p>Сайт сделан на: {{name}}</p> <!-- Сайт сделан на: Django -->
	<a href="news/">разделы</a>
</body>
</html>
 

 news.html

Как Вы могли заметить, в языке шаблонов Django используются конструкции if, for, url. Но откуда взялись переменные section_list и section? - section_list передаётся в качестве контекстного значения в шаблон при подготовке данных в представлении ( view ). Проверив, что список разделов существует, мы проходим по все элементам списка подставляя необходимые значения в шаблон. Поскольку section соответствует модели razdel, то соответствующие названия полей модели подхватываются автоматически.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Hello Django</title>
</head>
<body>
    <h1>NEWS!</h1>
	<article>
    <h1>Разделы</h1>
    {% if razdel_list %}
        <ul>
        {% for section in razdel_list %}
            <li>
            <a href="{% url ''section'' section.id %}">{{ section.title }}</a>
            </li>
        {% endfor %}
        </ul>
    {% endif %}
    </article>
</body>
</html>
 

news_details.html

В шаблоне разделов происходит формирование списка статей, которые соответствуют данному раздлу. В качестве контекста в шаблон передаётся переменная section, которая содержит информацию об объекте раздела. Мы подставляем название раздела и его описание. Заметьте, что описание подставляется со специальным аргументом safe, который указывает на сохранение форматирования. Это необходимо сделать, чтобы сохранить html разметку, иначе пользователь увидит вместо красиво оформленного описания код html вёрстки.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Hello Django</title>
</head>
<body>
	<article>
    <h1>Статьи в разделе</h1>
        <ul>
        {% for article in section %}
            <li>
            <a href="{% url ''article'' article.id_razdel article.id %}">{{ article.title }}</a>
            </li>
        {% endfor %}
        </ul>
    </article>
 
</body>
</html>

article.html

Как видите, шаблон для статьи достаточно скуден, чтобы что-то добавлять про него.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Hello Django</title>
</head>
<body>
    <article>
	<h2>тут статья</h2>
        <h1>{{ article.title2 }}</h1>
        <p>{{ article.body }}</p>
    </article>
</body>
</html>

Представление

В данном случае работа с представления достаточно ограниченная, поэтому приведу сразу полный листинг файла views.py. который  лежит в корне нашего приложения   /news

Мы наследуемся от класса View и переопределяем метод get, который отвечает за выполнение GET запроса, то есть запроса страницы пользователем. Также импортируем методы render_to_response, который будет обрабатывать шаблон в нужном нам контексте

from django.shortcuts import  render,render_to_response, get_object_or_404
from django.views import View
#from django.shortcuts import get_object_or_404, render_to_response,render
#from django.template import RequestContext
#from .models import Baza
from .models import *
def index(request):
    return render(request, "index.html", {"name": "Django"})
class ESectionView(View):
    template_name = ''news_details.html''
    def get(self, request, *args, **kwargs):
        context = {}
        #получить список статей  в разделе , те  получить несколько записей
        section = news.objects.filter(id_razdel = self.kwargs[''section''])
        #section = get_object_or_404(news, id_razdel=self.kwargs[''section''])
        context[''section''] = section
        return render_to_response(template_name=self.template_name, context=context)
class EKnowledgeIndex(View):
    template_name = ''news.html''
    def get(self, request, *args, **kwargs):
        context = {}
        context[''razdel_list''] = razdel.objects.all().order_by(''title'')
        return render_to_response(template_name=self.template_name, context=context)
class EArticleView(View):
    template_name = ''article.html'' 
    def get(self, request, *args, **kwargs):
        context = {}
        #Получить только одну запись  ,одну  статью
        article = news.objects.get(id = self.kwargs[''article_id''])       
        context[''article''] = article
        return render_to_response(template_name=self.template_name, context=context)
В EKnowledgeIndex забираются абсолютно все разделы с сортировкой по наименованию и помещаются в контекст под именем razdel_list, Вы помните, что данная переменная использовалась в шаблоне news.html

В ESectionView забирается уже конкретный Раздел, по аргументу, который передаётся в запрашиваемом url.news как раз отвечает за переменные, которые вычленяются из url по шаблону, заданном в файле urls.py.

В EArticleView всё гораздо интереснее. Дело в том, что в шаблоне url используется две переменных, но для получения статьи достаточно сделать запрос по id,

URL шаблоны

Хорошо, всё что нужно написано, но осталось совсем немного, чтобы всё заработало, а именно настроить шаблоны url, по которым будут обрабатываться запросы.

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

mysite/mysite/urls.py

Для начала необходимо задать шаблоны в файле mysite/mysite/urls.py , который будет определять, в какое приложение направить запрос .path('''', views.index)  обрабатывает гланую страницу .Также имеется направление в админку сайта и в приложение news  которое отвечает как раз за разделы и статьи.

from django.contrib import admin
from django.urls import path,re_path
from django.conf.urls import include
from news import views
admin.autodiscover()  #функция автоматического обнаружения файлов admin.py в наших приложениях
urlpatterns = [
    #re_path(r''^news/(?P<pk>\d+)/$'', views.news_details),
    path(''news/'', include(''news.urls'')),
    path(''admin/'', admin.site.urls),
    path('''', views.index),
    #re_path(r''^$'', views.index, name=''index''),
]

include(''news.urls'')  задаёт использовать  URL из папки приложения mysite/news/urls.py

его содержимое  mysite/news/urls.py:

from django.urls import path,re_path
from django.conf.urls import include
from . import views
 
urlpatterns = [
     re_path(r''^$'', views.EKnowledgeIndex.as_view(), name=''index''),
     re_path(r''^(?P<section>[\w]+)/$'', views.ESectionView.as_view(), name=''section''),
     re_path(r''^(?P<section>[\w]+)/(?P<article_id>[0-9]+)/$'', views.EArticleView.as_view(), name=''article''),
]