Django的入门(二)创建models和处理数据、上传显示图片

这篇博客介绍了Django入门的一些关键步骤,包括启动服务器、记录终端内容、关闭CSRF保护、创建注册页面、在models.py中定义数据库字段、url.py的跳转逻辑、正则匹配URL路径、处理POST请求的CheckBox和文件上传,以及如何在Django中显示图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


继续上文,这次完成接收前端网页的GET和POST请求数据并处理
具体功能为实现注册账户密码和修改密码功能,并实现数据库交互

终端开启服务器

  • cd 到你的文件夹
  • workon django_py3 // 用workon打开你配置好的虚拟环境
  • python manage.py runserver // 运行服务器

记录终端的内容到txt文件中

在你要放这个txt文件的地方创建

script -a 1.txt

设定接下去的终端所有内容,都打印到1.txt这个文件,同时在终端显示结果。只到你输入:

exit

为止。这样打印出来的文本文件直接在图形化的gedit打开有些字符是无法正常显示的,但是如果利用

cat 1.txt

发现是没有乱码的。

关闭csrf保护的三种方法

在html文件的表单标签里写

<form method="POST" action="/user/changepwd/">
     {#  前后端不分离发送form表单要加这个  #}
     {% csrf_token %}

在setting.py这个列表第四个,注释掉即可

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',  # 这个就是验证
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

在viwes.py导包然后写装饰器,也是关csrf验证

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def changepwd(request):

创建注册网页

这里action是跳转到handleraddress/,要注意斜杠

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>注册账号</h1>
<form method="POST" action="/user/handleraddress/">
     {#  前后端不分离发送form表单要加这个  #}
     {% csrf_token %}
     <sapn>请输入名字</sapn><input type="text" name="username"><br>
     <sapn>请输入密码</sapn><input type="password" name="pwd"><br>
     <sapn>请确认密码</sapn><input type="password" name="cpwd"><br>
     <sapn>请输入地址</sapn><input type="text" name="addname"><br>
     <sapn>请输入手机号码</sapn><input type="text" name="phone"><br>
     <input type="submit" value="提交">

</form>
</body>
</html>

在models.py添加数据库字段(列名)

直接添加一个字段password,然后在终端写python manage.py makemigrations迁移数据库
python manage.py migrate

# 每个表对应一个类
class UserInfo(models.Model):
    name = models.CharField(max_length=20)
    password = models.CharField(max_length=20, default='123456')
    phone = models.CharField(max_length=11)
    addkey = models.ForeignKey(AddressInfo, on_delete=models.CASCADE)

    class Meta:
        # 元类
        db_table = 'userinfo'
        verbose_name_plural = '用户信息'

    def __str__(self):
        return self.name

在url.py写跳转逻辑

最下面三个是今天要写的功能

from django.conf.urls import url
from user.views import *

urlpatterns = [
    url(r'^index/', index),
    url(r'^userinfo/', userinfo),
    url(r'^show_userinfos/', show_userinfos),
    url(r'^register/', register),
    url(r'^handleraddress/', handleradd),
    url(r'^changepwd/',changepwd),
]

url路径匹配使用正则匹配

  • 这是用()里面内容正则匹配,会匹配出一组则会生成一个参数自动传输到views.py里对应的函数, 所以需要多加一个参数
  • ()正则匹配如果多写了,就要多添加几个参数
  • 正则写多了可以用?P<NAME>,这个name是写别名用的
    url(r'^(?P<city>city)/(?P<cname>\w+)/', showadd),

在views.py的对应方法showadd加参数:

def showadd(request, cname, city):
    print(request.path)  # 这两种都能打印路径
    print('城市名字是', cname)  # 这种更直接,直接打印正则匹配的路径没有/
    print('city是', city)
    return HttpResponse('城市页面')

在views.py写功能

上面导包不能少

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
import re

def register(request):
	# render返回网页,HttpResponse返回字符串,JsonResponse返回json数据
    return render(request, 'register.html')


def handleradd(request):
    print('##############################3')
    print(request.POST)
    # addname = request.GET.get('addname')
    # POST的获取方法
    addname = request.POST.get('addname')
    username = request.POST.get('username')
    phone = request.POST.get('phone')
    pwd = request.POST.get('pwd')
    cpwd = request.POST.get('cpwd')
    # 如果为空返回false
    if not all([username, addname, phone, pwd, cpwd]):
        return JsonResponse({'null': "can't be null!!"})
    # 验证用户名的首字母大写,必须是数字字母下划线6-8位
    # 校验两次密码是否一致
    # 校验地址,不存在则创建,存在则使用旧地址
    # 将处理后的数据插入数据库
    ret = re.match(r"^[A-Z][a-zA-Z0-9_]{5,7}$", username)
    try:
        print('匹配成功', ret.group())
        if pwd == cpwd:
            try:
                # 检验数据库是否已存在地址
                add_obj = AddressInfo.objects.get(add=addname)
            except BaseException as e:
                print('校验数据库出的错误:', e)
                add_obj = AddressInfo.objects.create(add=addname)
            finally:
                UserInfo.objects.create(
                    name=username,
                    password=pwd,
                    phone=phone,
                    addkey=add_obj
                )
                return HttpResponse('OK')
        else:
            return HttpResponse('密码不一致')
    except BaseException as e:
        print('校验用户名出的错误:', e)
        return HttpResponse('用户名的首字母大写,必须是数字字母下划线6-8位')


def changepwd(request):
    if request.method == 'GET':
        print('###############')
        print('进入get请求')
        return render(request, 'changepwd.html')
    else:
        # 进入post请求
        # 参数分别是用户名,旧密码,新密码,确认新密码
        username = request.POST.get('username')
        old_pwd = request.POST.get('old_pwd')
        pwd = request.POST.get('pwd')
        cpwd = request.POST.get('cpwd')
        '''1.检验名字是否存在
        2.校验旧密码是否匹配
        3.输入密码和确认密码是否一致
        4.最后修改'''
        try:
            # 检验数据库是否存在用户名
            user_list = UserInfo.objects.filter(name=username)
            print('*********************POST')
            obj = user_list[0]
            if len(user_list) == 0 or obj.password != old_pwd:
                return HttpResponse('用户名或者密码存在错误')
            else:
                if pwd != cpwd:
                    # 判断密码
                    return HttpResponse('密码不一致')
                # 取出对象,然后修改密码并保存
                user_obj = UserInfo.objects.get(name=username)
                # user_obj.password = pwd
                # 第二种修改方法
                user_obj.objects.update(password=pwd)
                user_obj.save()
                return HttpResponse('ok')
        except BaseException as e:
            return HttpResponse(e)

views.py某些小知识点

request.GET或者POST得到的是一个类字典结构的数据,其实是QueryDict对象
用postman软件模拟get请求,即

localhost:8000/user/city/beijing?name=小王&age=18&age=19

然后request.GET打印出来结果为:

<QueryDict: {'name': ['小王'], 'age': ['18', '19']}>

但是用getlist可以获取所有,这两个方法都可以设置默认值

	print(request.GET)  # 只能获取一个,最后那个
   	print(request.GET.getlist('age'))  # 获取对应的列表

POST请求的时候CheckBox传递加名字

value设置名字,不设置则显示状态

<form method="post" action="show">
    姓名:<input type="text" name="username">
    爱好:<input type="checkbox" name="hobby" value="sing"><input type="checkbox" name="hobby" value="dance"><input type="checkbox" name="hobby" value="rap">rap
    <input type="checkbox" name="hobby" value="basketball">篮球
    <input type="submit" value="提交">

</form>

打印结果

<QueryDict: {'hobby': ['on', 'on', 'on', 'basketball'], 'username': ['cxk']}>

POST发送文件

    <input type="file" name="file"><br>

打印request.body得到的是二进制编码,这里可以用png,jpg,jpeg文件

	print(request.body)  # 这个获取到的就是原始文件数据,bytes类型
    print(request.POST)  # 类字典
    data = request.body
    with open('上传的图片.png', 'wb+') as f:
        f.write(data)

这时候用POSTMAN软件模拟请求:
在这里插入图片描述

如何使用form表单提交文件:
修改这个enctype

<form method="post" action="show2" enctype="multipart/form-data">

然后打印看看效果

print(request.FILES)  # 这个获取到的是字典类型
# <form method="post" action="show2" enctype="multipart/form-data">

print(request.FILES['file'])  # 这个打印显示是一个class django的某种对象

所以可以使用这个对象:

file_obj = request.FILES['file']
print('##################')
# chunks表示不溢出内存读取,打印出来的是二进制及文件内容
for i in file_obj.chunks():
	print(i)
    with open('form上传的.png', 'wb+') as f:
    	f.write(i)

Django怎么显示图片

图片是本地路径上,但是Django里img标签src只会查找url路径,不能填相对路径或者绝对路径,因此需要转换

在urls.py进行转换:

from django.views.static import serve
# 导包

# 指定路径显示图片,serve是方法
# document_root后面对的是本地相对路径
urlpatterns = [
    url(r'^medias/(?P<path>.*)$', serve, {'document_root': ''}),
]

然后在views.py对应方法写:

		print(request.FILES['file'])  # 这个打印显示是一个class django的某种对象
        file_obj = request.FILES['file']
        print('##################')
        # chunks表示不溢出,打印出来的是二进制及文件内容
        imgsrc = '../medias/xiaobei.jpg'  # 这个是相对路径,根据url配置来
        for i in file_obj.chunks():  
			# 这个是表单上传并写入到本地的地址,默认为相对根目录路径
            with open('xiaobei.jpg', 'wb+') as f:
                f.write(i)
		# hobby是表单选择得到的结果,多项选择因此是list,进行拼接,也可以直接传列表
        list1 = request.POST.getlist('hobby')
        str1 = ''
        for s in list1:
            str1 += ' ' + s
        name = request.POST['username']
		# 把这些拼成context字典传过去,然后在html处理
        context = {'imgsrc': imgsrc, 'name':name, 'interest':str1}
        return render(request, 'myprofile.html', context)

在对应的html界面处理数据:

<head>
    <meta charset="UTF-8">
    <title>个人资料</title>
    <style>
        h1{
            display: inline-block;
        }
        .imgsrc{
            border-radius: 50px;
            display: inline-block;
        }
    </style>
</head>
<body>
<h1>{{ name }}</h1><img src="{{ imgsrc }}" class="imgsrc" width="50px" height="50px"><br>
<span>我的爱好是:{{ interest }}</span>
</body>

这样显示的网页内容为:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值