Contents:

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

效果图