vkill'blog

“技术本身没有太多价值,掌握了新的思考方式才是真的收获”
Pages: 3/34 First page Previous page 1 2 3 4 5 6 7 8 9 10 Next page Final page [ View by Articles | List ]
Image model 代码如下

# cat app/models/image.rb
class Image < ActiveRecord::Base
  has_attached_file :data,
                    :url  => "/system/images/:id/:style_:basename.:extension",
                    :path => ":rails_root/public/system/images/:id/:style_:basename.:extension",
                    :styles => { :normal => ['400x300#', :png], :thumb => ['200x150#', :png] }

  validates_attachment_size :data, :less_than => 2.megabytes
  validates_attachment_presence :data
end


那么想在 seed 中保存几个图片到 Image,就这样写

# cat db/seeds.rb
#first, add  gem "content_type"  to Gemfile and bundle install, http://rubygems.org/gems/content_type
attachment_file = "#{Rails.root}/public/images/rails.png"
attachment = {
  :original_filename => File.basename(attachment_file),
  :content_type => File.content_type(attachment_file),
  :tempfile => File.open(attachment_file, 'rb')
}
data_obj = ActionDispatch::Http::UploadedFile.new(attachment)
data_obj.original_filename = attachment[:original_filename]
data_obj.content_type = attachment[:content_type]
Image.create!(:data => data_obj)



后记:
使用 fixture_file_upload

include ActionDispatch::TestProcess
Image.create :data => fixture_file_upload("/root/profile.jpg", 'image/jpg')


结合 factory_girl 使用如下

include ActionDispatch::TestProcess
FactoryGirl.define do
  factory :attachment do
      name { Faker::LoremCN.word }
      describtion { Faker::LoremCN.word }
      data { fixture_file_upload(Rails.root.join('public', 'images', 'rails.png'), 'image/png', :binary) }
      download_times { rand 1_000 }
    end
end
类别:ruby & rails | Tags: , , , , , , , , | 0 条评论, 2744 次阅读
Jun
6
2011
这个 rake 主要用来在rails中自动生成 config/locales/zh-CN.model.yml ,建好model后执行一下,主要为了提高工作效率用,写的比较简陋,呵呵,凑合着用哈先

#encoding: utf-8
#
# by: vkill vkill.net@gmail.com
# updated_at: 2011.6.6
# first, please install psych gem, YAML dump support Chinese
#
# usage:
#   write it to Rails.root.join("lib/tasks/model_i18n_column.rake")
#   >rake model:i18n_column
#
require 'find'
require 'fileutils'
require 'tmpdir'

namespace :model do
  desc 'this is auto generate i18n.zh-CN.activerecord'
  task :i18n_column => :environment do

    t = {
      "id" => '序号',
      "type" => '类型',
      "name" => '名称',
      "state" => '状态',
      "title" => '标题',
      "content" => '正文',
      "created_at" => '创建时间',
      "updated_at" => '更新时间',
      "user_id" => '用户id'
    }
    i18n_new = {
      "zh-CN" => {
        "activemodel" => {
          "models" => {},
          "attributes" => {}
        },
        "activerecord" => {
          "models" => {},
          "attributes" => {}
        }
      }
    }
    i18n_file = Rails.root.join("config/locales/zh-CN.model.yml").to_s
    i18n_tmp = File.join(Dir.tmpdir, File.basename(i18n_file) + "_" + Time.now.strftime('%Y%m%d%H%M%S'))
    i18n = YAML.load_file(i18n_file) || i18n_new
    
    Find.find(Rails.root.join("app/models").to_s) do |path|
      if FileTest.directory?(path)
        if File.basename(path)[0] == ?.
          Find.prune
        else
          next
        end
      else
        require path
      end
    end

    ObjectSpace.each_object(Class) do |k|
      if k.ancestors.include?(ActiveRecord::Base)
        if k.name != "ActiveRecord::Base" and !k.abstract_class?
          if k.table_exists?
            if k.column_names.include?('type') and k.subclasses.size > 0
              next
            end
            #puts k.name
            model = k.name.underscore
            i18n_new["zh-CN"]["activerecord"]["models"][model] = i18n["zh-CN"]["activerecord"]["models"][model] || model
            i18n_new["zh-CN"]["activerecord"]["attributes"][model] = i18n["zh-CN"]["activerecord"]["attributes"][model] || {}
            k.column_names.each do |column|
              if !i18n_new["zh-CN"]["activerecord"]["attributes"][model][column]
                i18n_new["zh-CN"]["activerecord"]["attributes"][model][column] = t[column.to_s] || column.to_s
              end
            end
            if enums = i18n["zh-CN"]["activerecord"]["attributes"][model]["enums"]
              i18n_new["zh-CN"]["activerecord"]["attributes"][model]["enums"] =  enums
            end
          end
        end
      end
    end

    FileUtils.cp(i18n_file, i18n_tmp)

    require 'psych'
    require 'yaml'
    YAML::ENGINE.yamler= 'psych'
    File.open(i18n_file, "wb") do |f|
      f.write YAML.dump(i18n_new)
    end
    YAML::ENGINE.yamler= 'syck'

    puts "updated #{i18n_file}, old file backup to #{i18n_tmp}"
  end
