需求描述:

做一个简单的注册页面,使得用户在注册页上传头像。

解决办法:

以前用java写这个的时候,在action上面需要用IO接受文件,然后生成一个文件名,再将文件相对路径保存到user表的img字段中。

而在django的model层上,有一个叫做ImageField的字段(还有FileField,两者几乎一样),看了文档中对于这个字段的描述,大致意思就是自动将文件保存在media的文件夹里面,然后产生的文件路径保存到一个var char的字段中。如果一个model有ImageField字段,则在其对应表里面就会有一个var char字段,正是用于保存路径的。

1.设置setting中的MEDIA_ROOT:

如果使用django的快捷方法,那么所有用户上传的文件应该都会被保存到MEDIA_ROOT定义的文件夹中去。注意这里需要绝对路径。我的设置是:

# in settings.py

HERE = os.path.dirname(os.path.abspath(__file__))

MEDIA_ROOT = os.path.join(HERE,'media').replace('\\','/')+'/'

这样就能将MEDIA_ROOT设置为项目目录下的media目录。注意最后的斜杠,如果不加最后的斜杠,那么在保存的时候会出现奇怪的错误。

2.设置model:

为了方便,自己建了一个User的Model:

# in myapp1/models.py

class User(models.Model):

name = models.CharField(max_length=30)

password = models.CharField(max_length=30)

GENDER_CHOICE = (

(u'M', u'Male'),

(u'F', u'Female'),

)

gender = models.CharField(max_length=2,choices = GENDER_CHOICE)

birthday = models.DateField(null=True)

img = models.ImageField(upload_to='photo',null=True,blank=True)

phoneNum = models.CharField(max_length=13,null=True,blank=True)

email = models.EmailField(null=True,blank=True)

hobbies = models.CharField(max_length=100,null=True,blank=True)

regTime = models.DateTimeField(null=True,blank=True)

bio = models.TextField(null = True,blank=True)

def __unicode__(self):

return self.name

这里要注意的地方是null=True之后,要也要加上blank=True。其中null=True是针对数据库的,而blank=True是针对validation的。如果blank=True没加,那么在下面做form的时候,省略字段的话验证不会通过。

这里面有一个img字段,是ImageField类型的,这个在快速制作上传图片的表单里起了至关重要的作用。里面有一句upload_to='xxxxx',是指文件保存在MEDIA_ROOT中的哪个子目录下。

3.设置forms from models:

django有一个form类,这个类抽象出了html的form。用在view里的话,就能在template里生成form的html。但是可以发现用户注册时,表单的字段和model的字段非常相似,所以可以通过model生成form类。

而model类里面并不是所有的内容都需要用户填写,比如regTime就不需要。这时候可以指定那些字段会成为form字段(使用fields=(xxxx)),或者可以指定哪些字段不会成为form字段(使用exclude=(xxx))。这里,我们似乎只有一个regTime不需要显示。

另外,我们的model里面password字段是CharField,django不会聪明到通过变量名的意思来生成form,所以默认生成出来的会是input type="text"的表单,我们需要通过一种方法修改掉它。综上所述,最后的form代码是这样的:

# in myapp1/models.py

from django.db import models

from django.forms import ModelForm

from django import forms

class UserForm(ModelForm):

class Meta:

model = User #通过上面的User Model生成表单

exclude =('regTime')#将regTime字段排除在外

widgets = {

'password':forms.PasswordInput(),#将password字段的input type设为password

}

这样就能生成一个简单的form了。forms from models和普通的form类有一个区别,就是它有save()方法,这个方法在view中将会被使用。

4.在view里调用form

这里,假设注册页面为/reg/。如果使用get方法,则浏览器中给出注册表单,如果用post方法,则将表单内容保存到数据库。

如果使用forms from models,则在view上面将会非常的简单:

#in myapp1/views.py

def reg(request):

if request.method == 'POST':#提交表单

form = models.UserForm(request.POST,request.FILES)#如果表单中要传文件、图片,则需要传两个参数

if form.is_valid():#这个is_valid通过model的配置定义,这里显现出blank=True的意义了

form.save()#这一句save,不但保存了各个字段,而且自动将上传的文件保存到指定目录,并且生成文件路径,保存到user表的img字段中了。

else:#显示表单

form = models.UserForm()

return render_to_response('reg_form.html', {'form': form})

5.template中的使用:

<body>

<form enctype="multipart/form-data" action="/reg/" method="post">

{{ form.as_p }}

<input type="submit" value="Submit" />

</form>

</body>

这里和普通form是一样的。当然也可以手动设置格式,详见文档。

最后再配置一下urlpattern,就能在这个表单上传图片了。

不足:

单单这样做注册表单有个不足之处,就是没有confirm password这个字段。不过我们可以在UserForm类中增加一个表单字段,最后结果会是:

class UserForm(ModelForm):

confirm_password = forms.CharField(widget=forms.PasswordInput())

class Meta:

model = User

exclude('regTime')

widgets = {

'password':forms.PasswordInput(),

}

不过这样一来,template中生成的表单,会把confirm_password字段放在最下面。所以得手动设定格式。另外,form.is_valid()也不会监测password和它是不是一样,需要在后面手动加逻辑。

