2017年11月30日 星期四

Javascript - 新增element

var tag = document.createElement('div');
var img = document.createElement('img');
img.setAttribute('class','bobo')
tag.appendChild(img);
document.getElementById("mydiv").appendChild(tag);

2017年11月25日 星期六

Django - Display Foreign Key object Fields at Admin Interface

# admin.py

class TaskDetailAdmin(admin.ModelAdmin):
    list_display = ['get_name']

    def get_name(self, obj):
        return obj.user.last_name

admin.site.register(models.Task, TaskAdmin)

2017年11月22日 星期三

Django - 分頁

from django.core.paginator import Paginator




reference:https://docs.djangoproject.com/en/1.11/topics/pagination/

Django - 設定User Model 顯示

#models.py

def get_name(self):
    return '{} {}'.format(self.last_name, self.first_name)

User.add_to_class("__str__", get_name)

2017年11月17日 星期五

Django - Message

此筆記將紀錄如何使用Django Message 功能
參考資料:https://docs.djangoproject.com/en/1.11/ref/contrib/messages/

設定預設Tag
# settigns.py

from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
messages.INFO: '',
50: 'critical',
}


# views.py

from django.contrib import messages
messages.add_message(request, messages.INFO, 'Hello world.')


# template

            {% if messages %}
                {% for message in messages %}
                <p {% if message.tags %} class="bg-{{ message.tags }}"{% endif %}>{{ message }}</p>
                {% endfor %}
            {% endif %}



各種TAG

messages.debug(request, '%s SQL statements were executed.' % count)
messages.info(request, 'Three credits remain in your account.')
messages.success(request, 'Profile details updated.')
messages.warning(request, 'Your account expires in three days.')
messages.error(request, 'Document deleted.')


客制level
剛剛設定預設Tag的 50 = critical

def my_view(request):
    messages.add_message(request, 50, 'A serious error occurred.')

2017年11月13日 星期一

Python - DataTime筆記

from datetime import date

取得日期
t = date.today()

轉換字串
t.strftime('%Y%m%d') # 20171114

轉成TUPLE
tt = t.timetuple()


使用localtime()取得時間跟日期
import time

time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) 

Python - CSV筆記

參考:https://docs.python.org/3.6/library/csv.html


mode二碼
第一碼:
r -讀取
w - 檔案存在與否,均可寫入
x - 檔案不存在時,寫入
a - 檔案存在時,寫入結尾

第二碼:
t - 文字
b - 二進位



讀取

 import csv
 with open('eggs.csv', newline='') as csvfile:
     spamreader = csv.reader(csvfile, delimiter=',', quotechar=',')
     for row in spamreader:
         print(', '.join(row))


csvinstance轉換成串列

lists = []
for row in csv_instance:
    lists.append(row)


寫入

import csv
with open('eggs.csv', 'w', newline='') as csvfile:
    spamwriter = csv.writer(csvfile, delimiter=',', quotechar=',', quoting=csv.QUOTE_MINIMAL)
    spamwriter.writerow(['001','002','003'])

如果要使用絕對路徑backslash 改成 common slash
c:\123\  to c:/123/



2017年11月11日 星期六

Django - 語系更改

以輸入中文為例:

# settings.py

import sys  
reload(sys)  
sys.setdefaultencoding('utf-8')

LANGUAGE_CODE = 'zh-hant' # Django 1.9之前zh-TW

TIME_ZONE = 'Asia/Taipei'

2017年11月10日 星期五

Django - 客製Admin



1. 修改Admin Title



新增admin資料夾至templates資料夾並新增base_site.html
取得admin templates,參考以下連結,複製內容貼在剛剛新增的base_site.html
https://github.com/django/django

django/contrib/admin/templates/admin/base_site.html

{% extends "admin/base.html" %}

{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('派工系統後台') }}</a></h1> 
{% endblock %}

{% block nav-global %}{% endblock %}


2.客制Admin ListView
首先新增一個class名字為model+admin

# admin.py

from django.contrib import admin
from . import models

class SchoolAdmin(admin.ModelAdmin):
   

記得將新增的class註冊到admin
admin.site.register(models.School, SchoolAdmin)


如要設定只需要override以下ModelAdmin變數

設定ListView欄位名稱排序
 fields = ['field1','field2','field3'] # 左至右

設定ListView搜尋功能
search_fields = ['field1','field2'] # 如此field1, field2都可以搜尋到

設定ListView Filter
list_filter = ['field1','field2']

設定ListView顯示欄位
list_display = ['field1','field2']

設定ListView欄位編輯
list_editable = ['field1','field2']






Bootstrap - Navbar筆記

Bootstrap js cdn 放在body最底部

Django - Dynamic URL

# views.py

from django.shortcuts import render
from .models import Post


def post_detail(request, pk):
    post = Post.objects.get(pk=pk)
    return render(request, 'post.html', {'post': post})


# urls.py

url(r'^post/(?P<pk>\d+)/$', post_detail, name='post_detail'),
url(r'^send_message/(?P<user_id>[\w]+)/(?P<text>\w+)/$', views.send_message, name="send_message"),