end



2011.12.1 更新:
有个更好的方法,参见 https://github.com/vkill/i18n_attributes 这个gem
类别:ruby & rails | Tags: , , , , , , | 0 条评论, 2455 次阅读
Jun
6
2011
下面这个例子是 人员表和任务表,人员表和任务表是一对多的,但是这里有 分配任务的人 和 接受任务的人,所以这里就要用到 一对多 多外键
下面是 models.py 的代码及例子

class Person(models.Model):
    name = models.CharField(max_length=50)

class Task(models.Model):
    assign = models.ForeignKey(Person,related_name='assign')
    accept = models.ForeignKey(Person,related_name='accept')


#use
>>> Person.objects.create(name='a')
<Person: Person object>
>>> Person.objects.create(name='b')
<Person: Person object>
>>> Person.objects.create(name='c')
<Person: Person object>
>>> Person.objects.create(name='d')
<Person: Person object>
>>> Task.objects.create(assign_id=1,accept_id=2)
<Task: Task object>
>>> Task.objects.create(assign_id=1,accept_id=3)
<Task: Task object>
>>> Task.objects.create(assign_id=1,accept_id=4)
<Task: Task object>
>>> Task.objects.create(assign_id=2,accept_id=3)
<Task: Task object>
>>> Task.objects.create(assign_id=2,accept_id=4)
<Task: Task object>

>>> Person.objects.get(name='b').assign.all()
[<Task: Task object>, <Task: Task object>]
>>> Person.objects.get(name='b').accept.all()
[<Task: Task object>]
>>> Task.objects.get(pk=1).assign.name
u'a'
>>> Task.objects.get(pk=1).accept.name
u'b'
类别:python & django | Tags: , , , , | 0 条评论, 2840 次阅读
May
30
2011
这里不是说的是 profile,关于 profile 的看官方
网上有继承 User 的那个更不可用
django 写的太死,扩展下还是很麻烦
还有,下面的这个会在 django 库的 contrib\auth 目录下创建 migrations 目录,如果你觉得这个影响你别的项目的话,那就在这个项目目录下新建 django  目录,把 django 库下的文件全部复制过来,目录结构如 项目目录/django/bin 这样
------------------------------------------------------
后记:
south 的 auth migrations 目录可以定义的,方法来自于 django-primate 这个app

#注意,这里你要在项目目录下建个 users 目录
SOUTH_MIGRATION_MODULES = {
    'auth': 'users.migrations',
}


还有,更好的扩展 User model 使用 django-primate 这个库要好很多,参见 https://github.com/aino/django-primate
------------------------------------------------------


开工

F:\hyp\test>django-admin.py startproject my_django
F:\hyp\test>cd my_django
F:\hyp\test\my_django>manage.py startapp my_app


编辑 settings.py,INSTALLED_APPS 加入 my_app 和 south ,如下
Quotation

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',
    'my_app',
    'south'
)


DATABASES 配置好引擎并建好数据库,如这里我们配置成sqlite3
Quotation

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'test.db',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # 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.
    }
}


my_app/models.py 中加入,添加一个字段,添加一个实例方法,一个类方法
关于添加字段参见 http://djangosnippets.org/snippets/2132/

from django.db import models
from django.contrib.auth.models import User

some_field = models.CharField(max_length=32)
some_field.contribute_to_class(User, 'some_field')

def before_save(self):
    self.username = 'test'
User.before_save = before_save

@classmethod
def test(cls):
    print cls.__name__
User.test = test


创建 auth 的 migration,这样在 syncdb 的时候就会跳过 auth 这个app

F:\hyp\test\my_django>manage.py schemamigration auth --initial
Creating migrations directory at 'F:\hyp\language\Python27\lib\site-packages\django\contrib\auth\migrations'...
Creating __init__.py in 'F:\hyp\language\Python27\lib\site-packages\django\contrib\auth\migrations'...
+ Added model auth.Permission
+ Added unique constraint for ['content_type', 'codename'] on auth.Permission
+ Added model auth.Group
+ Added M2M table for permissions on auth.Group
+ Added model auth.User
+ Added M2M table for groups on auth.User
+ Added M2M table for user_permissions on auth.User
+ Added model auth.Message
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate auth


