ORM练习(利用数据查询/增加/修改做登录/注册/用户查询页面)

ORM命令大全

# 创建主键 名为id字段
id = models.AutoField(primary_key=True,verbose_name='主键')
'''
primary_key=True 是自增的意思
verbose_name='主键' 是对字段的解释、注释,可以不加
'''

# 创建char类型,名为username的字段
username = models.CharField(max_length=32)
'''max_length=32 是范围限制,表示最多32位'''

# 创建int类型,名为password的字段
password = models.IntegerField()

ORM命令参数解释

hobby = models.CharField(max_length=32,verbose_name='兴趣爱好',default='学习')
'''
max_length=32 是范围限制,表示最多32位,字符串类型必须设置的参数
verbose_name 是该字段的解释,所有字段都应该有的
default='学习' 是默认值的意思
'''

一、ORM练习之数据查询

之前我们学会request对象,后端可以获取前端提交的数据,现在我们又学会了ORM操作数据库的方法。那么我们就来实现下面的需求,

用户在浏览器登录账号,点击登录提交。
后端拿到用户提交的数据,然后去数据库和数据对比。
如果对比一致,就打印 登录成功,否则失败

def login(request):
    user = request.POST.get('username')
    pwd = request.POST.get('password')
    from app01 import models
    res = models.User.objects.filter(username=user)  # 查询数据库
    obj1 = res[0]
    print(obj1)  # User object
    print(obj1.username)  # poco
    print(obj1.password)  # 123

    return render(request, 'login.html')

'''【分析】
user = request.POST.get('username')
pwd = request.POST.get('password')
上面这两段代码拿的是前端用户输入的 用户名和密码

res = models.User.objects.filter(username=user)
这段代码拿的是数据库里的一个对象,它可以调用方法

obj1.username
obj1.password
这两段代码是真正的拿到是数据库里的用户和密码
'''

1、用户登录(后端视图层逻辑代码)

def login(request):
    # 如果用户提交POST请求,就运行下列代码
    if request.method == 'POST':
        # 拿到用户提交的数据
        user = request.POST.get('username')
        pwd = request.POST.get('password')
        # 导入models模型层
        from app01 import models
        # 查询数据库里的数据
        res = models.User.objects.filter(username=user).first()
        obj1 = res
        # 前端用户名和数据库的用户名进行比对,然后根据不同的判断结果显示不同内容
        if user == obj1.username:
            if pwd == obj1.password:
                return HttpResponse('登录成功')
            else:
                return HttpResponse('密码错误')
        else:
            return HttpResponse('用户名不存在')
    # 用户提交GET请求运行,这行代码
    return render(request, 'login.html')

1-1、遇到的错误

'''
问题1:明明前端输入的密码和数据库密码一样,但验证密码时总是不对

解决方法:前端拿到的数据都是str类型,我把密码字段设置成了int类型,所以我把字段改成了数据库的char类型。这里也可以把前端拿到的数据转换成int类型
'''
#####################################################
'''
问题2:在测试时,我输入一个数据库不存在的用户名时,总是报错,
AttributeError: 'NoneType' object has no attribute 'username'
按照我上面写的代码来说,应该是返回一个用户名不存在的页面

解决方法:按理来说filter查询即使查不到也不会报错的。。。不知道为什么
只好用一个异常捕获的代码解决了。。。。

def login(request):
    try:
        if request.method == 'POST':
            user = request.POST.get('username')
            pwd = request.POST.get('password')
            from app01 import models
            res = models.User.objects.filter(username=user).first()
            obj1 = res
            if user == obj1.username:
                if pwd == obj1.password:
                    return HttpResponse('登录成功')
                else:
                    return HttpResponse('密码错误')
    except AttributeError as e:
        return HttpResponse('用户名不存在')
    return render(request, 'login.html')
'''

2、用户注册

def reg(request):
    if request.method == 'POST':
        user = request.POST.get('username')
        pwd = request.POST.get('password')
        res = models.User.objects.create(username=user, password=pwd)
    return render(request,'reg.html')

3、用户数据展示以及编辑、删除

首先是前端页面,用于展示数据和提供编辑、删除按钮

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load static %}
    <link rel="stylesheet" href="{% static '/css/bootstrap.min.css' %}">
</head>
<body>

