almost 3 years ago

I didn't expect creating a radio input in a form using Bootstrap3's style could have some many pitfalls.

Here is a model I have:

class UserProfile(models.Model):
    GENDER_CHOICES = (('M', 'Male',), ('F', 'Female',))
    fullname = models.CharField(u'Name', max_length=10)
    sex = models.CharField(u'Gender', max_length=1, choices=GENDER_CHOICES)
    # ... and 11 other fields

Here is the corresponding ModelForm:

from django.forms.widgets import RadioSelect

class UserProfileForm(ModelForm):
    class Meta:
        model = UserProfile
        widgets = {
            'sex': forms.RadioSelect()

I have a sex field which let users to pick their gender. When running the code above, I get three choices instead of two:

  • '--------' # django automatically insert this 'default' option
  • 'Male'
  • 'Female'

This is of course not what we want. There should only be two options, 'Male' and 'Female'. So to correct this issue, I had to add TWO extra parameters to the Model:

sex = models.CharField(u'Gender', max_length=1, choices=GENDER_CHOICES, blank=False, default='M')

Note that I added blank=False AND default='M'. If you only include blank=False, you will still see the '--------' option. It is important to have both of them set.

Now, I want to style my forms using Bootstrap3. To do this, I recommend using crispy-forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from crispy_forms.bootstrap import InlineRadios

class UserProfileForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UserProfileForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.method = 'post'
        self.helper.form_action = 'index'
        self.helper.layout.append(Submit('save', 'Save'))

    class Meta:
        model = UserProfile

Crispy-form creates a Bootstrap3 style input field for every single field defined in the model when this line runs:

self.helper = FormHelper(self)

The UserProfile model has 13 fields. It is nice that I don't have to specify each one of the 13 fields. But here comes the problem, when the radio input is been rendered. The male and female options are listed vertically. I want them to be listed horizontally. Crispy-form does provide an inline option for rendering radio inputs horizontally. This is nice, but how can I replace the default Layout of the gender field with the suggested inline Layout?

self.helper[1] = InlineRadios('sex')

Crispy-forms allows you to access the Layout of each field by using index.

With the tweaks above, now I have a wonderful radio input for gender selection :) So many small things need to be taken care of for something seems so trivial.

almost 3 years ago

When writing a user registration form in Django, you are likely to encounter this error message:

A user with that Username already exists.

This happens when a new user wants to register with a name that is already stored in the database. The message itself is self explainatory but what I need is to display this message in Chinese. According to Django's documentation, I should be able to do this:

