2017年10月31日 星期二

基本功 - 佇列

利用python實作佇列Queue

class Queue:
    def __init__(self):
        self.items = []

    def enqueue(self, item):
        self.items.insert(0,item)

    def dequeue(self):
        return self.items.pop()

    def size(self):
        return len(self.items)

基本功 - 堆疊

利用python實作stack堆疊

class Stack:
     def __init__(self):
         self.items = []

     def push(self, item):
         self.items.append(item)

     def pop(self):
         return self.items.pop()

     def size(self):
         return len(self.items)

2017年10月30日 星期一

Django - Relative URLs筆記

此筆記將紀錄進階Template技巧

1. Relative URLs


<a href="basicapp/index"> Index </a>
簡化成
<a href="{% url 'basicapp:index' %}">  Index </a>

上例我們設定路由urls.py

# urls.py

from django.conf.urls import url
from basicapp import views

app_name = 'basicapp' # 新增app_name變數
urlpatterns = [
    url(r'^$', views.index, name='index'), # 設定屬性name為index
]

由此可得 {% url 'basicapp:index' %}是如何生成


如果要產生admin頁面相對URLs
{% url 'admin:index' %}


注意:'basicapp:index' 請確認有無空白,不然會噴錯

P.S:此方法為Python2.0之後方法

Django - Model Form筆記

使筆記將紀錄使用Model Form,Model Form直接的與Form做連接,來達成驗證。

操作前務必import以下:
form django import forms
form mapp.models import MyModel

P.S:我們將使用Meta class,實作ModelForm


ModelForm操作案例:

1. show model中全部的欄位,使用__all__

class MyForm(models.ModelForm):
class Meta:
model = MyForm()
fields = "__all__"


2. 排除特定欄位,使用exclude

class MyForm(models.ModelForm):
class Meta:
model = MyForm()
exclude = ["field1", "field2", "field3"]


3. 指定特定欄位
class MyForm(models.ModelForm):
class Meta:
model = MyForm()
fields = ("field1", "field2", "field3")


如想要客制驗證,可以直接寫在Form class裡

class MyForm(models.ModelForm):
        # 加在這 name = froms.CharField(...)
class Meta:
model = MyForm()
fields = ("field1", "field2", "field3")
# 更改Modelform field 屬性
        widgets = {
            'field1': forms.TextInput(attrs={'class': 'textinputclass'}),
            'field2': forms.Textarea(attrs={'class': 'editable medium-editor-textarea postcontent'}),
        }


現在我們將進行ModelForm實作,假設我們已經有一個User Model,現在要製作一個輸入User Model頁面

1. 設定form.py

class MyModelForm(forms.ModelForm):
class Meta():
model = User
fields = '__all__'

2. 設定templates

<form method="POST">
{{ form.as_p }}
{% csrf_token %}
<input type="submit" value="Submit">
</form>

3. 設定views.py

from form import MyModelForm

def model_form_name_view(request):
form = forms.MyModelForm()
if request.method == 'POST':
form = MyModelForm(request.POST)
if form.is_valid():
form.save(commit=True) # exection, same as form.save()
return index(request)
else:
print('ERROR FORM INVALID')

return render(request, 'myapp/model_form_page.html', {'form' : form})

4. 設定urls.py

完成



隱藏內建User model  help_text 訊息

# form.py

from django.contrib.auth.models import User

class UserForm(forms.ModelForm):

password = forms.CharField(widget=forms.PasswordInput())

class Meta():
model = User
help_texts = {
'username': None, # 取消掉
                }
fields = ('username', 'email', 'password')

完成

2017年10月29日 星期日

Django - Form資料驗證筆記

此筆記將紀錄詳細的資料驗證。

以驗證機器人為例:
新增一個隱藏的欄位來檢驗機器人,如屬性value有值代表是機器人,即發出資料驗證訊息。
使用clean_XXX()來驗證單一欄位
from django import forms

class FormName(forms.Form):
name = forms.CharField()
email = forms.EmailField()
text = forms.CharField(widget=forms.Textarea)
botcatcher = forms.CharField(required=False,
widget=forms.HiddenInput)

def clean_botcatcher(self):
botcatcher = self.cleaned_data['botcatcher']
if len(botcatcher) > 0:
raise forms.ValidationError("Gotcha bot!!!")

return botcatcher



另一種方法是使用validators,可以讓程式更簡短

from django import forms
from django.core import validators