创建 my_app 的 migration

F:\hyp\test\my_django>manage.py schemamigration my_app --initial
Creating migrations directory at 'F:\hyp\test\my_django\my_app\migrations'...
Creating __init__.py in 'F:\hyp\test\my_django\my_app\migrations'...
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate my_app


执行 manage.py syncdb --all 创建表

F:\hyp\test\my_django>manage.py syncdb --all
Syncing...
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table south_migrationhistory

You just installed Django's auth system, which means you don't have any superuse
rs defined.
Would you like to create one now? (yes/no): no
Installing custom SQL ...
Installing indexes ...
No fixtures found.

Synced:
> django.contrib.auth
> django.contrib.contenttypes
> django.contrib.sessions
> django.contrib.sites
> django.contrib.messages
> django.contrib.staticfiles
> my_app
> south

Not synced (use migrations):
-
(use ./manage.py migrate to migrate these)


好了,基本上搞定了,下面我们来测试一下

F:\hyp\test\my_django>manage.py shell
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from my_app.models import *
>>> u = User()
>>> u.username
''
>>> u.before_save()
>>> u.username
'test'
>>> u.some_field
''
>>> User.test()
User


类别:python & django | Tags: , , , , , , , , | 1 条评论, 3486 次阅读
May
26
2011
官方文档:http://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield

默认的是显示 Model().__unicode__() 里的内容,下面几个位置都可以改,在任一一个地方改都可以
方法1:

class BookForm(ModelFormBase):
    def __init__(self, *args, **kwargs):
        super(self.__class__, self).__init__(*args, **kwargs)
        self.fields['person'].queryset = Person.objects.all()
        self.fields['person'].label_from_instance = lambda obj: "%s" % (obj.name)
    class Meta:
        model = Book
    mytest = forms.CharField(max_length=5)


方法2:

from django.forms.models import ModelChoiceField
class PersonModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return "%s" % obj.name
class BookForm(ModelFormBase):
    class Meta:
        model = Book
    mytest = forms.CharField(max_length=5)
    person = PersonModelChoiceField(queryset = Person.objects.all())



方法3:

class Person(ModelPerson, MPerson):
    def __unicode__(self):
        return "%s" % self.name


方法4:view中动态的更改

def create_book(request):
    form = BookForm()
    form.fields['category'].queryset = request.user.categories.all()
    #form.base_fields['category'].queryset = request.user.categories.all()


ok了,具体的用哪个这个看需求,哈哈
类别:python & django | Tags: , , , , , | 0 条评论, 2708 次阅读
May
19
2011
当我们在 类实例方法/类方法 中使用装饰器 cache_page 的时候,如下面这样

class PersonView(ViewBase):
    @cache_page(60 * 15)
    def index(self, request, *args, **kwargs):
        persons = Person.objects.select_related()
        return list_detail.object_list(
            request,
            queryset = persons,
            template_name = "person/index.html",
            paginate_by = 3,
            extra_context = {'string':'aaa'}
        )


此时就会提示下面这个错误
Quotation

ViewClass instance has no attribute 'method'


发生在 Python27\lib\site-packages\django\middleware\cache.py in process_request, line 138
看了下位置意思是 request.method 这个错了

之前想过,django自带的那些装饰器都是针对 函数 的,而类实例方法多了个 self 参数,自然用django自带的那些会出错的,至少从理论上来说是这样
google 了,搜索到这篇文章
http://www.toddreed.name/content/django-view-class/
很巧妙的给django自带的装饰器外再套一层装饰器使用,这个方法很不错,哈哈

新定义的装饰器

def on_method(function_decorator):
    def decorate_method(unbound_method):
        def method_proxy(self, *args, **kwargs):
            def f(*a, **kw):
                return unbound_method(self, *a, **kw)
            return function_decorator(f)(*args, **kwargs)
        return method_proxy
    return decorate_method


类实例方法中使用django自带装饰器

class PersonView(ViewBase):
    @on_method(cache_page(60 * 15))
    def index(self, request, *args, **kwargs):
        persons = Person.objects.select_related()
        return list_detail.object_list(
            request,
            queryset = persons,
            template_name = "person/index.html",
            paginate_by = 3,
            extra_context = {'string':'aaa'}
        )


这样就好了,继续使用类实例方法做view中,哈哈
类别:python & django | Tags: , , , , , | 0 条评论, 2595 次阅读
May
18
2011
Pages: 3/34 First page Previous page 1 2 3 4 5 6 7 8 9 10 Next page Final page [ View by Articles | List ]