Sunday, June 17, 2012

Django -- redirect to outside link

in views.py
out_url = "http://www.google.com"
return render_to_response('short/redirect.html', {'out_url':out_url})
in short/redirect.html
<meta http-equiv="refresh" content="0; URL={{ out_url }}">

Tuesday, June 12, 2012

Django -- upload file

上傳資料,參考
http://oranlooney.com/django-file-uploads/
http://www.nitinh.com/2009/02/django-example-filefield-and-imagefield/
http://gibuloto.com/blog/models-dot-imagefield/ 

(1)設定上傳用的資料夾
Django 1.4 裡面有提供 MEDIA_URL 和 MEDIA_ROOT
這兩個部份的設定主要是讓使用者上傳資料和顯示

這邊就不從開新的app開始說,直接從settings.py和models.py設定開始

首先是settings.py的設定
cd //var/www/mutarock/mutarock
vim settings.py
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), '..', 'multimedia').replace('\\','/')
MEDIA_URL = '/multimedia/'
設定完之後移到上一層去
cd ..
mkdir multimedia
接下來是apps裡面models.py的設定
class Picture(models.Model):
    image = models.ImageField(upload_to='pic')

上面的models開了一個欄位,讓使用者上傳圖片,在django裡面,系統不會真的把東西儲存在資料庫裡面
而是儲存資料在系統裡面的位置

MEDIA_ROOT 和 upload_to 的設定,有以下的關係

MEDIA_ROOT = ‘/home/myname/files/
upload_to=’videos’
file: abc.flv
results in: /home/myname/files/videos/abc.flv

MEDIA_ROOT = '/home/myname/files/'
upload_to='/videos'
and file : abc.flv
result will be saved in : '/videos/abc.flv' (i.e., root directory of filesystem)

upload_to也可以加進去上傳的日期和時間
upload_to='videos/%Y/%m/%d'
如果上傳時間是2012 Jun 12
檔案就會儲存到 /home/myname/files/videos/2012/06/12

(2)設定form.py
form的部分可以直接建立在html裡面,網路上的參考文章則是順便教了如何用django實做form
連到自己的apps裡面新增一個form.py
vim form.py
輸入下面的code
from django import forms
from PIL import Image
class PictureUploadForm(forms.Form):
    image = forms.ImageField()
    

    def clean_image(self):
        ' reject large images.'
        max_size = 10**7
        if len(self.cleaned_data['image'].read()) > max_size:
            raise forms.ValidationError('Image must be less then %d bytes.' % max_size)
        else:
            return self.cleaned_data['image']

上面的code會有一個可以欄位,讓使用者決定要上傳什麼圖檔
其中也自訂一個function,檢查上傳的檔案是否超過我們自定的大小

(3)設定views.py
import uuid #use for data name
from apps.picture.form import PictureUploadForm  #import your form

def picture_upload(request):

    picture = Picture()
    if request.method != 'POST':
        form = PictureUploadForm()
    else:
        form = PictureUploadForm(request.POST, request.FILES)
        if form.is_valid():

            # an UploadedFile object
            uploadedImage = form.cleaned_data['image']
            file_name = uuid.uuid4().hex
            file_extension = os.path.splitext(uploadedImage.name)[-1]
            full_file_name = file_name + file_extension

            # save picture object
            picture.image.save(
                full_file_name, 
                request.FILES['image'], 
                save = False
            )
            picture.save()
            return render_to_response(
                'example/result.html'
                {'result': "Upload success",},
                context_instance = RequestContext(request))


    return render_to_response(
        'example/picture_upload.html',
        {'form':form},
        context_instance = RequestContext(request))

簡單說明上面的code
如果request不是POST,就只回傳form
如果是POST,則把使用者選擇的圖片上傳到系統裡面
檔名的部分我是用uuid,這樣幾乎可以確保檔案名稱不會重複
file_extension是檔案的格式,例如 jpg 或是 png
最後就印出"Upload success"給使用者


picture_upload.html
<form enctype="multipart/form-data" method="post" action="example/picture_upload">
    {% csrf_token %}   
    <table>
        {{form.as_p}}
    </table>
    <input type="submit" value="Submit" id="Save"/>
</form>

result.html
<p> {{ result }} </p>


上傳檔案大概就是這樣,主要就是設定好
MEDIA_ROOT
upload_to
大概就沒問題了