class FormName(forms.Form):
name = forms.CharField()
email = forms.EmailField()
text = forms.CharField(widget=forms.Textarea)
botcatcher = forms.CharField(required=False,
widget=forms.HiddenInput,
validators = [validators.MaxLengthValidator(0)])

客製驗證,以檢驗開頭必要為z為例:
利用validators客制自己的資料驗證,新增一個method 來寫入檢驗邏輯,成立即發出error訊息。

from django import forms
from django.core import validators

def check_for_z(value):
if value[0].lower() != 'z':
raise forms.ValidationError('Name needs to start with z')


class FormName(forms.Form):
name = forms.CharField(validators=[check_for_z],)
email = forms.EmailField()
text = forms.CharField(widget=forms.Textarea)



驗證再次輸入的email與email欄位是否相符,使用clean()
使用clean()讀取多個欄位

from django import forms
from django.core import validators

class FormName(forms.Form):
name = forms.CharField(validators=[check_for_z],)
email = forms.EmailField()
verify_email = forms.EmailField(label='Enter your email again')
text = forms.CharField(widget=forms.Textarea)

def clean(self):
email = self.cleaned_data.get('email')
vmail = self.cleaned_data.get('verify_email')
if email != vmail:
raise forms.ValidationError("make sure emails match")


Django - Basic Form筆記

此筆記將實作Basic Form


1.
新增form.py並設定欄位,如下:
from django import forms

class FormName(forms.Form):
name = forms.CharField()
email = forms.EmailField()
text = forms.CharField(widget=forms.Textarea)

2.
新增view
from django.shortcuts import render
from . import form as forms

def for_name_view(request):
form = forms.FormName()
if request.method == 'POST':
form = forms.FormName(request.POST)

if form.is_valid():
print('Validation success!!!')
print("Name: "+form.cleaned_data['name'])
print("Email: "+form.cleaned_data['email'])
print("Text: "+form.cleaned_data['text'])
                        # 此處之後進行query或是一些邏輯

return render(request, 'basicapp/form_page.html',{'form' : form})


3.
新增template
<form method="POST"> # 大小寫沒差
{{ form.as_p }}
{% csrf_token %}
<input type="submit" value="Submit">
</form>

4.
設定路由

完成


Django - Model & Admin Interfacel筆記

行前準備

python mange.py migrate

python mange.py makemigratons app

為了讓admin mode可以看到model,必須要在admin.py中註冊

from app.models import Model1, Model2
admin.site.register(Model1)
admin.site.register(Model2)


創立Model

開啟app中的model.py輸入:

class Topic(models.Model):
top_name = models.CharField(max_length=264, unique=True)

def __str__(self):
return self.top_name

class Webpage(models.Model):
topic = models.ForeignKey(Topic)
name = models.CharField(max_length=264, unique=True, verbose_name='名字')
url = models.URLField(unique=True)

def __str__(self):
return self.name

class AccessRecord(models.Model):
name = models.ForeignKey(Webpage)
date = models.DateField()

def __str__(self):
return str(self.date)


python mange.py migrate

python mange.py makemigratons app # 必須要和app name相同

python mange.py migrate

完成以上指令我們進入shell mode確認一下model是否創立成功

python manage.py shell

from apptwo.models import Topic
print(Topic.objects.all()) # 沒東西
t = Topic(top_name="social network")
t.save()
print(Topic.objects.all()) #出現剛剛新增的social network
quit()

接下來將利用admin interface來新增資料,在這之前註冊


# admin.py

from apptwo.models import AccessRecord, Topic, Webpage
admin.site.register(AccessRecord)
admin.site.register(Topic)
admi.site.register(Webpage)

建立superuser
python manage.py createsuperuser

利用superuser帳號登入admin interface
http://127.0.0.1:8000/admin

完成

新增日期, 修改日期
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Django - Form概念筆記

此筆記將介紹Django強大的Input Form功能,以下為基本流程。

1.
新增form.py並定義之,內容類似model

2.
將form.py import views.py,此動作可選兩種方法:
from . import form
from form import FormName

3.
新增新的view給form,如下:
def form_name_view(request):
    form = forms.FormName()
    return render(request, 'form.html', {'form' : form})

4.
設定urls.py的路由

5.
新增template接應view的form,以及templates資料夾路徑

完成


How to inject the form?

<form method="post">
    {{ form.as_p }}
    {% csrf_token %}
    <input type="submit" value="Submit">
