Django图片上传与分页

配置

  1. 新建上传目录

    1
    2
    # 这个位置可自己定,一般放在根目录下新建一个media文件夹
    mkdir media
  2. 配置上传文件保存目录

    1
    2
    # 项目settings.py文件中新增配置项
    MEDIA_ROOT = os.path.join(BASH_DIR, 'media')

后台上传图片

  1. 设计模型类

    1
    2
    3
    4
    # 在对应应用下的models.py文件中注册图片管理
    class PIC_Upload(models.Model):
    # upload_to:表示图片上传的路径,该路径是相对于settings.py文件media_root配置
    pic = models.ImageField(upload_to='picture')
  2. 在项目的管理后台进行注册

    1
    2
    # 修改app对应的admin.py文件,注册图片的那张表
    admin.site.register(PIC_Upload)

    通过ImageField设置图片字段,它会自动的检测上传的内容是不是图片格式

  3. 【问题解决】当生成迁移文件的时候,可能会提示没有任何修改,然后导致数据库并不会生成对应的数据表,但是本质上我们确实已经做了修改,这个原因主要是因为数据库中【django_makemigrations表】已经生成了对应的表记录,因此引出以下解决方案:

    • 删除【django_makemigrations】表中重复的数据

      1
      delete from django_makemigrations where id=12
    • 再次执行迁移文件生成命令的时候,如果继续报错,则需要修改迁移文件的内容

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      from django.db import migrations, models
      import django.db.models.deletion

      class Migration(migrations.Migration):
      initial = True
      dependencies = [
      ]
      operations = [
      # 如果某个模板在数据库中已经存在而导致无法迁移文件,则直接删除该列表中对应的内容后再执行即可
      migrations.CreateModel(
      name='Book',
      fields=[
      ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
      ('btitle', models.CharField(max_length=256)),
      ('bcontent', models.CharField(max_length=256)),
      ('bpub_date', models.DateField()),
      ],
      ),
      migrations.CreateModel(
      name='Hero',
      fields=[
      ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
      ('hname', models.CharField(max_length=50)),
      ('hgender', models.BooleanField(default=False)),
      ('hcomment', models.CharField(max_length=256)),
      ('hook', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wuxiang.book')),
      ],
      ),
      ]

自定义上传图片

  1. 创建上传图片的模板文件

    1
    2
    3
    4
    5
    6
    7
    # method:必须为post
    # enctype="multipart/form-data":该属性必须存在
    <form method="post" enctype="multipart/form-data" action="/upload_action">
    {% csrf_token %}
    <input type="file" name="pic">
    <input type="submit" value="按钮">
    </form>
  2. 定义上传文件的视图处理函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def upload_file(request):
    # 接受用户传递的图片文件对象, files后面的参数是上传图片按钮的name值
    pic = request.FILES["pic"]

    # 在存储目录下创建文件用于存储该图片
    # pic.name:可以获取到上传图片的文件名
    save_path = '{0}/picture/{1}'.format(settings.MEDIA_ROOT, pic.name)
    with open(save_path, 'wb') as f:
    for data in pic.chunks():
    f.write(data)

    # 在数据库中写入图片的上传记录,
    # pic是该表的字段名,其值填写的是图片存储的路径,路径是相对于
    PIC_Upload.objects.create(pic='picture/%s'.format(pic.name))

    return HttpResponse('OK')

    关于django的视图处理函数:

    • 针对request.FILES处理器一共有两个:

      django.core.files.uploadhandler.MemoryFileUploadHandler

      django.core.files.uploadhandler.TemporaryFileUploadHandler

    • 处理机制:

      当上传的图片的大小小于2.5M时,则文件将存放于内存中,然后使用MemoryFileUploadHandler处理。

      当上传的图片大小大于2.5M时,则文件存放于临时文件中,然后使用TemporaryFileUploadHandler处理

    • 文件读取:

      由于有时上传的文件过大,所有一次性将所有的内容读取到内存中会导致服务器崩溃,因此需要边读边写,每次写一部分图片的内容到文件中,所以有了pic.chunks()的方法,它每次返回一部分图片的内容。

分页

背景

  • 实现web前端的内容分页功能

  • 需要通过Paginator对象来实现梦想

    1
    from django.core.paginator import Paginator

属性和方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from django.core.paginator import Paginator
def show_fenye(request):
'''分页内容展示'''
data = fenye.objects.filter(id__lt=1000)

# 对查询集合进行分页,则需要通过Paginator类对象
# Paginator类对象中:第一个参数添加查询结果集,第二个参数填写每页显示的条数
paginator_list = Paginator(data, 20)

# Paginator对象中有两个类属性:
# num_pages(返回分页后的总页数)
print(paginator_list.num_pages)
# page_range(分页后的页码列表集)
print(paginator_list.page_range)

# 对分页操作后的paginator对象筛选数据,需要通过Page类对象
# Page类对象中:第一个参数是分页数,返回值是该页所有的数据集
page_list = paginator_list.page(2)

# Page类对象中三个属性:
# number:返回当前页的页码
print(page_list.number)
# ogject_list:返回当前页的所有数据的查询集合
print(page_list.object_list)
# paginator:返回对应的paginator对象
print(page_list.paginator)

# Page类对象中四个方法
# has_previous():判断当前页是否有前一页
print(page_list.has_previous())
# has_next():判断当前页之后是否有下一页
print(page_list.has_next())
# previous_page_number():返回前一页的页码
print(page_list.previous_page_number())
# next_page_number():返回下一页的页码
print(page_list.next_page_number())


return render(request, 'show_fenye.html', {"data":page_list})

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.core.paginator import Paginator
def show_fenye(request, pageindex):
data = fenye.objects.filter(id__lt=1000)

paginator_list = Paginator(data, 20)
page_range = list(paginator_list.page_range)
print(page_range)

# 当url未匹配到正则的内容的时候,则会返回空字符串
if pageindex == '':
page_list = paginator_list.page(1)
else:
page_list = paginator_list.page(int(pageindex))

return render(request, 'show_fenye.html', {"data":page_list, 'page': page_range})

拓展

  • jquery前端ajax方法中获取数据的简洁写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 当从服务端获取数据的时候,可以用get方法,当修改、新增、删除数据的时候,都需要用post方法
    // jquery中ajax的get简写,第一个参数是请求的地址,第二个参数是返回数据后的回调函数,其中data是服务器的返回数据
    $.get('/getdata', funcation(data){
    对返回的data数据进行操作
    })

    // ajax的post简写,第一个参数是请求的地址,第二个参数是请求的json数据,第三个是返回数据后的回调函数
    $.post('/getdata', {"name": "shuai", "me": "henshuai"},funcation(data){
    对返回的data数据进行操作
    })
  • jquery循环遍历的简洁写法

    1
    2
    3
    4
    5
    6
    // jquery中对数组进行遍历的时候,可以通过.each方法遍历
    // 第一个参数是遍历的数组对象
    // 第二个参数是对遍历对象执行的函数,index是遍历对象的下标,data是遍历时的数据
    $.each(res, funcation(index, data){
    对遍历的data数据进行操作
    })
  • 对select下拉选项框的监听事件

    1
    2
    3
    4
    // 监听select下拉选项框的选择内容,一旦发生变化,则触发事件
    $('#select').change(funcation(){
    当select下拉选项框发生变化的时候,该事件执行的内容
    })