Django图片系统
782 浏览 5 years, 10 months
1.1 前台上传 – FormView
版权声明: 转载请注明出处 http://www.codingsoho.com/前台上传 – FormView
前面例子中我们简单的创建一个model只包含image,并完成了相关的创建和更新等工作。
这一节我们试着给一个用户去更新头像。跟前面不同的是,更新好的图像要更新到另外一个表单里去。
我们用一段最简单的代码去添加图片
<form action="" enctype="multipart/form-data" method="post">{% csrf_token %}
<input type="file" name="image" id="id_image">
<br>
<input type="submit" value="Update" />
</form>
实例里,我是把这段代码嵌在用户详情视图里的,上传完成之后,图片信息要更新到用户详情里。
添加视图处理类和表单
该表单用于上传图片
class UserUpdateImageForm(forms.ModelForm):
class Meta:
model = User
fields = [
'image'
]
详情视图本身是不带表单功能的,所以需要添加FormMixin
class UserProfileDetailUpdateImageView(FormMixin, DetailView):
model = UserModel
template_name = 'auth/user_detail.html'
form_class = UserUpdateImageForm # (1)
def get_object(self, *args, **kwargs):
try:
return UserModel().objects.get(id=self.kwargs.get('pk'))
return UserModel._default_manager.get_by_natural_key(self.kwargs.get('pk'))
except:
return None
def get_context_data(self, *args, **kwargs):
context = super(UserProfileDetailUpdateImageView, self).get_context_data(*args, **kwargs)
context["form"] = self.form_class(instance = self.get_object()) # (2)
return context
def get_success_url(self):
return reverse("userprofile_detail", kwargs=self.kwargs)
def post(self, request, *args, **kwargs):
form = self.get_form() # (3)
if form.is_valid():
usermodel = UserModel().objects.get(id=self.kwargs.get("pk"))
if 'image' in form.cleaned_data:
usermodel.image = form.cleaned_data['image'] # (4)
usermodel.save()
return self.form_valid(form)
else:
return self.form_invalid(form)
简单的介绍一下上面的内容
(1) 定义form_class
form_class = UserUpdateImageForm
定义form_class,后面通过通过get_form_class()或get_form()获取form相关的内容。本例中,我们通过UserUpdateImageForm
来完成图片上传。
(2) form_class 赋值
context["form"] = self.form_class(instance = self.get_object())
Profile是DetailView,本来是不带form的,如果要支持image功能,必须支持form,所以我们添加了基类FormMixin。
在form_class指定form类型,并且在context里面将form数据传递给templates, 并根据object内容对form进行了初始化。
如果是CreateView,它的基类本身带有FormMixin,所以form_class是默认已定义的,不需要额外添加FormMixin。不过,如果要添加额外的form,同样需要在context里面传递
更新form内容除了通过instance,也可以直接更新queryset,例如form.fields['categories'].queryset = Category.objects.all()
(3) 获取form对象
form = self.get_form()
get_form()会根据定义的form_class获取form类,并根据传递的参数初始化或实例化
在该例子中,我们可以用该句子代替图片信息获取内容form = self.form_class(request.POST, request.FILES)
具体FormMixin可参考class FormMixin(six.with_metaclass(FormMixinBase, ContextMixin)):
class FormMixin(six.with_metaclass(FormMixinBase, ContextMixin)):
def get_form_class(self):
"""
Returns the form class to use in this view
"""
return self.form_class
def get_form(self, form_class=None):
"""
Returns an instance of the form to be used in this view.
"""
if form_class is None:
form_class = self.get_form_class()
return form_class(**self.get_form_kwargs())
def get_form_kwargs(self):
"""
Returns the keyword arguments for instantiating the form.
"""
kwargs = {
'initial': self.get_initial(),
'prefix': self.get_prefix(),
}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
(4) 读取模板内容
usermodel.image = form.cleaned_data['image']
该语句获取image对象。也可以通过下面原生文件处理的方式
filename=request.FILES['image']
from PIL import Image
if filename:
img=Image.open(filename)
img.save(os.path.join(settings.MEDIA_ROOT, photoname))
usermodel.image = photoname
效果图