前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python Django个人网站搭建10-扩展用户信息

Python Django个人网站搭建10-扩展用户信息

作者头像
zifan
发布2021-12-14 12:30:27
4980
发布2021-12-14 12:30:27
举报
文章被收录于专栏:个人编程技术学习与分享

作者: zifanwang  发布于2020-05-16

1. 扩展用户信息

编写userprofile/models.py:

代码语言:javascript
复制
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
   # 与User模型构成一对一的关系
   user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
   phone = models.CharField(max_length=20, blank=True)
   avatar = models.ImageField(upload_to='avatar/%Y%m%d/', blank=True)
   bio = models.TextField(max_length=500, blank=True)

   def __str__(self):
       return 'user{}'.format(self.user.username)


# 信号接受函数,每当新建User实例时自动调用
@receiver(post_save, sender=User)
def create_user_profile(sender,instance, created, **kwargs):
   if created:
       Profile.objects.create(user=instance)

# 信号更新函数,每当更新User实例时自动调用
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
   instance.profile.save()

每个Profile模型对应唯一的一个User模型,形成了对User的外接扩展,因此你可以在Profile添加任何想要的字段。 这种方法的好处是不需要对User进行任何改动,从而拥有完全自定义的数据表。 模型本身没有什么新的知识,比较神奇的是用到的信号机制。 接下来重建数据库, 安装pillow 在命令行输入:

代码语言:javascript
复制
pip install Pillow

然后迁移数据

代码语言:javascript
复制
C:\mysite>python manage.py makemigrations
System check identified some issues:

WARNINGS:
article.ArticlePost.created: (fields.W161) Fixed default value provided.
        HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. If you want to have the current date as default, use `django.utils.timezone.now`
Migrations for 'article':
  article\migrations\0004_auto_20200516_1827.py
    - Alter field created on articlepost
Migrations for 'userprofile':
  userprofile\migrations\0001_initial.py
    - Create model Profile

C:\mysite>
代码语言:javascript
复制
C:\mysite>python manage.py migrate
System check identified some issues:

WARNINGS:
article.ArticlePost.created: (fields.W161) Fixed default value provided.
        HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. If you want to have the current date as default, use `django.utils.timezone.now`
Operations to perform:
  Apply all migrations: admin, article, auth, contenttypes, sessions, userprofile
Running migrations:
  Applying article.0004_auto_20200516_1827... OK
  Applying userprofile.0001_initial... OK

C:\mysite>

成功迁移数据库了。 在虚拟环境中输入python manage.py shell:

代码语言:javascript
复制
C:\mysite>python manage.py shell
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

接下来输入:

代码语言:javascript
复制
>>> from django.contrib.auth.models import User
>>> User.objects.all().delete()
(11, {'admin.LogEntry': 6, 'auth.User_groups': 0, 'auth.User_user_permissions': 0, 'article.ArticlePost': 4, 'userprofile.Profile': 0, 'auth.User': 1})
>>>

接下来为Profile模型新建一个表单类userprofile/forms.py去编辑它的内容:

代码语言:javascript
复制
from .models import Profile
...
class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('phone', 'avatar', 'bio')

接下来在userprofile/views.py中填写处理用户信息的函数profile_edit

代码语言:javascript
复制
from .froms import ProfileForm
from .models import Profile
...
# 编辑用户信息
@login_required(login_url='/userprofile/login/')
def profile_edit(request, id):
    user = User.objects.get(id=id)
    # user_id是OneToOneField自动生成的字段
    profile = Profile.objects.get(user_id=id)

    if request.method == 'POST':
        # 验证修改数据者是否为本人
        if request.user != user:
            return HttpResponse("你没有权限修改次用户信息")

        profile_form = ProfileForm(data=request.POST)
        if profile_form.is_valid():
            # 取得清洗后的合法数据
            profile_cleaned_data = profile_form.cleaned_data
            profile.phone = profile_cleaned_data['phone']
            profile.bio = profile_cleaned_data['bio']
            profile.save()
            return redirect("userprofile:edit", id=id)

        else:
            return HttpResponse("注册表单输入有误,请重新输入")

    elif request.method == "GET":
        profile_form = ProfileForm()
        context = {'profile_form': profile_form, 'profile': profile, 'user': user}
        return render(request, 'userprofile/edit.html', context)
    else:
        return HttpResponse("请使用GET或POST请求数据")

接下来在templates/userprofile中新建模板文件edit.html并写入:

代码语言:javascript
复制
{% extends "base.html" %}
{% load static %}
{% block title %}
User
{% endblock title %}
{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-12">
                <br>
                <div class="col-md-4">Username {{ user.username }}</div>
                <br>
                <form method="post" action=".">
                    {% csrf_token %}
                    <div class="form-group col-md-4">
                        <label for="phone">phone</label>
                        <input type="text" class="form-control" id="phone" name="phone" value="{{ profile.phone }}">
                    </div>
                    <div class="form-group col-md-4">
                        <label for="bio">bio</label>
                        <textarea type="text" class="form-control" id="bio" name="bio" rows="12">{{ profile.bio }}</textarea>
                    </div>
                    <button type="submit" class="btn btn-primary">submit</button>
                </form>
            </div>
        </div>
    </div>
{% endblock content %}

下一步配置userprofile/urls.py:

代码语言:javascript
复制
path('edit/<int:id>/', views.profile_edit, name='edit'),

接下来给人个信息添加一个入口 修改templates/header.html

代码语言:javascript
复制
...
               <div class="dropdown-menu" aria-labelledby="navbarDropdown">
         <a class="dropdown-item" href="{% url "userprofile:edit" user.id %}">User</a>
                 <a class="dropdown-item" href="{% url "userprofile:logout" %}">Exit</a>
         <a class="dropdown-item" href="#" onclick="user_delete()">Delete</a>
               </div>
...

接下来修改article/views.py视图,前面为了简单就把所有文章的作者全部绑定为用户id为1的用户, 还没有对用户登陆状态进行检查:

代码语言:javascript
复制
...
from django.contrib.auth.decorators import login_required
...
@login_required(login_url='/userprofile/login')
def article_create(request):
    ...
           new_article = article_post_form.save(commit=False)
           new_article.author = User.objects.get(id=request.user.id)
           new_article.save()
            ...

运行服务器(python manage.py runserver):

点击用户信息后就可以编辑和查看了。

2. 配置Admin

在admin中将User profile合并为一张完整的表格:修改userprofile/admin.py:

代码语言:javascript
复制
from django.contrib import admin
from userprofile.models import Profile
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
class ProfileInline(admin.StackedInline):
   model = Profile
   can_delete = False
   verbose_name_plural = 'UserProfile'

# 将Profile关联到User中
class UserAdmin(BaseUserAdmin):
   inlines = (ProfileInline, )


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

打开admin中的User表(http://127.0.0.1:8000/admin/auth/user/),点进一个用户就可以看见Profile的数据已经堆叠在底部了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-05-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 扩展用户信息
  • 2. 配置Admin
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档