2018年10月30日 星期二

[Vue.js] 使用美化頁面的小幫手Bootstrap


Bootstrap是最常用的前端開發套件,以下介紹在Vue.js的專案內如何使用。

除了一般直接下載原始碼並在<head>加入,Bootstrap其實已經提供Vue.js使用的套件。
以下使用webpack產生的專案來說明,先創立一個新的專案,並依造下面步驟安裝。
# install related packages
npm install jquery
npm install ajv

# install boostrap-vue
npm i bootstrap-vue
創立專案的方式可參考『安裝 Vue.js』方法二。

請依照你的需求在頁面加入css檔,通常我會放在main.js,這樣所有的頁面都能使用。
# src/main.js
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
此時已經可以用平常的方法套用bootstrap。

不過這麼一來就跟下載原始碼沒什麼兩樣了,我們還沒發揮BootstrapVue plugin的好處,接著在main.js裡註冊bootstrap的元件。
# src/main.js
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'

Vue.use(BootstrapVue);

這時侯如果要在頁面裡加入一個button,你只要這樣寫:
# src/App.vue
<template>
    <div id="app">
        <b-button variant="primary">I am a Button</b-button>
    </div>
</template>

...

比較一下原始的寫法,是不是方便多了呢!
# src/App.vue
<template>
    <div id="app">
        <button class="btn btn-primary">I am a Button</button>
    </div>
</template>

...

另外,你也可以根據需求只載入需要的元件(Component),例如只加入按鈕的元件。
import { Button } from 'bootstrap-vue/es/components';
Vue.use(Button);

import bButton from 'bootstrap-vue/es/components/button/button';
Vue.component('b-button', bButton);

更多資訊可參閱https://bootstrap-vue.js.org/

2018年10月29日 星期一

[Django] 內建管理系統(Admin)使用技巧


Django內建的管理系統,就類似phpmyadmin一樣,可以用網頁的方式來管理資料庫,請先確定urls.py內已經加入這個路徑。
# project/urls.py
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

請先執行migrate,建立一個後臺使用者的資料表,再新增一個使用者來登入後台介面。
# apply admin models
python manage.py migrate

# create a user to login as admin
python manage.py createsuperuser

打開瀏覽器'http://your-ip-address/admin'就可以看到管理介面的登入畫面,請輸入剛剛設定的帳號密碼。

首先,建立一個models紀錄產品(Product)的資訊:
# myapp.models.py
class Product(models.Model):
    name = models.CharField(max_length=128)
    price = models.DecimalField(max_digits = 11, decimal_places = 2)
    count = models.IntegerField()
    created = models.DateTimeField(auto_now_add=True)
請執行以下指令,讓這個models生效,makemigrations的目的是將models.py的內容轉成sql,若models.py有任何異動,可以透過migrations針對修改的部分進行更新。migrate則是執行sql,也就是實際建立新的table。
python manage.py makemigrations
python manage.py migrate

執行結果請參考

方法一、
最簡單的使用方式,就是在admin.py註冊這個models。
# myapp/admin.py
from django.contrib import admin
from .models import Product

admin.site.register(Product)

此時,管理介面會多一個你註冊資料表Product。另外,上面的User則是一開始新增的superuser儲存的資料表。

新增資料後,預設的畫面如下,括號內的數字是自動遞增的ID,必須點開才能知道其他資訊,不方便管理。

方法二、
同方法一在admin.py內註冊models,此外我們重新定義回傳值,不再顯示流水編號,舉例我們能回傳產品名稱(name)。
# myapp.models.py
class Product(models.Model):
    name = models.CharField(max_length=128)
    price = models.DecimalField(max_digits = 11, decimal_places = 2)
    count = models.IntegerField()
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        # value to display
        return str(self.name)

效果如下:


方法三、
# myapp/admin.py
from django.contrib import admin
from .models import Product

class ProductAdmin(admin.ModelAdmin):
    # fields to display
    list_display = ('id', 'name', 'price', 'created')

admin.site.register(Product, ProductAdmin)

效果如下:


進階使用

[Django] 如何設定static files(css, javascript, images)


請確定設定檔內的參數,通常已經預設寫入。
# project/settings.py
INSTALLED_APPS = [
    ...
    'django.contrib.staticfiles',
]

STATIC_URL = '/static/'
接下來,分此兩種情形:

(1) 開發階段 (DEBUG=True)
首先,在開發階段時,因為static files經常性的修改,因此先讀取STATICFILES_DIRS的設定。
# project/settings.py
DEBUG = True

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
    # another directory ...
]


建立一個新的static資料夾,在裡面依照習慣將檔案分類放好,可以參考一下我的分類方式:

當在templates中要使用static資料夾內的資源,請記得加入tag。
# templates/index.html
{% load static %}
<img src="{% static 'images/example.png' %}" alt="My image" />


(2) 佈建正式環境 (DEBUG=False)
在正式環境時,請加入STATIC_ROOT的設定,請注意STATIC_ROOT與STATICFILES_DIRS的名稱不能重複!只要Debug設為False,一定要加入這個設定,否則網頁無法正常開啟。
# project/settings.py
DEBUG = False

STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")

接著,請執行指令,將static裡面的資料輸出到新的資料夾staticfiles內。
python manage.py collectstatic
此時,觀察一下兩個資料夾差別,會發現staticfiles內除了我們自己新增的images,Django內建的admin或其他套件所需的資源,都會一並新增至此。但因為js和css兩個資料夾是空的,所以載入時會被忽略。



若之後static資料夾內有任何修改,必須重複執行collectstatic的指令來更新。


【重點整理】比較三個相似參數的差別
1. STATIC_URL:
設定static files的URL前綴,按照設定的前綴+路徑、檔名產生URL,以本文example.png為例,STATIC_URL='/static/',因此透過URL 'http://your-ip-address/static/images/example.png'檢視example.png這個檔案。

2. STATICFILES_DIRS:
開發階段,static files存放的位置,可以寫入多個路徑。

3. STATIC_ROOT:
正式環境中,透過collectstatic指令,將STATICFILES_DIRS設定目錄下檔案,收錄到STATIC_ROOT指定目錄。

2018年10月4日 星期四

[Django] 支援多國語言的網站

internationalization(國際化)被簡寫為i18n,因為字首i和字尾n的中間共有18個字母。

安裝相關軟體
sudo apt-get install gettext

修改settings.py,在MIDDLEWARE加上所需的套件,LANGUAGES列出支援哪些語言,LOCALE_PATHS則是將語言的翻譯包儲存的路徑。
# project/settings.py
MIDDLEWARE = [
    ...,

    'django.middleware.locale.LocaleMiddleware',
]


LANGUAGES = (
    ('zh-tw', '繁體中文'),
    ('en', 'English'),
)
LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)

新增一個html的模板,記得加入i18n的tag,頁面內想翻譯的字詞標註起來。另外在url的設定裡,將所有頁面區分成多個語言,也就是原先的路徑http://your.ip.address/welcome,可由http://your.ip.address/en/welcome來檢視英文版網站,中文網站則是打開http://your.ip.address/zh-tw/welcome。
# templates/index.html
{% load i18n %}

{% trans '一起唱DoReMi' %}
設定url
# myapp/views.py
def index(request):
    return render(request, 'index.html', {})

# project/urls.py
from myapp import views
from django.conf.urls.i18n import i18n_patterns
urlpatterns = i18n_patterns(
    path('', views.index, name='index'),
)

標註好想翻譯的字詞或段落後,請透過下列指令產生翻譯文件。
python manage.py makemessages -l en
python manage.py makemessages -l zh_TW

此時在locale資料夾內,會找到產生的檔案,msgid是你標註的字詞,請在msgstr寫入翻譯。針對重複的id,在文件內只能設定一種翻譯。
# locale\en\LC_MESSAGES\django.po
msgid "一起唱DoReMi"
msgstr "singing DoReMi together"
# locale\zh_TW\LC_MESSAGES\django.po
msgid "一起唱DoReMi"
msgstr "一起唱DoReMi"

翻譯完成後,將翻譯包編譯出*.mo
python manage.py compilemessages -l en
python manage.py compilemessages -l zh_TW
可以參考一下完成編譯的檔案結構
locale/
├── en
│   └── LC_MESSAGES
│       ├── django.mo
│       └── django.po
└── zh_TW
    └── LC_MESSAGES
        ├── django.mo
        └── django.po

4 directories, 4 files

這時就可以開啟瀏覽器查看成果囉!
http://your.ip.address/en/
http://your.ip.address/zh-tw/