class RegistrationForm(ModelForm):
    class Meta:
        model = User
        error_messages = {
            'unique': 'my custom error message',

But this didn't work. It turns out that Django's CharField only accepts the following error message keys:

Error message keys: required, max_length, min_length

Thanks to this StackOverflow post, here is how Django developers solved this problem in the UserCreationForm, we can adopt their solution to this situation:

class RegistrationForm(ModelForm):
    # create your own error message key & value

    error_messages = {
        'duplicate_username': 'my custom error message'
    class Meta:
        model = User
    # override the clean_<fieldname> method to validate the field yourself

    def clean_username(self):
        username = self.cleaned_data["username"]
            #if the user exists, then let's raise an error message

            raise forms.ValidationError( 
              self.error_messages['duplicate_username'],  #user my customized error message

              code='duplicate_username',   #set the error message key

        except User.DoesNotExist:
            return username # great, this user does not exist so we can continue the registration process

Now when you try to enter a duplicate username, you will see the custom error message being shown instead of the default one :)

almost 3 years ago



$ gem sources --remove
$ gem sources -a
$ gem sources -l
# 请确保只有
$ gem install rails

almost 3 years ago


from django.db import models

class User(models.Model):
    user_name = models.CharField()



import django.forms as forms
from models import User

class Login(forms.ModelForm):
    user_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': u'输入Email地址'}))
    class Meta:
        model = User


import django.forms as forms
from models import User

class Login(forms.ModelForm):
    class Meta:
        model = User
        widgets = {
             'user_name': forms.TextInput(attrs={'placeholder': u'输入Email地址'}),
almost 3 years ago



p = (170, 0.1, 0.6)
if p[1] >= 0.5:
      print u'好深的'
if p[2] >= 0.5:
    print u'好亮啊'


from collections import namedtuple

Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
p = Color(170, 0.1, 0.6)
if p['saturation'] >= 0.5:
      print u'好深的'
if p['luminosity'] >= 0.5:
    print u'好亮啊'


假设有一个叫做颜色的列表, 需要计算出这个列表里每个颜色的名字被重复了几次

colors = ['red', 'green', 'red', 'blue', 'green', 'red']

d = {}


for color in colors:
    if color not in d:
        d[color] = 0
    d[color] += 1


for color in colors:
    d[color] = d.get(color, 0) + 1


from collections import defaultdict
d = defaultdict(int)

for color in colors:
    d[color] += 1



names = ['raymond', 'rachel', 'matthew', 'roger', 'bettry', 'melissa', 'judith', 'charlie']


d = {}
for name in names:
    key = len(name)
    if key not in d:
        d[key] = []


for name in names:
    key = len(name)
    d.setdefault(key, []).append(name)


d = defaultdict(list)
for name in names:
    key = len(name)

使用Keyword Argument

tw('@obama', False, 20, True)


twitter_search('@obama', retweets=False, numtweets=20, popular=True)



t = y
y = x + y
x = t


x, y = y, x+y




names = ['raymond', 'rachel', 'matthew', 'roger', 'bettry', 'melissa', 'judith', 'charlie']


del names[0]
names.insert(0, 'mark')


from collections import deque


names = deque(['raymond', 'rachel', 'matthew', 'roger', 'bettry', 'melissa', 'judith', 'charlie'])


almost 3 years ago



class Answer(models.Model):
    day_id = models.IntegerField()
    set_id = models.IntegerField()
    question_id = models.IntegerField()
    answer = models.TextField(default='')
    user = models.ForeignKey(User)

    def __unicode__(self):
        result = u'{4}:{0}.{1}.{2}: {3}'.format(self.day_id, self.set_id, self.question_id, self.answer,
        return result

这个Model除了自带的Field外还有一个外键 user,用于引用Django自带的User表。

我需要将所有用户的每天的答案都输出到一个文件里, 所以首先要提取出所有的答案:

answers = Answer.objects.all()

for answer in answers:
    print answer


result = u'{4}:{0}.{1}.{2}: {3}'.format(self.day_id, self.set_id, self.question_id, self.answer,

当打印answer这个Object的时候,除了会打印出自身的Field外,还会打印出 由于Answer这个表中没有user.id这个Field,所以要单独请求User的表给出相应的id。这个就是造成980次请求的原因。每次打印一个answer,都要请求一遍User表来获取相对应的用户id。


answers = Answer.objects.all().select_related('user')

for answer in answers:
    print answer


SELECT ... FROM "answer" INNER JOIN "auth_user" ON ( "answer"."user_id" = "auth_user"."id" )


almost 3 years ago



  • 每天凌晨1点对数据库进行备份
  • 每次备份后将数据库文件加上时间戳并存储到指定文件夹
  • 备份完成后在log里写入当前时间和备份文件名


#! /bin/bash

cur_time=$(date +%Y_%m_%d_%k_%M_%S)    #获取当前时间,并按照 年_月_日_小时_分钟_秒 的格式存储

file_name=./db_backup/db.sqlite3.bak_$cur_time    #将刚获取的时间接在备份文件名的后面

sqlite3 db.sqlite3 .dump > $file_name    #对一个sqlite数据库进行备份

now=$(date +'%x %X')    #获取现在的时间

output=$(printf "[ %s ] db backed @ %s" "$now" "$file_name")    #写一行log

echo $output >> ~/logs/cron.log    #将log写入指定文件




  1. crontab -e | 编辑你的定时工作脚本
  2. crontab -l | 查看你的工作脚本
  3. crontab -r | 删除你的工作脚本
  4. crontab -l > 文件名 | 将你的脚本备份到一个文件里
  5. crontab 文件名 | 将指定文件的内容复制到你的工作脚本



crontab -e


no crontab for root - using an empty one


export EDITOR=nano

上面例子中使用了nano,但你可以随意替换成pico、vi等任意编辑器。设置好后,再次执行crontab -e


0 1 * * * /home/cheng/



  • 分 0 - 59
  • 小时 0 - 23
  • 日 1 - 31
  • 月 1 - 12
  • 周日 sun, mon, tue, wed, thu, fri, sat (可以用这些缩写表示一周中的那一天,也可以用数字 0 - 7 表示, 注意0和7都是周日的意思)



0 17 * * sun  /scripts/


0 */6 * * * /scripts/


* * * * * /scripts/



每个用户通过crontab -e创建的脚本文件会被存储在:

cd /var/spool/cron/crontabs/



almost 3 years ago

I wrote two simple scripts for starting and stopping a gunicorn server that hosts a Django project.

Create a


source `which`  #assuming you use virtualenv

workon your_env_name # if you do not use virtualenv, remove this line the line above

gunicorn -c your_project_name.wsgi --daemon 

Create a


kill -9 `ps aux |grep gunicorn |grep your_app_name | awk '{ print $2 }'`  # will kill all of the workers

Once these scripts are created, don't forget to set the permission:

chmod 755
chmod 755

To run them:

almost 3 years ago

Bootstrap offers a great Accordion element but it needs a few patches:

  1. An up and down arrow beside the accordion's title would be nice.
  2. The clickable area is centered around the title text. If you click between the text and the background border, the accordion will not show or hide.
  3. A hide all or show all method would be nice.

I created a JSFiddle:

A few key points to point out,

  1. the up/down arrow switch is enabled by the CSS.

  2. I added the following to both the div.panel-heading and h4 element, so that the clickable area is the entire title div:

data-toggle="collapse" data-target='#collapse2'

The data-toggle="collapse" attribute makes your element clickable, by adding it to the div.title element, the entire div becomes clickable. Thus, when users click in between the title text and the border of the div.title element, the accordion will still respond.

The data-target="#collapse2" attribute will add and remove a class named collapsed when clicked. The CSS in the JSFiddle has different styles when collapsed appear and disappear.

  1. I removed the data-parent="#accordion" attribute to allow show all and hide all. If this attribute is added like in the Bootstrap's example, then only one section can be expanded at anytime.

  2. A great website for looking up Bootstrap icons (if you don't want to use the up/down arrow button), click here:


almost 3 years ago

I used Jasny's image upload plugin for Bootstrap to allow users upload images to a server. Later on, I had to populate a page with these uploaded images. Here is how I did it:

<!-- fileinput-exists is used instead of fileinput-new -->
<div class="fileinput fileinput-exists" data-provides="fileinput">
  <div class="fileinput-preview thumbnail" data-trigger="fileinput" style="width: 200px; height: 150px;">
  <!-- add the following line -->
  <img src="static/thumb.jpg">
    <span class="btn btn-default btn-file"><span class="fileinput-new">Select image</span><span class="fileinput-exists">Change</span><input type="file" name="..."></span>
    <a href="#" class="btn btn-default fileinput-exists" data-dismiss="fileinput">Remove</a>

That's it :)