Flask & Vue. Друга серія прикладів
Вітаю. Починаю наступну, другу серію прикладів Flask + Vue. У цій серії будуть наступні статті:
- Згадати все (ця стаття)
- Посторінковий вивід даних (пагінація). Як зробити правильно
- Посторінковий вивід даних + сортування + пошук
- Проста Аутентифікація
- Авторизація
- Наводимо красу. Кастомний вигляд компоненту "Product"
- Знову переробляємо backend. SQLAlchemy, Migrate, Marshmallow, JWT
- Використання систем збірки проекту. Webpack
Попередження. Все, що я буду куралесити на бекенді (мається на увазі до прикладу з SQLAlchemy), то так вже ніхто не робить. Цю "дичину" я буду творити тільки щоб показати як працює фронтенд, показати як воно працює у нутрях бекенду, і чому не треба морочити собі...голову, а використовувати вже стандартні готові рішення. Поки що будемо страждати збоченнями на бекенді і виписувати фронтенд. А потім ми перепишемо бекенд на сучасні рівні рейки, а вже в наступній серії переробимо фронтенд щоб він збирався по модньому. І тоді, я так думаю, Ви відчуєте різницю і зрозумієте чому зараз роблять саме так як це буде у наступній серії прикладів. А поки що починаємо другу серію прикладів з неофіційною назвою "збочення з бекендом".
Нагадаю, що попередня серія прикладів на тему Vue + трішечки Flask була присвячена побудові структур додатків. Ми зробили простий додаток: backend - на Flask, frontend - на Vue. У якості бази даних використовували SQLite. Для Flask побудували структуру для простого і швидкого додавання нових об'єктів даних. Для Vue створили комплекс компонент для роботи з даними. А саме: таблицю (standard-table), поля (form-field), форму (standard-form), і стандартну сторінку (standard-page) для перегляду і редагування даних. Компоненту standard-page можна вказати які саме дані використовувати з тих, що описані у const appDataset, і компонент буде будувати таблицю з даними, формую для редагування, додавання, видалення даних. Які поля будуть у таблиці, а які у формі теж описується у const appDataset.
Тобто, ми зробили компонент standard-page для того, щоб кожного разу не виписувати код для редагування наступної таблички у базі, а використовувати готові компоненти. "standard" у назві компоненти натякає на те, що це стандартна компонента і її зовнішній вигляд і функціонал буде дуже схожий для усіх даних, до яких ми будемо її застосовувати. Тобто, зовнішній вигляд усіх таблиць і форм суворо стандартизований. Нехай трохи йому не вистачає різноманітності, але він незмінний. У такому випадку, завдяки стандартній компоненті standard-page просто вказуємо які дані ми хочемо редагувати і все. Ми вже не програмуємо, а збираємо додаток з готових, стандартних блоків. Якщо Вам потрібно відійти від стандартів - це не проблема. Можна написати свою компоненту і використовувати, скажімо, компоненти standard-form, standard-table. Тобто, використовувати трохи дрібніші блоки. Якщо і форма не підходить - робимо свою форму і використовуємо ще більш дрібніші компоненти, наприклад компонент form-field. І так далі. Але це потребує значно більше часу. Тому стандартизація значно прискорює розробку.
У минулій серії прикладів ми зупинилися на простих формах з "простими" даними.
Задача на сьогодні:
- Створити у базі даних нову табличку "COUNTRIES" (довідник країн), додати у таблицю "CLIENT" поле "country_id"
- Додати у web-додаток можливість редагувати довідник країн.
- Додати у форму редагування Клієнта можливість вказувати країну зі списку. Список має містити перелік країн.
Цей приклад - є продовженням попереднього прикладу Vue + Flask. Ви можете завантажити попередній приклад Flask + Vue і виконати всі дії, описані у статті власноруч. Або завантажити готовий приклад Flask + Vue.
Модифікація Бази даних
Запускаємо скрипт modifyDB.py - цей файл містить мінімально необхідні SQL для модифікації бази даних і наповнення нової таблички тестовими даними.
modifyDB.py:
import sqlite3
conn = sqlite3.connect('myApp.db')
cur = conn.cursor()
print ("Opened database successfully")
conn.execute('''CREATE TABLE COUNTRIES
(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name TEXT,
code TEXT,
flag_img TEXT
);''')
print ("Table created successfully")
#############################
# Insert Data into table COUNTRIES
#############################
countries = [
{'id':1, 'name': 'Ukraine', 'code':'380', 'flag_img': 'ua.png'},
{'id':2, 'name': 'USA', 'code':'380', 'flag_img': 'us.png'},
{'id':3, 'name': 'France', 'code':'33', 'flag_img': 'fr.png'}
]
for item in countries:
SQL = 'INSERT INTO COUNTRIES (id, name, code, flag_img) VALUES({0}, "{1}", "{2}", "{3}")'.format(item['id'], item['name'], item['code'], item['flag_img'])
cur.execute(SQL)
print ("Table 'COUNTRIES' is done")
conn.execute('''ALTER TABLE CLIENT ADD COLUMN country_id INTEGER;''')
print ("Table CLIENT modified successfully")
conn.execute('''CREATE INDEX IF NOT EXISTS client_country_id ON CLIENT (country_id)''')
print ("Index created successfully")
conn.commit()
print ("Commit is done")
conn.close()
print ("Database is closed")
print ("Good luck!")
Модифікація Backend
Треба додати файл countries.py в директорію model
Файл countries.py містить наступне:
from model import default
class model(default.model):
def __init__(self, connection):
self.connection = connection
self.objName = 'COUNTRIES'
У файлі app_db.py додати "countries" у рядок:
from model import empty, menu, client, seller, product, countries
у цьому ж файлі додати рядок:
self.model['countries'] = product.model(self.connection)
Все! База даних і Backend готовий!
Frontend
Створюємо редактор довідника країн.
В const appDataset описуємо "countries" - посилання на backend, описуємо поля, які потрібно показати у таблиці, і які у формі:
'countries': {
'instance': 'countries',
'url': 'http://localhost:5000/countries/',
'fields': {
'table': [
{name:'name', 'title': 'Name', type:'string', sort: true},
{name:'flag_img', 'title': 'Flag', type:'string', sort: false},
],
'form': [
{name:'name', 'title': 'Name', type:'string', required:true},
{name:'code', 'title': 'Code', type:'string', required:true},
{name:'flag_img', 'title': 'Flag', type:'string' required:false},
]
}
}
в роутах додамо рядок:
{ path: '/countries', component: { template: ' ' } },
в menu.json додамо:
{
"item": "Countries",
"path": "#/countries"
},
Нагадаю: menu віддає backend. Ми його запхали у json винятково для демонстрації гнучкості і універсальності підходу.
Все! Редактор на Frontend готовий! От і все! Ми нічого нового не програмували! Ми використали раніше написаний компонент standard-page і лише вказали нові дані і у якій таблиці і формі їх показувати.
Поїхали далі
Редактор довідника країн готовий. Тепер додамо список (select) у форму редагування клієнта.
Основний підхід такий - основні дані (клієнта) завантажуються, як і раніше. Додаткові дані, (список країн) завантажуються окремо. При чому всі дані завантажує основний компонент. Це важливо! (щось не ясно - дивись попередні статті). Не треба функцію завантаження даних перекладати на компонент списку. Він тупо список - його робота просто показати, і коли щось змінилось повернути event. Що робити з даними - це клопіт основного компонента.
1. Міксин "crud_ext"
Новий функціонал завантаження додаткових даних зробимо у окремому міксині "crud_ext". Цей міксин ми потім будемо додавати при створенні компонентів.
Міксин "crud_ext":
var crud_ext = {
computed: {
form_fields: function () {
let fields = appDataset[this.instance]['fields']['form']
for (field of fields) {
// Prepare @select fields
if (field['type'] == 'select') {
field.items = []
if (field['dataset']) {
if (field['dataset']['src']) {
if (this[field['dataset']['src']]) {
let src = this[field['dataset']['src']]
for (item of src) {
field.items.push({value: item[field['dataset']['value']], caption: item[field['dataset']['caption']]})
}
}
}
}
}
}
return fields
}
},
methods: {
read_ext_data: function(instance) {
let url = appDataset[instance]['url']
let options = {method: 'GET'}
this.fetch_execute(url, options,
(response)=>{
this.$set(this, instance, response)
},
(response)=>{
this.show_error(response.errors)
}
)
}
}
}
В ньому є метод read_ext_data, який і завантажує додаткові дані, та computed поле form_fields яке обробляє і готує дані для форми на основі даних вказаних в описі instance (див. const appDataset) і завантажених додаткових даних. Зараз ми навчили form_fields готувати дані тільки для полів типу "select", але у подальшому його можна розширювати для інших типів. І робити це доведеться у одному місці - тут у міксині crud_ext.
2. Доробили компонент standard-form
Трохи доробили компонент standard-form (довелося додати свою data для забеспечення інтерактивності (щоб списки могли динамічно оновлюватися, коли в цьому виникне потреба)).3. Доробили компонент client-edit
Компонент client-edit відповідає за редагування клієнта (дивись попередні приклади і статті)В опис компонента client-edit додаємо створений міксин "crud_ext":
mixins: [crud, crud_ext],
додаємо дані "countries:
data : function () {
return {
countries: this.countries
}
},
у "mounted" додаємо виклик метода завантаження додаткових даних:
...
this.read_ext_data('countries')
...
4. Опис поля Country
Опис поля select для 'Country' тепер виглядає так:
{name:'country_id', 'title': 'Country', type:'select', dataset: {src: 'countries', value: 'id', caption: 'name'}},
- src - назва instance, звідки завантажувати дані
- value - поле, яке використовується, як значення
- caption - поле, яке використовується, як надпис у списку
Ми щойно розглянути, як доробити свою власну компоненту "client-edit". Ми її робили для того, щоб під час редагування був окремий роут (окремий URL). Але в нас є ще і універсальний компонент "standard-page", який показує таблицю з даними, форму для додавання / редагування даних і т.п. Треба і її навчити працювати з випадаючими списками.
Доробка standard-page
1. Добавили mixin crud_ext:
mixins: [crud, crud_front, crud_ext],
2. Модифікували "data", щоб зберігалася інтерактивність і в завантажених додатково даних
data: function () {
let obj = {
current_row: this.current_row,
form_data: this.form_data
}
if (this.datasets) {
for (ext_data of this.datasets) {
obj[ext_data] = this[ext_data]
}
}
return obj
},
3. У "mounted" для завантаження додаткових даних додали наступний код
Перелік (це масив) необхідних додаткових даних передається параметром "datasets":
if (this.datasets) {
this.datasets_array = []
for (ext_data of this.datasets) {
console.log(ext_data)
this.read_ext_data(ext_data)
this.datasets_array.push(ext_data)
}
}
4. В роутах опис стандартної сторінки виглядає так
{ path: '/client_old', component: { template: ' ' } },
Ми додали параметр datasets і вказали в ньому які додаткові дані треба завантажити.
Висновок
Раніше побудований CRUD - підхід на бекенді і на фронтенді дозволив швидко зробити новий об'єкт даних і створити форму для його редагування практично не програмуючи нічого нового. Вся пророблена сьогодні робота стосується тільки нового функціоналу. Звісно, це стосується досить простих, стандартних даних. Зі складними все цікавіше і доводиться дещо робити руками. Але саме для того, щоб позбутися рутини у своїй роботі і займатися виключно новими і цікавими речами і використовують сучасні практики.
P.S. У наступній статті: пагінація - взаємодія з сервером; що не так з компонентою standard-table?; як зробити правильно.
Як запустити приклад?
- Завантажити архів з прикладом, розпакувати
- Запустити приклад командою:
абоpython ./my_app.py
python3 ./my_app.py
- У браузері відкрити посилання: http://localhost:5000/
Дивись також:
- Flask & Vue. Приклад# 2.1
- Flask & Vue. Приклад# 2.2 Frontend - Зручна навігація
- Flask & Vue. Приклад# 2.3 Серверна пагінація, пошук, сортування даних
- Flask & Vue. Приклад# 2.4 Проста аутентифікація
- Flask & Vue. Приклад# 2.5 Авторизація
- Flask & Vue. Приклад# 2.6 Кастомні компоненти
- Flask & Vue. Приклад# 2.7 SQLAlchemy, Migrate, Marshmallow, JWT
- Flask & Vue. Використання систем збірки проекту. Webpack
- Flask & Vue. OAuth. Facebook / Google Account
- Flask & Vue. Завантаження файлів
Додати коментар

