Send Email Attachments with Unicode Filenames in Django

Send Email Attachments with Unicode Filenames in Django

使用 MIMEApplication 並設置 attachment 的 header
不然如果檔名有中文的話
用 Gmail 收到的附件檔名會是 noname

def withdraw_send_email(request, pk):
    withdraw = get_object_or_404(Withdraw, pk=pk)

    email = '[email protected]'
    subject = _(u'Packer 數位發行服務')
    body = render_to_string('dps/email/withdraw_notice.html', {})

    message = EmailMessage(
        subject=subject,
        body=body,
        to=[email, ],
    )
    message.content_subtype = 'html'

    from email.mime.application import MIMEApplication

    # 檔名包含中文的話,要用這種方式 Gmail 收到的附件檔名才不會是 noname
    filename = '%s 結算表.xlsx' % (withdraw.serial_number[:6].encode('utf-8'))
    file_data = withdraw.file.read()
    attach_file = MIMEApplication(file_data, _subtype='vnd.ms-excel')
    attach_file.add_header('Content-Disposition', 'attachment; filename="%s"' % (filename))

    message.attach(attach_file)

    message.send()

    return HttpResponse('OK')

ref:
https://docs.python.org/2/library/email.mime.html

Debug your Django project

Debug your Django project

How to debug in Django, the good way
http://stackoverflow.com/questions/1118183/how-to-debug-in-django-the-good-way

pdb or ipdb

ref:
ipdb: Interactive Python Debugger with IPython
https://vinta.ws/code/ipdb-interactive-python-debugger-with-ipython.html

django-pdb

$ pip install django-pdb
$ ./manage.py runserver 0.0.0.0:8000 --ipdb

ref:
https://github.com/tomchristie/django-pdb

Templatetags

from django import template
register = template.Library()

@register.filter 
def ipdb(element):
    import ipdb; ipdb.set_trace()
    return element

ref:
http://stackoverflow.com/questions/1118183/how-to-debug-in-django-the-good-way

django-extensions

$ pip install django-extensions
$ ./manage.py runserver_plus 0.0.0.0:8000

ref:
https://github.com/django-extensions/django-extensions

django-devserver

$ pip install django-devserver
$ ./manage.py runserver 0.0.0.0:8000 --werkzeug

上面這兩個 plugins 都是用 Werkzeug 的 interactive debugger
跟 Flask 用的那個一樣
你可以直接在瀏覽器的 Traceback 畫面按那個 terminal 圖示進入互動 debug 模式

ref:
https://github.com/dcramer/django-devserver

django-debug-toolbar

$ pip install django-debug-toolbar

ref:
https://github.com/django-debug-toolbar/django-debug-toolbar

coverage.py: Python code coverage

coverage.py: Python code coverage

coveralls.io 跑 python project 的覆蓋率就是用 coverage.py
nose 也是用 coverage.py
基本上 Python 社群幾乎都是用這個

ref:
http://nedbatchelder.com/code/coverage/
http://www.cnblogs.com/coderzh/archive/2009/12/01/1614874.html

Install

$ pip install coverage

Configuration

in .coveragerc

[run]
branch = True
source = email_confirm_la
omit =
    email_confirm_la/migrations/*
    email_confirm_la/south_migrations/*
    email_confirm_la/tests/*

[run] 底下的 include 和 omit 是用來指定 filename pattern
而 source 是用來指定 package 或目錄

omit 是「忽略」的意思

ref:
http://nedbatchelder.com/code/coverage/config.html

Usage

# 會自動套用當前目錄下的 .coveragerc
$ coverage run setup.py test
$ coverage report
$ coverage html

# 默認會一併測試所有包含第三方 lib 在內的 Python 程式碼(如果你沒有寫 .coveragerc 的話)
$ coverage run test.py

# 你可以用 --source 指定只測試某個 packages 或目錄
$ coverage run --source=haul setup.py test
$ coverage run --source=haul tests/test.py
$ coverage run --source=. manage.py test

# show report in terminal
$ coverage report

# generate html report in the same dir
$ coverage html

ref:
http://nedbatchelder.com/code/coverage/cmd.html
http://nedbatchelder.com/code/coverage/source.html

Usage with nose

$ pip install nose nose-cov

# output terminal
$ nosetests --with-cov --cov haul tests/

# output html
$ nosetests --with-cov --cov-report html --cov haul tests/ 
Travis-CI for Python: a .travis.yml example

Travis-CI for Python: a .travis.yml example

Configuration

in .travis.yml

language: python

# 多個 env 要寫在同一行
env:
  - DPS_ENV=test OTHER_ENV=whatever
  - DPS_ENV=development OTHER_ENV=whatever

python:
  - "2.7"
  - "3.3"

before_install:
  - sudo apt-get update -qq
  - sudo apt-get install -qq libxml2-dev libxslt1-dev

install:
  - pip install -r requirements_test.txt --use-mirrors

script:
  - coverage run --source=haul setup.py test

notifications:
  email:
    - [email protected]

after_success:
  - coveralls

要注意的是多個 environment variables 要寫在同一行
否則會被當成多個環境
每個環境都會跑一次 CI

ref:
http://docs.travis-ci.com/user/ci-environment/
http://docs.travis-ci.com/user/build-configuration/
http://docs.travis-ci.com/user/languages/python/
http://docs.travis-ci.com/user/database-setup/

in .coveralls.yml

如果是 public repo 的話,不需要特別設定什麼

ref:
https://coveralls.io/docs/python
https://github.com/coagulant/coveralls-python

How to Set a Variable in Django Templates?

How to Set a Variable in Django Templates?

Creating a custom template tag for assigning variables in Django template.

in app/templatetags/common.py

from django import template
register = template.Library()

class SetVarNode(template.Node):

    def __init__(self, var_name, var_value):
        self.var_name = var_name
        self.var_value = var_value

    def render(self, context):
        try:
            value = template.Variable(self.var_value).resolve(context)
        except template.VariableDoesNotExist:
            value = ""
        context[self.var_name] = value

        return u""

@register.tag(name='set')
def set_var(parser, token):
    """
    {% set some_var = '123' %}
    """
    parts = token.split_contents()
    if len(parts) < 4:
        raise template.TemplateSyntaxError("'set' tag must be of the form: {% set <var_name> = <var_value> %}")

    return SetVarNode(parts[1], parts[3])

in app/templates/xxx.html

{% load common %}

{% if work and is_public_work %}
    {% ifequal link_class 'info_box pull-right' %}
        {% set ga_label = 'card' %}
    {% else %}
        {% set ga_label = ga_label_detail %}
    {% endifequal %}
    <a class="{{ ga_label }}">123</a>
{% endif %}