Archive

Posts Tagged ‘Django’

Django-1.0-file-upload

September 15th, 2008 BianJiang No comments

原因

想通过 Django admin 做个简单的上传文件管理,遇到个问题。files = models.FileField(upload_to=(’files’)) 默认是把所有的文件都保存在同一个目录 files 下面,我想通过types来判断不同的类型保存到不同目录下,像这样的结构: files/types/filename.

表结构:

class Car(models.Model):
    name = models.CharField(max_length=255)
    types = models.CharField(max_length=255)
    files = models.FileField(upload_to=('files'))

分析问题

如果upload_to可以解决问题最好不过,如果不行就只能在数据库保存是进行干扰,再不行就放弃admin自己做管理页面。

解决问题

django 1.0 已经支持
upload_to参数使用函数,该函数约定有两个参数,一个是对象实例,一个是文件名,返回一个文件名。

def upload_to(instance,filename):
return ‘files/%s/%s’ % (instance.types,filename)

可以参考原文:

FileField.upload_to

A local filesystem path that will be appended to your MEDIA_ROOT setting to determine the value of the url attribute.

This path may contain strftime formatting, which will be replaced by the date/time of the file upload (so that uploaded files don’t fill up the given directory).

Changed in Django 1.0.

This may also be a callable, such as a function, which will be called to obtain the upload path, including the filename. This callable must be able to accept two arguments, and return a Unix-style path (with forward slashes) to be passed along to the storage system. The two arguments that will be passed are:

instance

An instance of the model where the FileField is defined. More specifically, this is the particular instance where the current file is being attached.

In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field.

filename

The filename that was originally given to the file. This may or may not be taken into account when determining the final destination path.

Also has one optional argument.

原文链接: http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.FileField.upload_to

最终代码

from django.db import models
from django.forms import ModelForm
from django.contrib import admin

def files_path(instance, filename):
    return 'files/%s/%s' % (instance.types, filename)

class Car(models.Model):
    name = models.CharField(max_length=255)
    types = models.CharField(max_length=255)
    files = models.FileField(upload_to=files_path)

    def __unicode__(self):
        return u'%s' % self.name

class CarAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'types', 'files', 'file_url', 'file_path')

    def file_url(self, obj):
        return obj.files.url
    file_url.short_description = 'files url'

    def file_path(self, obj):
        return obj.files.path
    file_path.short_description = 'files path'

admin.site.register(Car, CarAdmin)

感谢

非常感谢 Python-cn 用户组兄弟们的耐心解答。讨论地址: http://groups.google.com/group/python-cn/browse_thread/thread/0e678f1a6ce07d49#

Categories: SiteLog Tags:

Django From 0.96 update to 1.0 logging

August 8th, 2008 BianJiang No comments

Django升级到1.0时,发现原来写的东西就运行不起来, 去官方查了一下原来Admin和newform的API改动了, 还好这次不是大面积的改动.

更新简单记录一下.

本文主要参考: http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges

admin url

URLconfs:

# OLD:
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls')),
)

# NEW:
from django.conf.urls.defaults import *
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root),
)

slugfield prepopulate_from

code:

# OLD
class Catalog(models.Model):
    catalog_name = models.CharField(max_length=100)
    slug = models.SlugField(prepopulate_from=("catalog_name",))

    class Admin:
        list_display = ('id', 'catalog_name', 'post_count')

# NEW
class Catalog(models.Model):
    catalog_name = models.CharField(max_length=100)
    slug = models.SlugField(db_index=True)

from django.contrib import admin
class CatalogAdmin(admin.ModelAdmin):
    list_display = ('id', 'catalog_name', 'post_count')
    prepopulated_fields = {"slug": ("catalog_name",)}

admin.site.register(Catalog, CatalogAdmin)

filter_interface

code:

# OLD
tags = models.ManyToManyField(Tag, filter_interface=models.HORIZONTAL, related_name='entries')
slug = models.SlugField(
        unique_for_date='pub_date',
        prepopulate_from=('title',),
        help_text='Automatically built from the title.'
        )
# NEW
tags = models.ManyToManyField(Tag, related_name='entries')
slug = models.SlugField(db_index=True)

class EntryAdmin(admin.ModelAdmin):
    date_hierarchy = 'pub_date'
    prepopulated_fields = {"slug": ("title",)}
    filter_horizontal = ('tags',)
admin.site.register(Entry, EntryAdmin)

Renamed ‘fields’ to ‘fieldsets’

code:

# OLD
class Admin:
    fields = [(None, {'fields': ('title', 'catalog', 'public', 'slug', 'input_format', 'body', 'tags', 'comment_count', 'read_count')})]

# NEW
class EntryAdmin(admin.ModelAdmin):
    fieldsets = [(None, {'fields': ('title', 'catalog', 'public', 'slug', 'input_format', 'body', 'tags', 'comment_count', 'read_count')})]
admin.site.register(Entry, EntryAdmin)

更详细的变更请参考Blog-app. http://code.google.com/p/blog-app/source/detail?r=67

参考:

–EOF–

Categories: SiteLog Tags: ,

django REMOTE_ADDR on nginx

June 14th, 2008 BianJiang No comments

1   现象

  1. Django 取得客户端IP,在本地测试良好,但是放到服务器上报错, 报错信息:

    Request Method:     POST
    Request URL:        http://www.b0rder.com/blog/8/comment/
    Exception Type:     KeyError
    Exception Value:    'REMOTE_ADDR'

错误代码:

remoteIP = request.META['REMOTE_ADDR']
  1. 服务器采用 nginx fastcgi 方式.

1.1   分析原因

  1. 报错信息KeyError,说明服务器中没有 ‘REMOTE_ADDR’, 但是我在服务器中通过 Django 自带的服务器运行正常显示:

    python manage.py runserver 7000
  2. 原因可能是 nginx 配置的问题。Google了一圈发现没有把fastcgi转换过来:

    fastcgi_param REMOTE_ADDR $remote_addr;
    fastcgi_param SERVER_PROTOCOL $server_protocol;
    fastcgi_param SERVER_PORT $server_port;
    fastcgi_param SERVER_NAME $server_name;

1.2   解决

  1. 可以通过 nginx 的 include 简单处理:

    include /etc/nginx/fcgi.conf

1.3   我的nginx配置文件

server {
    listen 80;
    server_name www.b0rder.com b0rder.com;
    location ^~ /static  {
        alias /home/border/project/blog-app/media/;
        }
    location ^~ /media  {
        alias /home/border/lib/django/django/contrib/admin/media/;
        }
    location ^~ /books  {
        alias /home/border/books/;
        autoindex on;
        }
    location / {
        fastcgi_pass 127.0.0.1:9999;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;
        fastcgi_pass_header Authorization;
        fastcgi_param REMOTE_ADDR $remote_addr;
        fastcgi_param SERVER_PROTOCOL $server_protocol;
        fastcgi_param SERVER_PORT $server_port;
        fastcgi_param SERVER_NAME $server_name;
        fastcgi_intercept_errors off;
        }
    access_log  /home/border/log/access.b0rder.log;
    error_log  /home/border/log/error.b0rder.log;
    }

1.4   感谢

  1. 感谢 Vingel (http://www.vingel.com/) 的友情支持。

–EOF–

Categories: Tech.Notes Tags: ,