<h1 class="text-center">数据展示</h1>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
        <table class="table table-striped table-hover">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>username</th>
                    <th>password</th>
                    <th>action</th>
                </tr>
            </thead>
            <tbody>
                {% for user_obj in user_queryset %}
                    <tr>
                        <td>{{ user_obj.id }}</td>
                        <td>{{ user_obj.username }}</td>
                        <td>{{ user_obj.password }}</td>
                        <td>
                            <a href="" class="btn btn-primary btn-xs">编辑</a>
                            <a href="" class="btn btn-danger btn-xs">删除</a>
                        </td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
        </div>
    </div>
</div>

</body>
</html>

然后就是后端视图层的逻辑代码,用locals()把内容全部显示到前端去

# 数据展示
def userlist(request):
    user_queryset = models.User.objects.all()
    return render(request,'userlist.html',locals())

好,数据的查询我们已经做到了,现在我们该做编辑、删除功能了,HTML代码里不是有编辑和删除的按钮吗,我们在后端开放编辑和删除的接口就好了,接下来我们拿删除做一个举例

# 我们先去路由层开一个接口
url(r'^edit_user/', views.edit_user),

# 然后去视图层写删除的逻辑,这里先简单的演示一下
def edit_user(request):
    return HttpResponse('编辑用户')

# 修改userlist的HTML文件 编辑按钮
 <a href="/edit_user/" class="btn btn-primary btn-xs">编辑</a>
    
# 然后再去创建一个edit_user的HTML文件,点击编辑按钮就可以跳转到这个页面修改数据,可以拿之前用户注册的页面改一改

现在又有一个问题,前端如果点击 编辑和删除的按钮,后端如何知道前端点击的是哪一条数据呢,如果不知道具体是哪一条数据,我们就无法进行编辑和删除了。如何解决?请看下面

'''
如何告诉后端,用户想要编辑的是哪条数据?
我们知道【问号(?)】后面的参数不会参与路由匹配,所以利用url问号后面携带参数的方式,
将编辑按钮所在的那一行数据的主键值发送给后端
'''
<td>{{ user_obj.id }}</td>
<td>{{ user_obj.username }}</td>
<td>{{ user_obj.password }}</td>
<td>
	<a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-primary btn-xs">编辑</a>
	<a href="" class="btn btn-danger btn-xs">删除</a>
</td>

'''能够理解上面那行代码吗?,?user_id={{ user_obj.id }}这行代码我们就能获取到用户的主键id
比如说前端点击了第一条数据的编辑按钮,它的url就是这样的,类似于get请求'''
http://127.0.0.1:8000/edit_user/?user_id=1
# 所以我们后端就可以用request.GET.get('user_id')的方式获取到前端点击的具体数据了

def edit_user(request):
    # 获取 url问号后面的参数
    edit_id = request.GET.get('user_id')
    # 查询当前用户想要编辑的数据对象
    edit_obj = models.User.objects.filter(id=edit_id).first()
    # 将对象数据展示到页面上
    return render(request, 'edit_user.html',locals())

视图层edit_user函数完整的逻辑

def edit_user(request):
    # 获取 url问号后面的参数
    edit_id = request.GET.get('user_id')
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 修改数据库对应的数据内容
        models.User.objects.filter(id=edit_id).update(username=username, password=password)
        # 数据修改完毕跳转回 原页面
        return redirect('/userlist/')
    # 查询当前用户想要编辑的数据对象
    edit_obj = models.User.objects.filter(id=edit_id).first()
    # 将对象数据展示到页面上
    return render(request, 'edit_user.html', locals())

编辑我们就已经完成了,接下来就是删除功能,学会了编辑,删除就很简单了。。。和编辑的操作大同小异。。

# 我们先去路由层开一个接口
url(r'^del_user/', views.del_user),

# 然后去视图层写删除的逻辑,这里先简单的演示一下
def del_user(request):
	pass

# 修改userlist的HTML文件 删除按钮
<a href="/del_user/?user_id={{ user_obj.id }}" class="btn btn-danger btn-xs">删除</a>
    

删除完成(删除按理来说应该增加一个二次确认,目前我们就先不实现这个需求了)

def del_user(request):
    # 获取url问号后面的参数
    del_id = request.GET.get('user_id')
    # 删除按钮
    models.User.objects.filter(id=del_id).delete()
	# 删除完成跳转回到查询页面
    return redirect('/userlist/')
posted @ 2021-05-27 10:24  黑影Poco  阅读(98)  评论(0)    收藏  举报