</form>

看了之後可能會有以下問題:
as_p是什麼?
inject 的form 加上as_p
將會被<p>包起來而完整的排好

{% csrf_token %}是什麼?
每當使用form發出http verb都要加上這個,否則form無法運行。此機制是利用django加密好的token來防止資安問題。

cleaned_data是什麼?
form input的資料,可利用form.cleaned_data['name']來讀取





2017年10月28日 星期六

Django - MTV架構筆記

MTV是Django Models, Templates, Views的縮寫

此筆記將紀錄開發Django app時的步驟

1.
import 要用的models於views.py

2.
進行query於views.py

3.
將query的結果傳到Template

4.
Template去接應Views.py的結果,如果控制流程必須要有收尾的Tag
如:{% endif %}、{% endfor %}

5.
urls.py設定路由


Django - 利用Faker產生填充資料

開發系統時,往往都會需要一些填充資料去做測試,此筆記將利用Faker來產生填充資料


安裝Faker
pip install Faker


新增py檔於專案跟目錄底下

import os
# Configure settings for project
# Need to run this before calling models from application!
os.environ.setdefault('DJANGO_SETTINGS_MODULE','first_project.settings')

import django
# Import settings
django.setup()

import random
from first_app.models import Topic,Webpage,AccessRecord
from faker import Faker

fakegen = Faker()
topics = ['Search','Social','Marketplace','News','Games']

def add_topic():
    t = Topic.objects.get_or_create(top_name=random.choice(topics))[0]
    t.save()
    return t



def populate(N=5):
    '''
    Create N Entries of Dates Accessed
    '''

    for entry in range(N):

        # Get Topic for Entry
        top = add_topic()

        # Create Fake Data for entry
        fake_url = fakegen.url()
        fake_date = fakegen.date()
        fake_name = fakegen.company()

        # Create new Webpage Entry
        webpg = Webpage.objects.get_or_create(topic=top,url=fake_url,name=fake_name)[0]

        # Create Fake Access Record for that page
        # Could add more of these if you wanted...
        accRec = AccessRecord.objects.get_or_create(name=webpg,date=fake_date)[0]


if __name__ == '__main__':
    print("Populating the databases...Please Wait")
    populate(20)
    print('Populating Complete')

備註:
get_or_create()用於讀取以及寫入,查詢不存在時即寫入



2017年10月25日 星期三

Django - 靜態檔案筆記

本筆記同Template需要新增資料夾、設定settings.py



1.新增名為static的file於專案根目錄(同templates),static裡再創一個images file,放入一張圖片近該資料夾


2.設定settings,新增STATIC_DIR變數如下:
STATIC_DIR = os.path.join(BASE_DIR, "static")

新增STATICFILES_DIRS串列,串列中放入剛剛創的STATIC_DIR變數如下:
STATICFILES_DIRS = [
    STATIC_DIR,
]

3.去瀏覽器輸入http://127.0.0.1:8000/static/images/xxx.jpg,將會顯示剛剛放的圖片


4.使用靜態檔案前必須在模板<html>之外加上以下:
{% load staticfiles %}

之後新增img tag
<img src="{% static "images/hp.jpg" %}" alt="me" >

完成


Django的靜態檔案也可以應用在css跟javascript,以css舉例:


1.在static資料夾新增css資料夾並放入css檔

2.模板加入如下
<link rel="stylesheet" type="text/css" href="{% static "css/mycss.css" %}">

完成


設定Media,settings.py新增如下:

MEDIA_DIR = os.path.join(BASE_DIR, 'media').replace('\\', '/')
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'

如果settings.py
DEBUG = False
runserver 指令要加上--insecure

2017年10月24日 星期二

Django - Templates筆記

這邊要講如何利用Django的Template模板來完成動態網頁

1. 創建Templates資料夾於專案目錄底下

更改settings.py讓Django找到Templates的路徑

2. 賦予一個變數templates資料夾路徑
TEMPLATE_DIR = os.path.join(BASE_DIR, 'templates').replace('\\', '/')

找到TEMPLATE = []中的 DIRS 並貼上變數TEMPLATE_DIR

連接templates資料夾完成


3. 新增模板於templates,如index.html,內容加上模板標籤

# index.html
<h1>Hello index</h1>
{{ insert_me }} # 模板變數


4. 在views的function中,使用render()選擇index.html並傳參數給模板

