python + django 搭建网页(尝试5):用户登录

参考来源:
[1] https://zhuanlan.zhihu.com/p/425426994
[2] https://zhuanlan.zhihu.com/p/423436751
[3] https://www.runoob.com/django/django-admin-manage-tool.html
[3] https://www.runoob.com/django/django-model.html

看了 [1-4] ,我意识到接口都是现成的,只需要做适当的设置,把现成的东西组装起来。

1. 模型+数据库

我之前建的站叫做 mysite,然后在 mysite 下试了一下模型+数据库,感觉好像在 mysite 的基础上再安装一个 app,底层可能就是新增一个类。

django-admin startapp TestModel

会生成 mysite/TestModel 文件夹,文件夹下有一系列文件。在 TestModel/models.py 中定义新的类:


# models.py
from django.db import models
 
class Test(models.Model):
    name = models.CharField(max_length=20)

其中新类 Test 继承自内置的 models.Model。
然后在 mysite/mysite/settings.py 中的 APP 列表中加入 TestModel:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'TestModel',               # 添加此项
)

然后需要“migrate”,貌似类似于重载设置:

$ python3 manage.py migrate   # 创建表结构

$ python3 manage.py makemigrations TestModel  # 让 Django 知道我们在我们的模型有一些变更
$ python3 manage.py migrate TestModel   # 创建表结构

然后可以使用数据库(可能用户多了会用得着),我只把数据库操作的函数抄录在这里,使用的时候需要做相应的 url 配置。


# -*- coding: utf-8 -*-
 
from django.http import HttpResponse
 
from TestModel.models import Test
 
# 数据库操作
def testdb(request):
    test1 = Test(name='runoob')
    test1.save()
    return HttpResponse("<p>数据添加成功!</p>")


# -*- coding: utf-8 -*-
 
from django.http import HttpResponse
 
from TestModel.models import Test
 
# 数据库操作
def testdb(request):
    # 初始化
    response = ""
    response1 = ""
    
    
    # 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM
    list = Test.objects.all()
        
    # filter相当于SQL中的WHERE,可设置条件过滤结果
    response2 = Test.objects.filter(id=1) 
    
    # 获取单个对象
    response3 = Test.objects.get(id=1) 
    
    # 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2;
    Test.objects.order_by('name')[0:2]
    
    #数据排序
    Test.objects.order_by("id")
    
    # 上面的方法可以连锁使用
    Test.objects.filter(name="runoob").order_by("id")
    
    # 输出所有数据
    for var in list:
        response1 += var.name + " "
    response = response1
    return HttpResponse("<p>" + response + "</p>")



# -*- coding: utf-8 -*-
 
from django.http import HttpResponse
 
from TestModel.models import Test
 
# 数据库操作
def testdb(request):
    # 修改其中一个id=1的name字段,再save,相当于SQL中的UPDATE
    test1 = Test.objects.get(id=1)
    test1.name = 'Google'
    test1.save()
    
    # 另外一种方式
    #Test.objects.filter(id=1).update(name='Google')
    
    # 修改所有的列
    # Test.objects.all().update(name='Google')
    
    return HttpResponse("<p>修改成功</p>")




# -*- coding: utf-8 -*-
 
from django.http import HttpResponse
 
from TestModel.models import Test
 
# 数据库操作
def testdb(request):
    # 删除id=1的数据
    test1 = Test.objects.get(id=1)
    test1.delete()
    
    # 另外一种方式
    # Test.objects.filter(id=1).delete()
    
    # 删除所有数据
    # Test.objects.all().delete()
    
    return HttpResponse("<p>删除成功</p>")

2. Admin 管理工具

要激活 admin,只需在 urls.py 中 的 urlpatterns 里加入(模块也抄在下面)

from django.contrib import admin

    path('admin/', admin.site.urls),

就可以从 localhost:8000/admin 得到登录界面。
创建超级用户以后就可以进行登录:

python3 manage.py createsuperuser

注意,在第一次 migrate 之前,打上面的代码会报错。

3. 增加 APP: user

先在 settings.py 里增加设置一下语言、时区,模板路径

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

静态文件路径

# 配置静态文件路径与 url
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
    '/var/www/static',
]

# 配置用户上传文件路径和 url
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join( BASE_DIR, "media")

然后在 urls.py 中设置

