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

有沒有覺得很神奇呢?