Недавні записи
- Конструктор регуляторів моторів. Структура.
- Конструктор регуляторів моторів. Анонс.
- Golang + Vue + PostgreSQL #2
- Golang + Vue + SQLite #1
- FOC Position Control. Векторне управління - Стабілізація положення
- Flask & Vue. Завантаження файлів. Приклад № 2.10
- Рекуперація. FOC і цікаві досліди
- Flask & Vue. OAuth. Приклад№ 2.9
- Flask & Vue. Використання систем збірки проекту. Webpack. Приклад№ 2.8
- Flask & Vue. SQLAlchemy, Migrate, Marshmallow, JWT. Приклад№ 2.7
Tags
stm32 bkp soldering eeprom eb-500 led hih-4000 bme280 bmp280 3d-printer usb ethernet html git docker barometer raspberry-pi remap dc-dc rfid java-script nodemcu mpu-6050 rtc capture gpio avr brushless foc options flash flask atmega python displays rs-232 solar st-link ssd1331 dma adc bluetooth web ssd1306 wifi exti mpu-9250 pwm pmsm mongodb programmator i2c battery max1674 piezo css meteo watchdog books websocket servo dht11 ngnix mpx4115a lcd motor uart sensors nvic encoder usart sms smd bldc esp8266 tim timer gps examples
Архіви