MEDIA_URL的部分是要讓使用者可以讀取或是顯示出上傳的東西
我是設定成
MEDIA_URL = '/multimedia/'
然後再主要的urls.py加上
urlpatterns += patterns('',
    url(r'^multimedia/(?P.*)$', 'django.views.static.serve',
                 {'document_root': settings.MEDIA_ROOT}),
所以我輸入
http://localhost:8000/multimedia/pic/FileName
就可以顯示出我上傳的圖片了


Sunday, June 10, 2012

Django -- create a new app - part3

part 1和2已經記錄了如何開一個新的app和urls.py的設定
這一篇就把剩下的部分講完
這邊主要寫view.py和html的部分

首先先連到apps/polls/
cd //var/www/mutarock/apps/polls
vim views.py
首先先來新增一個index,這個可以印出資料庫最近新增的幾個投票
from django.template import Context, loader
from apps.polls.models import Poll
from django.http import HttpResponse

def index(request):
    latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
    t = loader.get_template('polls/index.html')
    c = Context({
        'latest_poll_list': latest_poll_list,
    })
    return HttpResponse(t.render(c))
上面的code會抓出最近的5個投票,並且讀取polls/index.html這個templates
並且把投票資訊傳給他顯示

存檔之後執行熟悉的
python manage.py runserver
開啟瀏覽器 http://127.0.0.1:8000/polls 應該會跑出錯誤訊息
TemplateDoesNotExist at /polls/
polls/index.html
這是因為我們還沒有把templates建立起來,我們前面只是設定

移到前兩層,去建立我們的templates資料夾
cd //var/www/mutarock
mkdir templates
cd templates
mkdir polls
目前這個系統的資料夾應該會像
mutarock/
    manage.py
    mutarock/
    apps/    
        polls/
    templates/
        polls/
移到 templates/polls 資料夾去建立我們的index.html
{% if latest_poll_list %}
{% if latest_poll_list %}
    <ul>
    {% for poll in latest_poll_list %}
        <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}
這樣就可以順利顯示我們的polls資訊了
其他的細節我就不細講了,教學都還滿仔細的,我覺得自己講不太清楚,所以detail, vote, result直接看教學比較好
教學三教學四


Thursday, June 7, 2012

Django -- create a new app - part2

part1是一些有關models建立以及如何和系統互動
這邊先來記錄一下如何顯示

首先先修改settings.py中的 TEMPLATE_DIRS
cd //var/www/mutarock/mutarock/
vim settings.py
TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    os.path.join(os.path.dirname(__file__), '..', 'templates').replace('\\','/'),
)
這個設定主要是告訴django你的模板放在哪裡,我這邊用的是相對路徑
方便將來移植,如果覺得完全不會動到就用絕對路徑也是可以的啦

回到前一層去新增templates資料夾
cd ..
mkdir templates
cd templates/
mkdir polls
我希望每個apps的模板放的地方不一樣,所以多新增一個子資料夾polls
到目前為止準備工作已經差不多了,接下來還有3個部分
  • 設定 urls.py
  • 編輯 /apps/polls/views.py
  • 編輯顯示用的 html

下面先來處理urls.py
這部分有很多不同的做法,你可以把全部的urls路徑都放到主資料夾下面的urls.py
也可以用導向的方式,在每個apps裡面都有自己的urls.py
教學上面的例子,下面兩個做法等價,挑自己喜歡的風格

例子一:
全都放在 //var/www/mutarock/mutarock/urls.py
from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^polls/$', 'polls.views.index'),
    url(r'^polls/(?P\d+)/$', 'polls.views.detail'),
    url(r'^polls/(?P\d+)/results/$', 'polls.views.results'),
    url(r'^polls/(?P\d+)/vote/$', 'polls.views.vote'),
    url(r'^admin/', include(admin.site.urls)),
)


例子二
主資料夾負責導向
//var/www/mutarock/mutarock/urls.py
from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^polls/', include('apps.polls.urls')),
    url(r'^admin/', include(admin.site.urls)),
)

apps的資料夾負責細節
//var/www/mutarock/apps/polls/urls.py (預設是沒有這個檔案,要自己新增)
from django.conf.urls import patterns, include, url

urlpatterns = patterns('apps.polls.views',
    url(r'^$', 'index'),
    url(r'^(?P\d+)/$', 'detail'),
    url(r'^(?P\d+)/results/$', 'results'),
    url(r'^(?P\d+)/vote/$', 'vote'),
)
之後再browser上面輸入 http://127.0.0.1/polls 系統就會知道要導向到polls的urls.py

  • 後面什麼都不接,會去找polls裡面view.py的index 
  • 後面接polls的id,找deatils
  • 以此類推


urls.py比較基本的概念就是這些,個人比較偏好第2種做法
主資料夾的urls.py看起來會比較整齊
不然開了幾十個apps不就可能會有幾百行在裡面


Django -- admin page

django的admin page相當的強大
可以顯示出來的東西非常多,不過還有很多細節需要去研究

首先先修改 settings.py
django.contrib.admin 的註解拿掉
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'apps.polls',
)


修改urls.py
from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
import settings

admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'mutarock.views.home', name='home'),
    # url(r'^mutarock/', include('mutarock.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
)
這邊的urlpattern是利用regular expression去表示
所以在domain後面接 admin 就會去開啟admin page
之後新增不同的app和服務之後就會實際了解如何作用

OK之後可以輸入
python manage.py runsever
打開瀏覽器進入你在domain下面的admin page
例如 http://127.0.0.1/admin
應該會看到