2017年11月9日 星期四

Django - Line Message API 筆記

from django.conf import settings
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt

from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError, LineBotApiError
from linebot.models import MessageEvent, TextSendMessage, TextMessage, FollowEvent

line_bot_api = LineBotApi('Channel access token')
handler = WebhookHandler('Channel secret')

# member_ids_res = line_bot_api.get_group_member_ids(group_id)

@handler.add(MessageEvent, message=TextMessage)
def handle_text_message(event):
    # print('room_id: {}'.format(event.room_id))
    print('text: {}'.format(event.message.text))
    text =event.message.text.lower()
    user = event.source.user_id
    print('user_id: {}'.format(user))
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=user)
    )

@handler.add(FollowEvent)
def handle_follow(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text='感謝這位兄長加我')
    )


@handler.default()
def default(event):
    print(event)
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text='Currently Not Support None Text Message')
    )


@csrf_exempt
def callback(request):
    if request.method == 'POST':
        signature = request.META['HTTP_X_LINE_SIGNATURE']
        body = request.body.decode('utf-8')

        try:
            handler.handle(body, signature)
        except InvalidSignatureError:
            return HttpResponseForbidden()
        except LineBotApiError:
            return HttpResponseBadRequest()
        return HttpResponse()
    else:
        return HttpResponseBadRequest()

def send_message(request):
    line_bot_api.multicast(['to1', 'to2','to3'], TextSendMessage(text='各位都是帥哥!'))
    # line_bot_api.push_message('to1', TextSendMessage(text='Hello World!'))
    return HttpResponse()

Django - CBV筆記

之前這筆記都是使用FBV(Function Based Views),以下與CBV(Class Based Views)做對照:

#FBC
def index(request):
    return render(request, 'index.html')

#CBV
class IndexView(TemplateView):
    template_name = 'index.html'


快速體驗CBV

# views.py
from django.views.generic import View

class CBView(View):
def get(self, request):
return HttpResponse('Class Based View are Cool!')

# urls.py
from basic_app import views

url(r'^$', views.CBView.as_view()),



TemplateView應用

from django.views.generic import TemplateView

# views.py
class IndexView(TemplateView):
    template_name = 'index.html'

    # for injection
    def get_context_data(self,**kwargs): # 雙*代表字典,單*代表Tuple
     context = super(IndexView, self).get_context_data(**kwargs)
     context['injectme'] = 'Basic Injection!'
     return context
    
#urls.py
url(r'^$', views.IndexView.as_view()),





ListView應用

from django.views.generic import ListView

class SchoolListView(ListView):
context_object_name = 'schools' # 沒有使用context_object_name django將預設成 school_list
model = models.School



DetailView應用



from django.views.generic import DetailView

class SchoolDetailView(DetailView):
context_object_name = 'school_detail' # 未設定
model = models.School
template_name = 'basic_app/school_detail.html'


url(r'^(?P<pk>\d+)/$', views.SchoolDetailView.as_view(),name='detail'),



CreateView應用

class SchoolCreateView(CreateView):
fields = ('name', 'principal', 'location')
model = models.School
之後要記得去School Model 加上get_absolute_url設定轉換的頁面
url(r'^create/$', views.SchoolCreateView.as_view(), name='create'),



UpdateView應用

class SchoolUpdateView(UpdateView):
fields = ('name','principal')
model = models.School

url(r'^update/(?P<pk>\d+)/$', views.SchoolUpdateView.as_view(),name='update'),


DeleteView應用









2017年11月7日 星期二

Django - Login筆記

新增 LOGIN_URL變數 於 settings.py
新增login template
設定login views
使用decorator
設定urls.py


1. 設定settings LOGIN_URL變數
LOGIN_URL = '/basicapp/user_login'


2. 新增login template
<h1>Login</h1>

<form method="post" action="{% url 'basicapp:user_login' %}" >
{% csrf_token %}
<label for="username">Username:</label>
<input type="text" name="username" placeholder="Enter username...">
<label for="password">Password:</label>
<input type="password" name="password" placeholder="Enter password...">
<input type="submit" name="" value="Login">
</form>


3. 設定views.py

from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required

def user_login(request):

if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')

user = authenticate(username=username, password=password)

if user:
if user.is_active :
login(request, user)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse('Account not active')
else:
print('Someone tried to login and failed')
print('Username: {} and password {}'.format(username,password))
return HttpResponse('invalid login details supply')

return render(request, 'basicapp/login.html')



@login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))

@login_required
def special(request):
return HttpResponse('You are logged in!')

4. 設定urls.py

完成

判斷登入使用者

不可等入admin mode
is_authenticated

可登入admin mode
is_staff
is_superuser

Javascript - JSON筆記

透過XMLHttpRequest API 載入JSON

宣告XMLHttpRequest物件
var request = new XMLHttpRequest();

設定請求
request.open('GET', requestURL);

設定取得的格式
request.responseType = 'json';
request.send();

