1. 前端

1.1 html

<div style="text-align: center;border: 1px solid olivedrab;width: 520px;margin: 0 auto">
    <form id="itemForm">
        {% csrf_token %}
        {% for field in form %}
            <div class="form-group">
                <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                {{ field }}
                <span style="color: red;">{{ field.errors.0 }}</span>
            </div>
        {% endfor %}
    </form>
    <a class="btn btn-success btn-xs" id="btnAuctionItem">
        <span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span> 保 存
    </a>
</div>

1.2 js

<script>
    let ITEM_ADD = "{% url 'auction_item_add' pk=auction_object.id %}"
    $(function () {
        addAuctionItem();
    });

    // 基本数据提交
    function addAuctionItem() {

        $("#btnAuctionItem").click(function () {
            // 自动把数据,以合适的方式进行添加到FormData里面,
            // 注意1:radio,checkbox,如果未选中,不会提交到后台
            // 注意2:csrf_token也会自动提交到后台,免除了认证
            var AuctionItemData = new FormData($('#itemForm')[0]);
            $.ajax({
                url: ITEM_ADD,
                type: "POST",
                data: AuctionItemData,
                dataType: "JSON",     // 对于返回来的数据,进行反序列化,ajax本身自带反序列化,但是加上他保险
                contentType: false,  // 让浏览器不要对你的数据进行任何的操作
                processData: false, // 不要使用任何编码格式 对象formdata自带编码格式并且django能够识别该对象
                success: function (res) {
                    if (res.status === 201) {
                        window.location.href = location.href
                    } else {

                    }
                }
            })
        })
    }
</script>

2. 后端

2.1 model

class AuctionItem(models.Model):
    """
    拍卖商品
    """
    auction = models.ForeignKey(verbose_name='拍卖专场', to='Auction', on_delete=models.DO_NOTHING)
    uid = models.CharField(verbose_name='图录号', max_length=225)

    status_choices = (
        (1, '待拍卖'),
        (2, '预展中'),
        (3, '拍卖中'),
        (4, '成交'),
        (5, '流拍'),
    )
    status = models.PositiveSmallIntegerField(verbose_name='状态', choices=status_choices, default=1)
    title = models.CharField(verbose_name='拍品名称', max_length=32)
    cover = models.FileField(verbose_name='拍品封面', max_length=225)

    start_price = models.PositiveIntegerField(verbose_name='起拍价')
    deal_price = models.PositiveIntegerField(verbose_name='成交价', null=True, blank=True)

    reserve_price = models.PositiveIntegerField(verbose_name='参考底价')
    highest_price = models.PositiveIntegerField(verbose_name='参考高价')

    video = models.CharField(verbose_name='预览视频', max_length=128, null=True, blank=True)
    # 单品保证金
    deposit = models.PositiveIntegerField(verbose_name='单品保证金', default=100)
    unit = models.PositiveIntegerField(verbose_name='加价幅度', default=100)

    bid_count = models.PositiveIntegerField(verbose_name='出价次数', default=0)
    look_count = models.PositiveIntegerField(verbose_name='围观次数', default=0)

    class Meta:
        verbose_name_plural = '拍品'

    def __str__(self):
        return self.title

2.2 url

 # 添加专场拍卖品
    re_path(r'auction/item/add/(?P<pk>\d+)/$', views.auction_item_add_view, name='auction_item_add'),

2.3 view

import datetime
from django.views.decorators.csrf import csrf_exempt
import uuid

def auction_item_add_view(request, pk):
    """添加拍品"""
    auction_object = models.Auction.objects.filter(id=pk).first()
    if request.method == 'GET':
        form = AuctionItemAdd()
        return render(request, 'auction_item_add.html', context={'form': form, 'auction_object': auction_object})
    form = AuctionItemAdd(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 保存之前,需要把用户不用传的数据,填上
        form.instance.auction = auction_object
        form.instance.uid = datetime.datetime.now().strftime('%Y%m%d%H%M%S%f')
        form.save()
        return JsonResponse({'status': 201})
    return JsonResponse({'status': 400})

2.4 form

import uuid
from django import forms
from utils.centent.cos import upload_img

from api import models
# 编辑(未改变)
from django.db.models.fields.files import FieldFile
# 上传
from django.core.files.uploadedfile import InMemoryUploadedFile


class BootStrapForm:
    except_bootstrap_styles = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            if name in self.except_bootstrap_styles:
                continue
            old_class = field.widget.attrs.get('class', "")
            field.widget.attrs['class'] = '{} form-control'.format(old_class)
            field.widget.attrs['placeholder'] = f'请输入{field.label}'


class AuctionItemAdd(BootStrapForm, forms.ModelForm):
    """拍品添加"""
    except_bootstrap_styles = ['cover']

    class Meta:
        model = models.AuctionItem  # 对应的Model中的类
        fields = ['title', 'cover', 'start_price', 'reserve_price', 'highest_price', 'deposit', 'unit']

    def clean(self):
        cover_file_object = self.cleaned_data.get('cover')
        # 判断是没有传图片 or 编辑(为修改)
        if not cover_file_object or isinstance(cover_file_object, FieldFile):
            return self.cleaned_data
        # 获取上传的文件名称,
        # 进行拼接,
        ext = cover_file_object.name.rsplit('.', maxsplit=1)[-1]
        file_name = "{0}.{1}".format(str(uuid.uuid4()), ext)
        # 调用上传文件,上传到cos
        result_url = upload_img(Bucket='19803630852-1645846574-1305448189', region='ap-chengdu', Body=cover_file_object,
                                Key=file_name)
        # 给cover字段添加路由
        self.cleaned_data['cover'] = result_url
        return self.cleaned_data

更多推荐

ajax提交文件对象----form组件+form表单+FormData对象