OK之後,下一步是把polls app也加進去admin page
這樣就可以方便管理了
先移到polls的資料夾下面並建立admin.py檔案
cd //var/www/mutarock/apps/polls/
vim admin.py
輸入
from polls.models import Poll
from django.contrib import admin

admin.site.register(Poll)

這樣就可以把這個apps註冊到admin page裡面
至於顯示的部分其實非常多樣化,可以依照apps的欄位顯示,或者顯示一些圖片或是縮圖
可以參考一下教學

Wednesday, June 6, 2012

Django -- create a new app - part1

為了方便管理全部的apps
所以先在外層的mutarock資料夾開一個apps的app
將來這個project裡面全部的app都放進去這裡
cd //var/www/mutarock
python manage.py startapp apps
以後的app都把它放在這麼資料夾下面
下面用tutorial的範例,簡單的投票系統做例子
cd /apps
python ./manage.py startapp polls
目前整個project的資料夾應該像下面這樣
mutarock/
    manage.py
    mutarock/
    apps/    
        polls/
polls則是長這個樣子
polls/
    __init__.py
    models.py
    tests.py
    views.py
models.py主要是這個app的資料型態,例如這個例子裡面有Poll和Choice
Poll 是只個別的投票
Choice 是各個選項
views.py則是一些動作,例如針對request做運算,或是回傳一些資料資料給使用者

實際開始編輯models.py
from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice = models.CharField(max_length=200)
    votes = models.IntegerField()
其他細節就不多說了,可以去看教學
只記錄下幾個關鍵
建立完新的app之後要記得去啟動他
到專案的資料夾下面

cd //var/www/mutarock/mutarock
vim settings.py
其中一個欄位是INSTALLED_APPS,在這邊把自己的app加進去
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'apps.polls', #這個範例的app
)
OK之後可以利用強大的managa.py去顯示這個app會建立的哪些table有哪些欄位(based on your model)
python manage.py sql polls
確定應該沒有問題之後就輸入
python manage.py syncdb
系統就會實際把table建好


============================================================
PS 建立完之後可以利用
python manage.py shell
這個語法去實際和系統互動 以下是教學提供的幾個例子,我就貼過來自己看
>>> from polls.models import Poll, Choice   # Import the model classes we just wrote.

# No polls are in the system yet.
>>> Poll.objects.all()
[]

# Create a new Poll.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> p = Poll(question="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> p.save()

# Now it has an ID. Note that this might say "1L" instead of "1", depending
# on which database you're using. That's no biggie; it just means your
# database backend prefers to return integers as Python long integer
# objects.
>>> p.id
1

# Access database columns via Python attributes.
>>> p.question
"What's new?"
>>> p.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<utc>)

# Change values by changing the attributes, then calling save().
>>> p.question = "What's up?"
>>> p.save()

# objects.all() displays all the polls in the database.
>>> Poll.objects.all()
[<Poll: Poll object>]
可以看到最後一個例子回傳的東西相當不人性化
看不出來是什麼鬼
所以可以在原來的models.py裡面加一些東西,讓資料顯示更明顯
class Poll(models.Model):
    # ...
    def __unicode__(self):
        return self.question

class Choice(models.Model):
    # ...
    def __unicode__(self):
        return self.choice
教學上面提到,熟悉python的人一般會使用 __str__ 而不是 __unicode__
這邊會建議使用 __unicode__ 是因為django預設是用unicode

Django -- database

安裝 mysql
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install mysql-server mysql-client python-mysqldb python-django

建立一個django用的database
mysql -u root -p
create database djangodb;
exit;

修改settings.py
cd //var/www/mutarock/mutarock/
vim settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'djangodb',                      # Or path to database file if using sqlite3.
        'USER': 'USERNAME',                      # Not used with sqlite3.
        'PASSWORD': 'PASSEORD',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}
ENGINE: 是database的種類,我是用mysql
NAME: database名稱
USER & PASSWORD: 該資料庫的使用者,如果不是使用root的話要記得放寬權限,不然syncdb的時候會有錯誤訊息

同步資料庫
輸入指令
python manage.py syncdb
就會在所選擇的database裡面新增幾個基本的table
之後開始寫app,也是利用這個指令將app所需要的table建立在database裡面
應該也會要求建立一個登入用的帳號

Tuesday, June 5, 2012

Django -- install/setup


參考 https://docs.djangoproject.com/en/dev/intro/tutorial01/ ~ /tutorial04/

Install:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python-setuptools
sudo apt-get install python-pip
sudo pip install django


Create a project:
cd //var/www/
sudo django-admin.py startproject mutarock

資料夾hello長的像這樣~~
mutarock/
    manage.py
    mutarock/
        __init__.py
        settings.py
        urls.py
        wsgi.py
  • 各別檔案和資料夾的敘述請見(連結)

確認一下django的server是否正確:
python manage.py runserver
如果沒有問題的話,應該就可以看到
----------------------------------------------------------------
Validating models...
0 errors found.

Django version 1.4, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
----------------------------------------------------------------
打開瀏覽器
http://127.0.0.1:8000
可以看到預設的頁面