Django(15):身份和权限认证

news2024/11/25 2:56:23

目录

  • 1.Django中的身份认证模块
    • 1.1 用户模型
    • 1.2 认证模块
    • 1.3 项目搭建演示
  • 2.权限管理架构
    • 2.1 权限相关数据模型
    • 2.2 权限相关功能函数
    • 2.3 权限分配函数
    • 2.4 权限设置
  • 3.资源访问管理

1.Django中的身份认证模块

1.1 用户模型

Django中有内建的用户模块django.contrib.auth.models.User,该类型通过定义网站中用户的基本数据完成身份认证功能支持。代码如下:

class User(AbstractUser):
    """
    Users within the Django authentication system are represented by this
    model.

    Username and password are required. Other fields are optional.
    """

    class Meta(AbstractUser.Meta):
        swappable = "AUTH_USER_MODEL"

可以看到它继承了AbstractUser,其代码如下:

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.

    Username and password are required. Other fields are optional.
    """

    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        _("username"),
        max_length=150,
        unique=True,
        help_text=_(
            "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
        ),
        validators=[username_validator],
        error_messages={
            "unique": _("A user with that username already exists."),
        },
    )
    first_name = models.CharField(_("first name"), max_length=150, blank=True)
    last_name = models.CharField(_("last name"), max_length=150, blank=True)
    email = models.EmailField(_("email address"), blank=True)
    is_staff = models.BooleanField(
        _("staff status"),
        default=False,
        help_text=_("Designates whether the user can log into this admin site."),
    )
    is_active = models.BooleanField(
        _("active"),
        default=True,
        help_text=_(
            "Designates whether this user should be treated as active. "
            "Unselect this instead of deleting accounts."
        ),
    )
    date_joined = models.DateTimeField(_("date joined"), default=timezone.now)

    objects = UserManager()

    EMAIL_FIELD = "email"
    USERNAME_FIELD = "username"
    REQUIRED_FIELDS = ["email"]

    class Meta:
        verbose_name = _("user")
        verbose_name_plural = _("users")
        abstract = True

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def get_full_name(self):
        """
        Return the first_name plus the last_name, with a space in between.
        """
        full_name = "%s %s" % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Return the short name for the user."""
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

可以看到,AbstractUser有自己的属性和方法,同时也从AbstractBaseUser, PermissionsMixin继承了其他属性和方法,具体内容可参看源码。

同时,如果用户没有身份信息,访问网站时,Django框架通过django.contrib.auth.models.AnonymousUser类型为其赋予了一个匿名身份。其源码如下:

class AnonymousUser:
    id = None
    pk = None
    username = ""
    is_staff = False
    is_active = False
    is_superuser = False
    _groups = EmptyManager(Group)
    _user_permissions = EmptyManager(Permission)

    def __str__(self):
        return "AnonymousUser"

    def __eq__(self, other):
        return isinstance(other, self.__class__)

    def __hash__(self):
        return 1  # instances always return the same hash value

    def __int__(self):
        raise TypeError(
            "Cannot cast AnonymousUser to int. Are you trying to use it in place of "
            "User?"
        )

    def save(self):
        raise NotImplementedError(
            "Django doesn't provide a DB representation for AnonymousUser."
        )

    def delete(self):
        raise NotImplementedError(
            "Django doesn't provide a DB representation for AnonymousUser."
        )

    def set_password(self, raw_password):
        raise NotImplementedError(
            "Django doesn't provide a DB representation for AnonymousUser."
        )

    def check_password(self, raw_password):
        raise NotImplementedError(
            "Django doesn't provide a DB representation for AnonymousUser."
        )

    @property
    def groups(self):
        return self._groups

    @property
    def user_permissions(self):
        return self._user_permissions

    def get_user_permissions(self, obj=None):
        return _user_get_permissions(self, obj, "user")

    def get_group_permissions(self, obj=None):
        return set()

    def get_all_permissions(self, obj=None):
        return _user_get_permissions(self, obj, "all")

    def has_perm(self, perm, obj=None):
        return _user_has_perm(self, perm, obj=obj)

    def has_perms(self, perm_list, obj=None):
        if not is_iterable(perm_list) or isinstance(perm_list, str):
            raise ValueError("perm_list must be an iterable of permissions.")
        return all(self.has_perm(perm, obj) for perm in perm_list)

    def has_module_perms(self, module):
        return _user_has_module_perms(self, module)

    @property
    def is_anonymous(self):
        return True

    @property
    def is_authenticated(self):
        return False

    def get_username(self):
        return self.username