def index(request): 
    my_dict = {'insert_me':'Hello I am from views.py'} 
    return render(request, 'index.html', context = my_dict)

完成



2017年10月23日 星期一

Django - View & Mapping

此筆記將簡略的記錄創造好app之後,該做的事情。

views.py裡新增function

urls.py新增 路徑與app.function做mapping


# views.py

from __future__ import unicode_literals

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
return HttpResponse('<em>My Second App</em>')



# urls.py

from django.conf.urls import url
from django.contrib import admin
from apptwo import views
urlpatterns = [
url(r'^$', views.index),
        url(r'^admin/', admin.site.urls),
]


現在我們已經知道要如何去做到Mapping了,可是會發現一個問題,假設有多個App,每個App都有多個Function,依照上述的設定urls.py將會變的很亂,而Django也有解決此問題的方法。

我們利用include()在project的urls.py中做app的設定,如下:

# first_project/urls.py

from django.conf.urls import url
from django.conf.urls import include # 新增這個

urlpatterns = [
url(r'^first_app/', include('first_app')), 
]


完成之後在App目錄底下新增urls.py

# first_app/urls.py

from django.conf.urls import url
from apptwo import views

urlpatterns = [
url(r'^index$', views.index, name='index'),
]


我大概解釋一下,上述設定將每個App的路由交給各自目錄的urls.py處理而不是全部都集中於project的urls.py,結果將會是http://127.0.0.1:8000/first_app/index


first_app/代表執行first_app這個App都要有first_app/,而之後的index代表著first_app中views的index function

有沒有覺得很神奇呢?

2017年10月21日 星期六

Django - Application筆記

專安中使用startapp新增wenb application
python manage.py startapp first_app

產生的first_app中會有以下檔案

# 作為package用
__init__.py

# 用來設定admin介面
admin.py

# 存放特定的設置
apps.py

# 用來設定資料模型
models.py

# 用於放置測試函式來測試程式碼
tests.py

# 用於控制請求與回應
views.py

# 存放資料庫與模組關聯的資訊
migrations資料夾

新增app之後,要去settings.py註冊新的app以便整個Django專案使用
找出INSTALLED_APPS,加入新的app


2017年10月14日 星期六

Django - 專案

指令django-admin

創造專案名稱為myproject
django-admin startproject myproject


新增專案後,資料夾裡會有以下五個py檔

 # treat django file as a python package  
__init__.py

# configuration
settings.py

# routes
urls.py

# for deploying production
wsgi.py

# include all the django commands as build the web app
manage.py 

使用runserver來啟動server,預設URL http://127.0.0.1:8000/
python manage.py runserver


Django - 虛擬環境與安裝

Virtual Enviroment虛擬環境

安裝Django於虛擬環境,方便安裝失敗重新安裝,或是控制使用新舊版本

安裝虛擬環境
pip install virtualenv

新增虛擬環境
virtualenv env_myproject

於新增虛擬環境的資料夾中輸入以下指令

Windows:
env_myproject\scripts\activate

OSX:
source env_myproject/bin/activate


安裝Django
pip install django

也可以指定版本
pip install django==1.11.2

BTW:注意在開啟虛擬機後才安裝Django,不然會被安裝在本機

2017年10月13日 星期五

Python - Name & Main筆記

常常會在程式的下看到如下:
if __name__ == '__main__':

__name__是什麼?

__name__用於顯示出目前主程式
主程式會顯示__main__
副程式會直接顯示module模組名稱,如:one.py # one

假如有兩個檔案one.py & two.py
# one.py

def func():
print('func() in one')

print('Top level one.py')
s is one.py {}'.format(__name__))


# two.py

import one
print('Top level two.py')
one.func()

print('This is two.py {}'.format(__name__))


執行two.py
python3 two.py

結果:
Top level one.py
This is one.py one
Top level two.py
func() in one
This is two.py __main__

2017年10月7日 星期六

Python - Decorators筆記

將函式當作引數傳給另外一個函式

def new_decorator(func):

    def wrap_func():
        print ("Code would be here, before executing the func")

        func()

        print ("Code here will execute after the func()")

    return wrap_func

def func_needs_decorator():
    print ("This function is in need of a Decorator")

func_needs_decorator()
# Reassign func_needs_decorator
func_needs_decorator = new_decorator(func_needs_decorator)

func_needs_decorator()


等同於以下簡化的方式