from django.conf import settings # 使用 settings.py 中的变量
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)  # 配置静态文件url

# 配置用户上传文件url
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

后面两行是把静态文件、上传文件的 url 加入 urlpatterns。
然后生成 user app,和前面的 TestModel 一样,也要把 users 注册到 settings.py 中的 INSTALLED_APPS 中。
然后在 users/models.py 中定义新的类 UserProfile,使用内置的 User 类,进行一对一关联(OneToOneField),

from django.contrib.auth.models import User

# 完整如下
class UserProfile(models.Model):

    USER_GENDER_TYPE = (
        ('male', '男'),
        ('female', '女'),
    )

    owner = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name='用户')
    nike_name = models.CharField('昵称', max_length=23, blank=True, default='')
    birthday = models.DateField('生日', null=True, blank=True)
    gender = models.CharField('性别', max_length=6, choices=USER_GENDER_TYPE, default='male')
    address = models.CharField('地址', max_length=100, blank=True, default='')
    image = models.ImageField(upload_to='images/%Y/%m', default='images/default.png', max_length=100, verbose_name = '用户头像')

    class Meta:
        verbose_name = '用户数据'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.owner.username

用户上传的静态图片会自动储存,需要在 settings.py 中 TEMPLATES 的 OPTIOINS 中添加
'django.template.context_processors.media',

在 users/admin.py 中注册 UserProfile 模型

# 首先引入User
from django.contrib.auth.models import User
# 我们看到的这个用户选项就是官方默认通过UserAdmin这个类注册到后台的,那么我们也引入进来,后边继承这个类
from django.contrib.auth.admin import UserAdmin
# 再引入我们定义的模型
from .models import UserProfile
# 必须先通过unregister将User取消注册
admin.site.unregister(User)

# 定义关联对象的样式,StackedInline为纵向排列每一行,TabularInline为并排排列
class UserProfileInline(admin.StackedInline):
    model = UserProfile   # 关联的模型

# 关联字段在User之内编辑,关联进来
class UserProfileAdmin(UserAdmin):
    inlines = [UserProfileInline]

# 重新注册User
admin.site.register(User, UserProfileAdmin)

然后重新 migrate, migrations, migrate。
我感觉这个做的有点啰嗦。
我不知道为什么不直接用内置的 User 类。

4. 静态登录页

搞个 user/templates/user/login.html

<form action=""method="post">
    {% csrf_token %} # 模板标签,用来通过 csrf 伪造防护
	<label for="id_username">用户名:</label>
    <input type="text" name="username" id="id_username">
    <label for="id_password">密码:</label>
    <input type="password"name="password"id="id_password">
    <input type="submit"value="提交">
</form>

然后想办法让 urls.py 调用 views.login_view,让用户输入用户名和密码,然后和数据库中信息进行比照:

# users/views.py

from django.shortcuts import render, HttpResponse
from django.contrib.auth import authenticate, login

def login_view(request):

    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        # 与数据库中的用户名和密码比对,django默认保存密码是以哈希形式存储,并不是明文密码,这里的password验证默认调用的是User类的check_password方法,以哈希值比较。
        user = authenticate(request, username=username, password=password)
        # 验证如果用户不为空
        if user is not None:
            # login方法登录
            login(request, user)
            # 返回登录成功信息
            return HttpResponse('登陆成功')
        else:
            # 返回登录失败信息
            return HttpResponse('登陆失败')

    return render(request, 'users/login.html')

url 设置为: mysite/urls.py 中

    path('users/', include('users.urls')),  # 这里使用include()引入users.urls文件

然后在 users/urls.py 中

from django.urls import path
from . import views

app_name = 'users'   # 定义一个命名空间,用来区分不同应用之间的链接地址
urlpatterns = [ 
    path('login.html', views.login_view, name='login')
]

5. 总结+展望

一边联系这些操作,一边尝试,通过阅读命令行中的报错信息,我重复出了登录界面: localhost:8000/users/login.html
这个界面只能用来核实:用户名+密码 是否存在,没有真的“登录”什么东西。

下一步可以尝试增加注册、上传功能,就可以满足《计算物理》的需求了。我感觉可以尝试搞懂几个自己需要的功能,然后自己尝试尝试,不用这么亦步亦趋地跟着做了。

posted on 2022-09-11 20:27  luyi07  阅读(167)  评论(0编辑  收藏  举报

导航