django自定义field,支持多种形式下选择图片

9 篇文章 0 订阅
2 篇文章 0 订阅

前言

为什么要开发这个功能?因为当时我在利用django搭建好自己的博客时,通过后台来发表文章时,需要上传文章封面,我的文章封面是单独定义一个字段也就是ImageField来上传封面,但是有的时候我可能好几篇文章都是同一个封面,这个时候不可能在上传一遍之前已经上传过了的封面了,有点浪费服务器空间,所以当时就想着要自定义个field来实现上面功能。

废话不多说先看看实现后的效果

新建django应用,

执行下面命令,新建一个应用名为uploader

startapp uploader

目录结构如下
│ apps.py
│ fields.py
│ widgets.py
init.py

├─migrations
│ │ init.py

├─static
│ └─uploader
│ │ jquery.fileupload.js
│ │ uploader.css
│ │ uploader.js
│ │
│ └─images
│ add.png
│ bg.png
│ dialog-title-bg.png
│ image.png
│ success.gif
│ success.png

├─templates
│ image.html

新建fields.py

from django import forms
from django.db import models

class UploaderTextField(models.CharField):
    def __init__(self,*args,**kwargs):
        super(UploaderTextField, self).__init__(*args, **kwargs)

    def formfield(self, **kwargs):
        defaults = {
            'form_class': self._get_form_class(),
        }
        defaults.update(kwargs)
        return super(UploaderTextField,self).formfield(**defaults)


    @staticmethod
    def _get_form_class():
        return UploaderFormField

class UploaderFormField(forms.CharField):

    def __init__( self,*args,**kwargs):
        from .widgets import UploaderWidget
        kwargs.update({"widget":UploaderWidget()})
        super(UploaderFormField, self).__init__(*args, **kwargs)

新建widgets.py

from django import forms
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe


class UploaderWidget(forms.TextInput):

    def __init__(self,*args, **kwargs):
        super(UploaderWidget, self).__init__(*args, **kwargs)

    def render(self,name,value,attrs=None, renderer=None):
        value='' if value is None else value
        final_attrs = self.build_attrs(self.attrs, attrs, name=name)
        context = {
            'value':value,
            'id': final_attrs['id'],
            'name':name,
            'label':self.attrs.get('label', name)
        }
        return mark_safe(render_to_string('image.html',context))

    def build_attrs(self, base_attrs, extra_attrs=None, **kwargs):
        attrs = dict(base_attrs, **kwargs)
        if extra_attrs:
            attrs.update(extra_attrs)
        return attrs

    class Media:
        js = ("uploader/image.js","uploader/jquery.fileupload.js",)
        css = {"all": ("uploader/image.css",)}

新建image.html

{% load  static %}
<a href="{{ value }}" target="_blank" title="{{ label }}">
    <img src="{{ value }}" class="field_img">
</a><br>更改:
<input type="file" data-toggle="modal"  data-target="#uploaderModal">
<input type="hidden" name="{{ name }}" value="{{ value }}" id="{{ id }}">
<!-- 模态框(Modal) -->
<div class="modal fade" id="uploaderModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            <h4 class="modal-title" id="myModalLabel">图片上传</h4>
        </div>
        <div class="modal-body uploader">
        <div class="wrapper">
            <div id="tabhead" class="tabhead">
                    <span class="tab focus" data-content-id="remote">插入图片</span>
                    <span class="tab" data-content-id="upload">本地上传</span>
                    <span class="tab" data-content-id="online">在线管理</span>
                    <span class="tab" data-content-id="search">图片搜索</span>
            </div>
            <div id="tabbody" class="tabbody">

        <div id="remote" class="panel focus">
            <label for="url">地 址:</label>
            <input class="text" id="url" type="text">
            <div id="preview"></div>
        </div>

                <!-- 上传图片 -->
                <div id="upload" class="panel">
                    <div class="file-button" id="upload_image">
                        <input type="file" name="upfile" id="fileupload">
                    </div>
                </div>

                <!-- 在线图片 -->
                <div id="online" class="panel">
                    <div id="imageList">图片加载中……</div>
                </div>

                <!-- 搜索图片 -->
                <div id="search" class="panel">
                    <div class="searchBar">
                        <input id="searchTxt" class="searchTxt text" type="text">
                        <select id="searchType" class="searchType" title="图片类型">
                            <option value=".jpg">jpg</option>
                            <option value=".png">png</option>
                        </select>
                        <input id="searchReset" type="button" value="清空搜索">
                        <input id="searchBtn" type="button" value="百度一下">
                    </div>
                    <div id="searchList" class="searchList"><ul id="searchListUl"></ul></div>
            </div>

            </div>

        </div>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">关闭
            </button>
            <button type="button" class="btn btn-primary" id="ok">确认</button>
        </div>
    </div><!-- /.modal-content -->
</div><!-- /.modal -->
</div>
<script>
 $(function () {
     $("#{{ id }}").uploader({"uploadUrl":"图片上传接口","deleteUrl":"图片删除接口","searchUrl":"图片搜索接口","queryUrl":"图片查询接口"});
 })
</script>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值