django 上传文件

最近在做一个管理问句的平台,需要上传一些问句,就想用django的upload模块来做,遇到一些问题,记录一下。

就拿测试用的demo来做例子吧:

第一:因为django默认的文件是存储在media下面的,所以需要现在settings.py里面把media定义一下

CUR_DIR=os.path.dirname(__file__)
MEDIA_ROOT = os.path.join(CUR_DIR,'media/')

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/media/'

然后就是写forms和models.

#forms.py
from django import forms
from django.forms.widgets import *
from blogapp.validate import * 

class UpLoadPicForm(forms.Form):
    title=forms.CharField(max_length=100)
    pic=forms.FileField(validators=[validate_fize])

#models.py
class Pic(models.Model):
    #这里的保存目录就是/mdeia.documents/%Y
    pic=models.FileField(upload_to='documents/%Y')

class PicGallery(models.Model):
    picid=models.IntegerField(primary_key=True)
    pic=models.ManyToManyField(Pic)

OK,都定义好了,然后就是把views.py补上

def uploadPic(request):
    if request.method=="POST":
        form=UpLoadPicForm(request.POST,request.FILES)
        if form.is_valid():
            storePic(request.FILES)
            return HttpResponse("success")
    else:
        form=UpLoadPicForm()
    return render_to_response('upload.html',{"form":form},context_instance=RequestContext(request))

def storePic(fileobj):
    newdoc=Pic(pic=fileobj["pic"])
    newdoc.save()

然后是超简单的模板页面

<form enctype="multipart/form-data" method='post',action='/upload/'>
    {% csrf_token %}
    <p>{{ form.non_field_errors }}</p>
    <p>
    {{form.title.errors}}
    {{form.title.label_tag}}
    {{form.title}}
    </p>
    <p>
    {{ form.pic.errors }} 
    {{form.pic}}
{{ form.pic.errors }} 
    {{form.pic}}

    </p>
    <input type="submit",value="提交">
</form>

这样就实现了上传文件,过程很简单,然后着重说下我遇到过的问题.

第一:UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.

这个错误发生的原因在与

return render_to_response('upload.html',{"form":form},context_instance=RequestContext(request))

这个里面忘记添加了context_instance=RequestContext(request),一开始不知道为什么,后来才发现django的说明文档里面有这么一句话:

If you are using generic views or contrib apps, you are covered already, since these apps use RequestContext throughout

而我这里的upload不属于contrib apps也不属于通用视图,所以需要手动添加RequestContext

第二:instance is on database "None", value is on database "default"

这个问题很粗心,发生的原因是这样的,我本来是想一个图库,就是PicGallery

于是我的storePic方法就变成了:

def storePic(fileobj):
    newdoc=Pic(pic=filobj["pic"])
    newdoc.save()
    picgallery=PicGallery(1)
    picgallery.pic.add(newdoc)
    picgallery.save()

问题就在于我这里的picgallery一开始就是没这个query结果的,所以当我add的时候就出错了,应该先picgallery.save(),然后再是add()

第三:object has no attribute _state

这个也是很粗心,我本来是想再扩展下Pic这个模型的,然后就变成

class Pic(models.Model):
    pic=models.FileField(upload_to='documents/%Y'def __init__(self,*args,**kargs):
        '''
问题就在于我这里init没有任何操作,也没有去super,所以出错了,
        '''
          pass        

第四:DjangoUnicodeDecodeError: 'utf8' codec can't decode byte 0x89 in position 77: invalid start byte.

这个问题是我想尝试下多个文件上传的时候出现的。

def storePic(fileobj):
    print fileobj["pic"]
  
''' 本来是这样,但是出现了错误 for pic in fileobj["pic"]: 后来通过getlist来获取上传的多个文件对象,才可以了 ''' for pic in fileobj.getlist('pic'): newdoc=Pic(pic=pic) newdoc.save()

PS:另外是自己学的一些,因为以前如果想自定义判断一个form数据是否有效的函数,都是在外部定义,比如在forms.is_valid()之后再调用自己的验证函数,今天也刚好尝试一下在form里面添加validate

比如我要判断文件大小是不是大于8M:

#validate.py
from django.core.exceptions import ValidationError
def validate_fize(value):
    if value.size>8*1024:
        raise ValidationError(u'sorry ,the size is too large',code='_invalid') 

然后调用就是在定义forms的时候

class UpLoadPicForm(forms.Form):
    title=forms.CharField(max_length=100)
    pic=forms.FileField(validators=[validate_fize])

即可,具体运行结果就是:

另外记录一个判断图片类型的函数:
def get_pic_type(picobj):
    filetype=None
    data=picobj.read(10).encode("hex")
    if data.startwith("ffd8ffe0"):
        filetype="jpg"
    elif data.startwith("474946"):
        filetype="gif"
    elif data.startwith("424d"):
        filetype="bmp"
    elif data.startswith('89504e470d0a1a0a'):
        filetype="png"
    return filetype

 

 

 

转载于:https://www.cnblogs.com/xiamuyouren/p/3275796.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值