上面的方法不一定是最好的,不过也提供了一些思路。另外,即便是不使用forms from models,也可以方便的使用ImageField保存图片:

碰到的问题:

和MEDIA_ROOT对应有一个MEDIA_URL。按照道理说,MEDIA_ROOT是一个public的文件夹,不需要通过urlpatterns映射就能直接访问里面的文件(至少django 1.3里面STATIC_ROOT加上STATIC_URL可以做到这点),但是我测试了好几次,都还是经过了url映射才可以。目前暂时不知道怎么解决。

注意:

通过阅读文档,对MEDIA_URL的问题有了进一步的了解:django不会自动开放这个目录作为静态文件目录。在开发阶段,要使用urlpatterns映射。
但是这样仅限于开发阶段(static files也一样),按照django官方的说法,用urlpatterns映射静态文件的方法是“效率非常低”,进入使用阶段后,需要将media_root和static_root发布到“真正的静态文件服务器”。这也是为什么django本身提供static文件扫描,却又提供了python manage.py collectstatic这个命令来汇集各个app的static文件到static_root文件夹。

使用django的ImageField和from制作上传图片页面的更多相关文章

  1. 利用Bootstrap框架制作查询页面的界面

    UI设计实战篇——利用Bootstrap框架制作查询页面的界面   Bootstrap框架是一个前端UI设计的框架,它提供了统一的UI界面,简化了设计界面UI的过程(缺点是定制了界面,调整的余地不是太 ...

  2. web基础,用html元素制作web页面

    用div,form制作登录页面,尽可能做得漂亮. 练习使用下拉列表选择框,无序列表,有序列表,定义列表. 观察常用网页的HTML元素,在实际的应用场景中,用已学的标签模仿制作. <!DOCTYP ...

  3. django之创建第11个项目-页面整合

    目的:将如下众多html页面整合到一个index.html页面中. 百度云盘:django之创建第11个项目-页面整合 用下面的方式实现: <!DOCTYPE html> <head ...

  4. jQuery - 制作非缘勿扰页面特效

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. stelller插件与background-attachment配合使用,制作滚动页面

    stelller插件与background-attachment:fixed配合使用,制作滚动页面

  6. 制作登录页面,点击键盘的 Enter 键或者单击“登录”按钮,验证用户输入的邮箱和密码是否正确

    查看本章节 查看作业目录 需求说明: 制作登录页面 点击键盘的 Enter 键或者单击"登录"按钮,验证用户输入的邮箱和密码是否正确 实现思路: 准备登录的静态页面 在页面中嵌入脚 ...

  7. Django中ImageField的使用

    http://blog.csdn.net/u013690521/article/details/38777213 from django.db import models from django.co ...

  8. Django内置form表单和ajax制作注册页面

    settings.py import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_D ...

  9. Jquer + Ajax 制作上传图片文件

    没什么 说的  直接 上代码 //选择图片并上传 function selectImg(node){ var f = node.value; var file = node.files[0]; if( ...

随机推荐

  1. 使用jquery的小记

    随便写点 1.给span这种标签赋值  不能用$("#id").val("abc"); 因为这种标签没有value属性 而应该用$("#id" ...

  2. scala学习笔记(1)

    下载和安装Scala 前往http://www.scala-lang.org/downloads下载Scala在各个平台的安装包,安装后即可在运行scala编译器和交互式命令行环境(interacti ...

  3. [c++基本语法]——构造函数初始化列表

    c++构造函数初始化成员变量列表: #pragma once class Node { public: int data; // 权值 Node *parent; // 父节点 Node *left; ...

  4. 通用窗口类 Inventory Pro 2.1.2 Demo1(上)

    插件功能 按照Demo1的实现,使用插件来实现一个装备窗口是很easy的,虽然效果还很原始但是也点到为止了,本篇涉及的功能用加粗标出,具体的功能如下: 1.实现了两个窗口,通过点击键盘I来,打开或者关 ...

  5. G面经prepare: X-Straight

    Define “X-Straight” as X cards with consecutive numbers (X >= 3). Determine if the deck can be fu ...

  6. 基于Qt实现的截图小程序

    在最近做的行人检测项目中,由于需要训练分类器,而分类器的训练又需要有一个一定长宽的样本.为了方便样本的采集,因此实现了这样的一个截图程序.该程序的主要功能是加载视频到程序中,程序可以对视频进行播放.暂 ...

  7. jvm内存设置

    JVM有很多个内存管理命令,总体而言,分为两类: 1.-X开头的管理命令:这些选项在JDK升级时不会通知修改: 2.-XX开头的管理命令:这些选项不够稳定,所以建议少用. JVM参数的含义: 参数名称 ...

  8. VCL 如何加载Gif图片和Png图片

    加上头文件#include <Vcl.Imaging.GIFImg.hpp> #include <Vcl.Imaging.pngimage.hpp> Image1->Pi ...

  9. Where does beauty come from?

    One more question, rational beauty should come from a dedicated brain and mind. Should there be more ...

  10. -Xloggc:log/gc.log 指定GC log的位置

    -Xloggc:log/gc.log指定GC log的位置,以文件输出帮助开发人员分析问题