def new_decorator(func):

    def wrap_func():
        print ("Code would be here, before executing the func")

        func()

        print ("Code here will execute after the func()")

    return wrap_func

@new_decorator
def func_needs_decorator():
    print "This function is in need of a Decorator"

func_needs_decorator()

2017年10月6日 星期五

Python - Regular Expressions筆記

用法
找出you關鍵字,回傳布林值
import re

text = 'abc1234'

match = re.search('a',text)

if match:
    print(m.group())


利用split()分割字串成串列
print(re.split('@','yous421@gmail.com')) # return list

利用findall()回傳不重複的匹配
print(re.findall('you',text)) # return list



‘\’:跳脫字元
‘.’ :匹配除了\n外任何單一字元
‘*‘:匹配任何數字(包括零)
‘^‘:匹配開始,^abc
‘$‘:匹配結尾,56$
‘?‘:匹配非必須項目(零或一個)
‘|’:或
\d:一個數字
\D:一個非數字
\w:一個英數字元
\W:一個非英數字元
\s:一個空白字元
\S:一個非空白字元
\b:一個單字範圍(介於\w與\W,無論順序為何)
\B:一個非單字範圍

prev{m}:m個連續prev
prev{m, n}:m到n連續prev
prev{m, n}?:
[abc]:a或b或c
[^abc]:not a或b或c
prev(?= next):prev,如果後面有next
prev(?! next):prev,如果後面沒有next
(?<= prev) next:如果next之前是prev,匹配next
(?<! prev) next:如果next之前不是prev,匹配next

2017年10月4日 星期三

Python - Module & Package筆記

利用module使用其他py檔的方法及類別

# mymodule.py

def func_in_module():
    print('using module')

# myprogram.py

import mymodule as md # 使用別名

md.func_in_module

以下方法同上,缺點為容易佔用太多記憶體
from mymodule import *

為了防止記憶體佔用太多,只挑選要用的方法
from mymodule import func_in_module

放在資料夾的情況,以此類推
from os.mymoduls import func_in_module

將__init__.py加入資料夾建立Package
os/
- __init__.py
- func_in_module









2017年10月3日 星期二

Python - 例外處理筆記

用法

try:
f = open('cool', 'r') # mode code is supposed to be 'w'
f.write('Test text')
except Exception as e:
print('Error:{}'.format(e))
else:
        print('success')
finally:
print('finally')

Python - I/O筆記

open(filename, mode):

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

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

write():寫入檔案
read():讀取
readline():行為單位讀取
readlines():行為單位讀取,並建立串列
seek()
close()

Python - OOP筆記

宣告方式

class Dog():
    
    species = 'mammal'

    def __init__(self, name): # 初始化方法
        self.name = name
        print("{} has been created".format(self.name))

mydog = Dog("Blacky") 
print(mydog.mammal) # 類別屬性Class Attribute
print(Dog.mammal) # 類別屬性Class Attribute
print(mydog.name) # 實例(物件)屬性Instance Attribute



例子圓形類別,計算圓面積
class Circle():
pi = 3.14

def __init__(self, radius=1):
self.radius = radius

def area(self):
return (self.radius ** 2) * Circle.pi  # 圓面積公式需要特別註明是哪種類型的屬性

tiny = Circle(2)
print(tiny.area()) 



類別變數Counter為例

class Person:
count = 0
def __init__(self):
Person.count += 1
print(Person.count)

tom = Person()
jack = Person()
amy = Person()


繼承
class Person(Alien, God, Monster):  #可實行多重繼承


封裝
利用雙底線__來封裝變數

class Person:

def __init__(self, a=2, b=3):
self.__a=a
self.__b=b

def do(self):
print(self.__a + self.__b)


呼叫父類別的建構子
class Father():
    def __init__(self):
        print("last name Hsieh")

class Son(Father):
    def __init__(self):
        Father.__init__(self)
        print("Son created")



class Father():
    def __init__(self):
        print("last name Hsieh")

class Son(Father):
    def __init__(self):
        super(Son, self).__init__()
        print("Son created")



特別method名稱

class Book():
def __init__(self, name, pages):
self.name = name
self.pages = pages
def __str__(self):
return "Name:{}".format(self.name)
def __len__(self):
return self.pages
def __del__(self):
print("A book is deleted.")

b = Book("The Guide", 20)

print(b) # __str__
print(len(b)) # __len__
del b # __del__
更多參考https://openhome.cc/Gossip/Python/SpecialMethodNames.html