正常情况下,上面的用户信息是不能满足我们的业务需求的,在实际项目中,可以根据需求自定义用户的扩展资料,将扩展资料和内建用户进行一对一关联,这样可以使用户的资料会大幅提升。

1.2 认证模块

Django框架内建的django.contrib.auth模块封装了身份认证和状态保持操作,可以使用django.contrib.auth.authenticate完成核心的身份认证处理。源代码如下:

@sensitive_variables("credentials")
def authenticate(request=None, **credentials):
    """
    If the given credentials are valid, return a User object.
    """
    for backend, backend_path in _get_backends(return_tuples=True):
        backend_signature = inspect.signature(backend.authenticate)
        try:
            backend_signature.bind(request, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try
            # the next one.
            continue
        try:
            user = backend.authenticate(request, **credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be
            # allowed in at all.
            break
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path
        return user

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(
        sender=__name__, credentials=_clean_credentials(credentials), request=request
    )

同时,使用django.contrib.auth封装的login()函数完成了状态保持,将用户保持到当前会话中;使用logout()函数可以移除状态保持。具体的内容可以参考源码。

1.3 项目搭建演示

1.创建项目

# 创建项目perm_demo
django-admin startproject perm_demo
# 创建blog子项目
cd perm_demo/
django-admin startapp blog

2.创建数据模型

在blog子项目中编辑models.py模块,添加用户扩展资料:

class UserProfile(models.Model):
    """用户扩展资料"""
    C_GENDER = (
        ("0", "女"),
        ("1", "男"),
    )
    # 关联内建用户
    user = models.OneToOneField(verbose_name="用户", to=User, related_name="profile", on_delete=models.CASCADE)
    # 用户性别
    gender = models.CharField(verbose_name="性别", max_length=5, choices=C_GENDER, default="1")
    # 用户年龄
    age = models.IntegerField(verbose_name="年龄", default=0)
    # 联系方式
    phone = models.CharField(verbose_name="手机", max_length=15, null=True, blank=True)
    # 所述组织
    org = models.CharField(verbose_name="组织", max_length=200, null=True, blank=True)
    # 个人介绍
    intro = models.TextField(verbose_name="简介", null=True, blank=True)

3.创建表单模块

在blog项目中创建forms.py模块,添加代码:

from django import forms
from django.contrib.auth.models import User


class UserRegisterForm(forms.ModelForm):
    """用户注册表单"""
    confirm = forms.CharField(label='确认密码', min_length=6, max_length=18)

    class Meta:
        model = User
        fields = ['username', 'password', 'confirm']

    def clean_username(self):
        """自定义用户名称验证规则"""
        u_list = User.objects.filter(username=self.cleaned_data['username'])
        if len(u_list) > 0:
            raise forms.ValidationError("账号已经存在,请使用其他账号注册")
        return self.cleaned_data['username']

    def clean_confirm(self):
        """自定义确认密码验证规则"""
        if self.cleaned_data['password'] != self.cleaned_data['confirm']:
            raise forms.ValidationError("两次密码输入不一致")
        return self.cleaned_data['confirm']

4.用户登录业务逻辑

编辑blog/views.py模块,代码如下:

from django.shortcuts import render, redirect, get_object_or_404, get_list_or_404
from django.urls import reverse
from django.contrib.auth import authenticate, login, logout
from django.views.decorators.http import require_GET
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.models import User

from . import forms
from .models import Article


def user_login(request):
    """用户登录"""
    if request.method == "GET":
        return render(request, 'blog/login.html', {})
    elif request.method == "POST":
        # 接受登录数据
        username = request.POST.get("username")
        password = request.POST.get("password")

        # 验证表单数据
        user = authenticate(request, username=username, password=password)
        if user and user.is_active:
            login(request, user)
            # 返回首页
            return redirect(reverse("blog:user_index"))
        else:
            return render(request, 'blog/login.html', {'msg_code': "-1",
                                                       'msg_info': "账号或者密码有误."})


def user_logout(request):
    """用户退出"""
    logout(request)
    return redirect(reverse("blog:user_index"))


def user_register(request):
    """用户注册"""
    if request.method == "GET":
        return render(request, "blog/register.html", {})
    elif request.method == "POST":
        # 接收用户注册数据
        form_register = forms.UserRegisterForm(request.POST)
        # 判断注册数据有效性
        if form_register.is_valid():
            # 验证通过,保存注册数据
            User.objects.create_user(username=form_register.instance.username,
                                     password=form_register.instance.password)
            # 跳转登录界面
            return redirect(reverse("blog:user_login"), kwargs={"msg_code": "0",
                                                                "msg_info": "账号注册成功"})
        else:
            return render(request, "blog/register.html", {"form": form_register,
                                                          "msg_code": "-1",
                                                          "msg_info": "注册失败"})

def user_index(request):
    # 查看文章列表
    articles = Article.objects.all()
    return render(request, "blog/index.html", {"articles": articles})

5.添加网页文件

创建blog/templates/blog文件夹,添加网页文件

添加基础模板文件base.html,其他文件继承它:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>身份认证-权限管理-{% block title %}{% endblock %}</title>
</head>
<body>
{% block page_body %}
{% endblock %}
</body>
</html>

添加登录网页文件login.html:

{% extends 'blog/base.html' %}

{% block title %}个人博客用户登录{% endblock %}

{% block page_body %}
    <h2>会员登录</h2>
    <p>
    {{ form.errors }}
    {{ msg_info }}
    </p>
    <form action="{% url 'blog:user_login' %}" method="POST">
        {% csrf_token %}
        <label for="username">账号: </label>
        <input type="text" name="username" id="username">
        <span style="color:red">{{ form.errors.username }}</span>
        <br />
        <label for="password">密码: </label>
        <input type="password" name="password" id="password">
        <span style="color:red">{{ form.errors.password }}</span>
        <br />
        <input type="submit" value="登录">
    </form>
{% endblock %}

添加注册网页文件register.html:

{% extends 'blog/base.html' %}

{% block title %}个人博客用户注册{% endblock %}

{% block page_body %}
    <h2>新用户注册
        <small>{{ form.errors }}</small>
    </h2>
    <hr>
    <form action="{% url 'blog:user_register' %}" method="POST">
        {% csrf_token %}
        <label for="username">账号:</label>
        <input type="text" name="username" id="username"><br />
        <label for="password">密码:</label>
        <input type="password" name="password" id="password"><br />
        <label for="confirm">确认密码:</label>
        <input type="password" name="confirm" id="confirm"><br />
        <input type="submit" value="提交注册">
    </form>
{% endblock %}

添加首页网页文件index.html:

{% extends 'blog/base.html' %}

{% block title %}个人博客首页{% endblock %}

{% block page_body %}
    <h2>个人博客首页
        <small>尊敬的用户{{ request.user }},欢迎访问本系统</small>
    </h2>
    <hr>
    <a href="{% url 'blog:user_logout'%}">退出</a>
    <p>博客网页内容</p>
    <ul>
        <li><a href="{% url 'blog:article_publish' %}">发表文章</a></li>
    </ul>
    <ul>
    {% for article in articles %}
        <li>标题:<a href="{% url 'blog:article_detail' article.id %}">{{ article.title }}</a> -- 作者:{{ article.author.username }} --
            <a href="{% url 'blog:article_delete' article.id %}">删除</a>  <a href="{% url 'blog:article_update' article.id %}">编辑</a></li>
    {% endfor %}
    </ul>
{% endblock %}

6.添加路由

编辑blog/urls.py

from django.urls import path
from django.views.generic import TemplateView

from . import views

app_name = 'blog'

urlpatterns = [
    path("perm_refused/", TemplateView.as_view(template_name='blog/permission_refused.html'), name="perm_refused"),
    path("login/", views.user_login, name="user_login"),
    path("logout/", views.user_logout, name="user_logout"),
    path("register/", views.user_register, name="user_register"),
    path("", views.user_index, name="user_index"),
]

7.启动项目

访问http://127.0.0.1:8000/blog/register,先注册一个用户,容纳后访问首页http://127.0.0.1:8000/blog/让先登录,登录后到了博客首页,如下:
在这里插入图片描述

2.权限管理架构

权限管理是指用户对网站资源的访问管理操作,对于不同的用户身份,对资源的访问方式应有所区分。在用户访问资源时,需要先判断是否有权限。

对于很多用户,可能有级别相似的权限,权限设置造成大量冗余,于是引入角色,通过角色对权限进行管理,用户拥有某个角色,相当于拥有该角色的权限。

2.1 权限相关数据模型

对于整个权限管理,Django内置了用户模块、角色模块、权限模块来尽心管理:

  • django.contrib.auth.models.User:用户模块中的用户类型
  • django.contrib.auth.models.Group:用户模块中的用户组类型
  • django.contrib.auth.models.Permission:用户模块中的权限类型

2.2 权限相关功能函数

Django内置的django.contrib.auth模块中,除了有上面用于描述实力的模块,也封装了用于身份认证和权限管理的函数。

  1. django.contrib.auth.authenticate:用户身份认证函数,传入用户身份信息,默认参数为账号、密码。如果认证通过,返回当前用户对象,否则返回None。
  2. django.contrib.auth.login:用户身份状态记录函数,传入请求对象和需要记录的用户对象。该函数负责将用户信息记录到所属的会话对象(如session)中存储。
  3. django.contrib.auth.loglout:登录状态清除函数,传入请求对象,将记录在当前请求所属会话中的用户对象user清空并设置匿名用户Anonymous。
  4. django.contrib.auth.decorators.login_required:用户身份认证资源访问装饰器,验证用户是否通过身份认证,如果验证通过,则允许该用户访问装饰器下面的函数,否则跳转到login_url参数指定的路径。如果不提供该参数,则自动获取配置文件里的LOGIN_UTL配置路径。
  5. django.contrib.auth.decorators.permission_required:数据资源访问装饰器,验证当前用户是否拥有制指定权限。如果验证通过,则允许该用户访问装饰器下面的函数,否则跳转到login_url参数指定的路径。如果不提供该参数,则自动获取配置文件里的LOGIN_UTL配置路径。

另外再第七章视图处理函数中,还有require_GET、require_POST、require_http_method等装饰器,用于限制请求类型。

2.3 权限分配函数

用户通过身份认证后,可以在操作过程中根据实际场景进行用户组和用户权限的独立分配,相关函数如下:

  1. user.groups.set([group_list]):为用户设置用户组,可以设置到多个组里。
  2. user.groups.add(group1, group2, ...):为用户设置用户组。
  3. user.groups.remove(group1, group2, ...):将当前用户从指定用户组删除。
  4. user.groups.clear():把用户从所有的用户组删除。
  5. user.user_permissions.set([permission_list]):为用户设置权限,可以指定多个。
  6. user.user_permissions.add(perm1, perm2, ...):为用户设置权限。
  7. user.user_permissions.remove(perm1, perm2, ...):删除用户指定权限。
  8. user.user_permissions.clear():删除用户所有权限。

2.4 权限设置

在Django中,会自动设置在配置INSTALLED_APPS中的app内部模型类的默认访问权限,有增删改查4种,如下:

  • add:如blog子项目的Article模型,设置了权限blog.add_article;
  • change:如blog子项目的Article模型,设置了权限blog.change_article;
  • delete:如blog子项目的Article模型,设置了权限blog.delete_article;
  • view:如blog子项目的Article模型,设置了权限blog.view_article;

使用上一节perm_demo项目,添加模型类Article,如下:

class Article(models.Model):
    """文章类型"""
    # 文章主键编号
    id = models.UUIDField(verbose_name="文章编号", primary_key=True, default=uuid4)
    # 文章标题
    title = models.CharField(verbose_name="文章编号", max_length=20)
    # 文章内容
    content = models.TextField(verbose_name="文章内容")
    # 发布时间
    publish_time = models.DateTimeField(verbose_name="发表时间", auto_now_add=True)
    # 修改时间
    update_time = models.DateTimeField(verbose_name="修改时间", auto_now=True)
    # 文章作者
    author = models.ForeignKey(verbose_name="作者", to=User, on_delete=models.CASCADE)

    def get_absolute_url(self):
        return reverse("blog:article_detail", kwargs={"article_id": self.id})

登录后台管理系统访问http://127.0.0.1:8000/admin/auth/user/4/change/可查看所有的权限,如下:
在这里插入图片描述

3.资源访问管理

可以通过装饰器@permission_required进行权限认证。

以上面perm_demo项目为例,编辑blog/views.py,在与文章相关的视图处理函数中添加权限认证操作:

@permission_required("blog.view_article")
@login_required
@require_GET
def user_index(request):
    # 查看文章列表
    print("index")
    articles = Article.objects.all()
    print(request.user.get_all_permissions())
    print(request.user.has_perm("blog.view_article"))
    return render(request, "blog/index.html", {"articles": articles})


@login_required
@permission_required("blog.add_article", login_url='/blog/perm_refused/')
def article_publish(request):
    """发表文章"""
    if request.method == "GET":
        return render(request, "blog/article_publish.html", {})
    elif request.method == "POST":
        # 接受文章数据
        form = forms.ArticleForm(request.POST)
        # 验证文章数据是否正确
        if form.is_valid():
            # 发表文章
            form.save()
            # 跳转到文章详情页面
            return redirect(form.instance)
        return render(request, "blog/article_publish.html", {'form': form})


@permission_required("blog.view_article", login_url='/blog/perm_refused/')
@require_GET
def article_detail(request, article_id):
    """查看文章"""
    if request.method == "GET":
        article = get_object_or_404(Article, pk=article_id)
        return render(request, "blog/article_detail.html", {"article": article})


@login_required
@permission_required("blog.change_article", login_url='/blog/perm_refused/')
def article_update(request, article_id):
    """修改文章"""
    article = get_object_or_404(Article, pk=article_id)
    if request.method == "GET":
        return render(request, "blog/article_update.html", {"article": article})
    elif request.method == "POST":
        # 接受文章数据
        form = forms.ArticleForm(request.POST, instance=article)
        # 验证文章数据是否正确
        if form.is_valid():
            print("文章修改数据验证通过")
            # 存储文章数据
            form.save()
            # 跳转到文章详情页面
            return redirect(form.instance)
        return render(request, "blog/article_update.html", {'form': form})


@login_required
@permission_required("blog.delete_article", login_url='/blog/perm_refused/')
def article_delete(request, article_id):
    """删除文章"""
    # 查询文章数据
    article = get_object_or_404(Article, pk=article_id)
    # 删除文章
    article.delete()
    # 返回首页
    return redirect(reverse("blog:user_index"))

上面的代码中看到,访问首页(user_index视图函数)和文章详情(article_detail视图函数)都需要当前用户拥有blog.view_article权限;发表文章(article_publish视图函数)需要当前用户拥有blog.add_article权限;修改文章(article_update视图函数)需要当前用户拥有blog.change_article权限;同理删除需要blog.delete_article权限。

上面的操作方式可以满足大部分需求,到那时如果有定制化的权限架构,可参考Django的设计进行实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/154379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022 CNCC 中国计算机大会参会总结

前言 第 19 届 CNCC 于2022年12月8-10日召开&#xff0c;本届大会为期三天&#xff0c;首次采取全线上举办形式&#xff0c;主题为“算力、数据、生态”&#xff0c;重点在保持多样性、聚焦热点前沿话题、平衡学术界和产业界参与等维度展开讨论。大会由CCF会士、中国科学院院士…

【SpringBoot】一文带你入门SpringBoot

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;【Spring】 &#x1f96d;本文内…

【职场进阶】做好项目管理,先从明确职责开始

优秀的项目管理一定是高效协调各方资源、反馈及时、调整迅速的。 同时可以做到让参与各方在整个项目过程中张弛有序、愉快合作&#xff0c;最终实现产品项目的效益最大化。 那什么是项目呢&#xff1f; 项目是为向客户提供独特的产品或服务而进行的临时性任务&#xff0c;项目有…

TypeScript 对象key为number时的坑

首先在js的对象中有一个设定&#xff0c;就是对象的key可以是字符串&#xff0c;也可以是数字。 不论key是字符串还是数字&#xff0c;遍历对象key的时候&#xff0c;这个key会变成字符串 通过[] 操作符访问key对应值时候&#xff0c;不论是数字还是字符串都转成了 字符串的k…

Chromedriver安装教程

第一步 查看你当前Chrome浏览器的版本&#xff0c;如下图所示&#xff1a; 第二步 查看当前Chrome浏览器的版本号&#xff0c;如下图所示,版本 108.0.5359.125&#xff08;正式版本&#xff09; &#xff08;64 位&#xff09;中的&#xff0c;108就是我们的版本号。 第三…

VTK-PointPlacer

前言&#xff1a;本博文主要研究VTK中点转换到曲面上的应用&#xff0c;相关的接口为vtkPolygonalSurfacePointPlacer&#xff0c;为深入研究将基类vtkPointPlacer开始讲解。主要应用为在PolyData表面进行画线。 vtkPointPlacer 描述&#xff1a;将2D display位置转换为世界坐…

ospf知识点汇总

OSPF &#xff1a; 开放式最短路径优先协议使用范围&#xff1a;IGP 协议算法特点&#xff1a; 链路状态型路由协议&#xff0c;SPF算法协议是否传递网络掩码&#xff1a;传递网络掩码协议封装&#xff1a;基于IP协议封装&#xff0c;协议号为 89一.OSPF 特点1.OSPF 是一种典型…

基于javaweb(springboot+mybatis)网上酒类商城项目设计和实现以及文档报告

基于javaweb(springbootmybatis)网上酒类商城项目设计和实现以及文档报告 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏…

【Linux】Linux项目自动化构建工具—make/Makefile

目录一.什么是make/MakefileMakefilemake二.Makefile逻辑1.简单依赖2.复杂依赖三.make指令1.make的使用2.clean清理3.伪目标4.make如何确定是否编译访问时间的影响修改时间的影响一.什么是make/Makefile Makefile 在Windows下&#xff0c;我们使用VS、VS Code这些ide编写C/C程…

MySQL的客户端/服务器架构

以我们平时使用的微信为例&#xff0c;它其实是由两部分组成的&#xff0c;一部分是客户端程序&#xff0c;一部分是服务器程序。客户端可能有很多种形式&#xff0c;比如手机APP&#xff0c;电脑软件或者是网页版微信&#xff0c;每个客户端都有一个唯一的用户名&#xff0c;就…

赶紧收藏 | 50个超实用微信小程序,巨好用|||内含免费配音软件

现在App太多了&#xff0c;想用的功能都要下载&#xff0c;但是手机有258g内存不允许这么放肆呀&#xff0c;只能挖掘不占用存的方法了&#xff0c;小程序就解决了这个痛&#xff0c;节省内存&#xff0c;让手机不再卡顿&#xff0c;打游戏也舒服.给大家整理了50个很好用的小程…

【阶段三】Python机器学习11篇:机器学习项目实战:KNN(K近邻)回归模型

本篇的思维导图: 项目实战(KNN回归模型) K近邻算法回归模型则将离待预测样本点最近的K个训练样本点的平均值进行待预测样本点的回归预测。 项目背景 K近邻除了能进行分类分析,还能进行回归分析,即预测连续变量,此时的KNN称为K近邻回归模型。回归问题是一类…

synchronized 重量级锁分析

synchronized 重量级锁分析 1. 背景 在JDK1.6以前&#xff0c;synchronized 的工作方式都是这种重量级的锁。它的实现原理就是利用 kernel 中的互斥量,mutex。主要是内核中的mutex 能够保证它是一个互斥的量。如果线程1拿到了 mutex,那么线程2就拿不到了。这是内核帮我们保证…

二十三、Kubernetes中Pod控制器分类、ReplicaSet(RS)控制器详解

1、概述 Pod是kubernetes的最小管理单元&#xff0c;在kubernetes中&#xff0c;按照pod的创建方式可以将其分为两类&#xff1a; 自主式pod&#xff1a;kubernetes直接创建出来的Pod&#xff0c;这种pod删除后就没有了&#xff0c;也不会重建 控制器创建的pod&#xff1a;kub…

小米应用商店APP侵权投诉流程

目录一、官方指引二、侵权投诉流程1.侵权投诉通知和反通知流程2.受理渠道3.权利人发起侵权通知邮件一、官方指引 https://dev.mi.com/distribute/doc/details?pId1142 二、侵权投诉流程 1.侵权投诉通知和反通知流程 2.受理渠道 对外邮箱&#xff1a;developerxiaomi.com …

云呐|固定资产盘点APP

如果工人想做好他们的工作&#xff0c;他们想做好他们的工作。目前&#xff0c;行政事业单位对固定资产管理进行一物一卡一码管理&#xff0c;根据条形码粘贴和扫码总结&#xff0c;是目前科学完善的总结方法&#xff0c;具有快速、高效、准确的特点。对于这种方法&#xff0c;…

5.6、TCP超时重传时间的选择

超时重传时间的选择是 TCP 最复杂的问题之一 1、超时重传时间RTO的选取 假设主机 A 给主机 B 发送 TCP 数据报文段 000&#xff0c;并记录下当前的时间 主机 B 收到后&#xff0c;给主机 A 发送相应的确认报文段 主机 A 收到确认报文段后&#xff0c;记录下当前的时间 那么…

为什么BI仪表板的共享功能对企业如此重要?

随着大数据的发展&#xff0c;企业逐渐将数据作为其决策的重要组成部分&#xff0c;共享商业智能 (BI) 仪表板显得越来越重要。例如&#xff0c;在员工之间共享BI仪表板&#xff0c;不仅可以做出更好的数据驱动决策&#xff0c;还可以更好地提高工作透明度和问责制&#xff0c;…

Golang时间处理容易踩坑,小心损失百万

简介 在各个语言之中都有时间类型的处理&#xff0c;因为这个地球是圆的&#xff08;我仿佛在讲废话&#xff09;&#xff0c;有多个时区&#xff0c;每个时区的时间不一样&#xff0c;在程序中有必要存在一种方式&#xff0c;或者说一种类型存储时间&#xff0c;还可以通过一系…

手写RPC框架第8版-通过SpringBoot-Starter接入SpringBoot

源代码地址&#xff1a;https://github.com/lhj502819/IRpc/tree/v9 系列文章&#xff1a; 注册中心模块实现路由模块实现序列化模块实现过滤器模块实现自定义SPI机制增加框架的扩展性的设计与实现基于线程和队列提升框架并发处理能力框架容错性相关设计通过SpringBoot-Starte…