處理取得的JSON
request.onload = function() {
  var superHeroes = request.response;
  populateHeader(superHeroes);

}

function populateHeader(jsonObj) {
  var myH1 = document.createElement('h1');
  myH1.textContent = jsonObj['squadName'];
  header.appendChild(myH1);

  var myPara = document.createElement('p');
  myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed'];
  header.appendChild(myPara);
}

參考資訊
https://www.fooish.com/jquery/dom-manipulation.html

HTML5 - BackGround Video

使用mp4為目前最保險的方法

控制播放
<video width="320" height="240" controls>
  <source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>

自動播放
<video width="320" height="240" autoplay>
  <source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>

2017年11月6日 星期一

JQuery - AJAX筆記

本筆記將實作JQuery AJAX + Django 按鈕觸發AJAX


# ajax.html

<!DOCTYPE html>
<html>
<head>
<title>Ajax</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<script>
  $( document ).ready(function() {
$("#btn1").on('click', function () {
$.ajax({
url: 'http://localhost:8000/basic_app/get_json_data/',
type: 'get',
data: {},
dataType: 'json',
timeout: 10000,
success: function(result) {
alert('sucess');
$('#txt1').html(result.result);
},
error: function() {
$('#txt1').html("error");
    }
});
});
});
</script>
</head>
<body>
<h1>Ajax</h1>
<h1 id="txt1" >ready</h1></br>
<button type="button" id="btn1">turn off </button>
</body>
</html>


# views

from django.http import HttpResponse
import json

def get_json_data(request):
    a = {
    'result' : 'success',
    }
    return HttpResponse(json.dumps(a), content_type='application/json')


# urls.py

url(r'^get_json_data/', views.get_json_data,name='get_json_data'),

完成

Cordova筆記

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
function onBodyLoad(){
document.addEventListener("deviceready", onDeviveReady, false);
window.location.href = "http://139.162.96.42";

}

function onDeviveReady(){

}
</script>
<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
</head>
<body onload="onBodyLoad()">

</body>

</html>



npm install -g cordova

cordova create MyApp

cd MyApp

cordova platform add browser

cordova run browser

2017年11月5日 星期日

Django - User Model & Form

新增與django內建User model關聯的UserProfileInfo model

from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
# Create your models here.

class UserProfileInfo(models.Model):

user = models.OneToOneField(User)

# additional
portfolio_site = models.URLField(blank=True)

profile_pic = models.ImageField(upload_to='profile_pics', blank=True)

def __str__(self):
return self.user.username
使用image前先安裝pillow Image Library

pip install pillow


設定form.py

設定views.py

設定urls.py

makemigrations


2017年11月4日 星期六

Django - Password筆記

此筆記將紀錄使用者認證以及密碼

settting.py

我們將使用以下兩個app才能實作
TEMPLATE_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
]

我將使用bcrypt,使用bcrypt加密密碼是較安全的做法

pip install bcrypt
pip install [argon2] # 如果是1.10以上不需要裝argon2,已經內建於django中


於settings新增

PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
]


設定AUTH_PASSWORD_VALIDATORS(可略過)

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'min_length' : 9, #設定密碼至少9碼
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]



Django - Filter & 自製Tag 筆記

此筆記將紀錄如何使用Filter

{{ value | filter : "params" }}
並非全部的filter都用參數

每個單字以大寫開頭
{{ text | title }}

日期格式
{{ mydate | data : "Y-m-d"  }}

大寫text
{{ text | upper }}

小寫
{{ text | lower }}

數字加法,number變數必須要是數字型別
{{ number | add:"2" }}

顯示前n個字元
{{ text | truncatewords:80 }} # 前80


自製Filter


新增templatetags資料夾於app底下,注意不是project而是app


接著於templatetags新增__init__.py 和 tags.py,內容如下:

from django import template

register = template.Library()

def cut(value, arg):
return value.replace(arg,'')

register.filter('cut', cut) # 註冊cut function 成 'cut'

自製Filter,使用decorator

tags.py改成

from django import template

register = template.Library()

@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg,'')


上述設定完就可以使用自製的Filter

{{ text | cut:'cool' }}



自製Tag

import datetime
from django import template

register = template.Library()

@register.simple_tag
def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)

參考:https://docs.djangoproject.com/en/1.11/topics/templates/





2017年11月1日 星期三

Django - Template Inheritance筆記

此筆記將紀錄以DRY為原則的Template Inheritance
{% extends "basic_app/base.html" %}
{% block body_block %}
{% include "includes/_messages.html" %}

# base.html

{% extends "basic_app/base.html" %}

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Base</title>
  </head>
  <body>
    <nav class="navbar navbar-default navbar-static-top">
    </nav>
    <div class="container">
        {% block body_block %}
        {# Anything outside of this will be inherited if you use extend.#}
        {% endblock %}
    </div>
  </body>
</html>

index.html繼承base.html的navbar

{% extends "basic_app/base.html" %}
    {% block body_block%}
        <h1>This is the index.html page</h1>
    {% endblock %}