Python入门自学进阶-Web框架——29、DjangoAdmin项目应用-整表只读、自定义用户认证

news2025/2/28 20:25:43

一、整表只读

对于readonly_fields是对单个字段设置只读,现在要对整个表使用只读,也做成可配置的。在自己项目的admin.py中进行配置,如在mytestapp_admin.py中对Customer进行整表只读配置,在基类BaseAdmin中增加readonly_table = False,即默认所有表都是可读写的,在CustomerAdmin中配置readonly_table = True。

此时,前端,在修改和添加页面中,将对应的保存、删除按钮隐去,使前端没有保存、删除按钮:

{% if not admin_class.readonly_table %}
                    <div class="form-group row" >
                        <div class="col-sm-2"><button type="button" class="btn btn-danger pull-left"><a href="/mytestapp/plcrm/customer/{{ form_obj.instance.id }}/delete/">Delete</a></button></div>
                        <div class="col-sm-3"></div>
                        <div class="col-sm-7  pull-right">
                            <button type="submit" class="btn btn-success pull-right">Save</button>
                        </div>
                    </div>
{% endif %}

在记录查看页面中将Add按钮也隐去:

{% if not admin_class.readonly_table %}
            <div style="float: right"><a class="pull-right" href="{{ url_path }}add/">Add</a> </div>
{% endif %}

前端的隐去是可以通过技术手段再加上的,所以还需要在后端做验证。

对于修改和增加,在默认验证中,如果判断是只读表,直接抛出错误,在create_model_form中的default_clean函数中,增加:

        if admin_class.readonly_table:
            raise ValidationError(
                        _('Table is readonly,cannot be Modified or Add'),
                        code='invalid',)

对于删除,在视图函数中进行判断:

def rec_obj_delete(req,app_name,table_name,id_num):
    admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    model_obj = admin_class.model.objects.filter(id=id_num)
    print('{{{{{{{{',model_obj)
    if admin_class.readonly_table:   # 如果配置了只读表,不能删除,添加错误显示信息
        error = {'readonlyerror':"Table is readonly,[%s] cannot be deleted!"%(model_obj)}
    else:
        error = {}
    if req.method == "POST":
        if not admin_class.readonly_table:   # 判断是否只读表,不是,可以删除,否则不能删除
            model_obj.delete()
            return redirect("/mytestapp/%s/%s/" %(app_name,table_name))
    return render(req,"mytestapp/rec_delete.html",{"model_obj":model_obj,'error':error})

然后在前端页面中加上{{ error }},显示错误信息就可以了。

对于自定义的动作中的删除,再对应的视图函数中加上判断:

 error = ""
    if req.method == "POST":
        if not admin_class.readonly_table:
            select_ids = req.POST.get('selected_ids')
            select_ids = select_ids.split(',')
            actions = req.POST.get('myaction')
            action_obj = getattr(admin_class,actions)
            models_objs = admin_class.model.objects.filter(id__in=select_ids)
            action_obj(admin_class,req,models_objs)
        else:
            error = 'readonlyerror:Table is readonly, cannot be deleted!'

当然,对于自定制的动作,本身就是特殊的操作,也可以根据需要不进行只读表判断,可以进行正常删除。

实现URL跳转:

 对于菜单项,如客户首页,想跳转到前面写的mytestapp/plcrm/customer项,在对应的页面中增加:

{% block page-content %}
    <script>
    window.location.assign("{% url 'table_objs' 'plcrm' 'customer' %}");
    </script>
{% endblock %}

点击后自动跳转的相应页面。

二、自定义用户认证

项目中使用的用户,是借助于admin中的User,并自己定义了一个UserProfile,进行了一对一关联,在自定义的UserProfile中对用户进行自定义配置。这种方法的弊端是在添加用户时,需要先在User表中添加一条,再在UserProfile中添加,两次操作,很麻烦。

现在要写一个model,模拟django.contrib.auth.models.User,即admin中的模型,并最终使用自定义的这个模型来做用户验证,即实现User的作用。

首先模拟User做一个新的模型,User是继承了AbstractUser:class User(AbstractUser),而AbstractUser又继承了AbstractBaseUser, PermissionsMixin,即class AbstractUser(AbstractBaseUser, PermissionsMixin),AbstractBaseUser定义用户,PermissionsMixin定义权限。我们自定义的模型,也继承AbstractBaseUser, PermissionsMixin:

admin原来的用户管理:

登录,注意是账户名是:Username

 

用户表是在AUTHENTICATION AND AUTHORAZATION中

 

 用户相关信息:



 对应的User定义: class User(AbstractUser),而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)



class AbstractBaseUser(models.Model):
    password = models.CharField(_('password'), max_length=128)
    last_login = models.DateTimeField(_('last login'), blank=True, null=True)

    is_active = True

    REQUIRED_FIELDS = []

    # Stores the raw password if set_password() is called so that it can
    # be passed to password_changed() after the model is saved.
    _password = None

    class Meta:
        abstract = True

    def __str__(self):
        return self.get_username()

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        if self._password is not None:
            password_validation.password_changed(self._password, self)
            self._password = None

    def get_username(self):
        """Return the username for this User."""
        return getattr(self, self.USERNAME_FIELD)

    def clean(self):
        setattr(self, self.USERNAME_FIELD, self.normalize_username(self.get_username()))

    def natural_key(self):
        return (self.get_username(),)

    @property
    def is_anonymous(self):
        """
        Always return False. This is a way of comparing User objects to
        anonymous users.
        """
        return False

    @property
    def is_authenticated(self):
        """
        Always return True. This is a way to tell if the user has been
        authenticated in templates.
        """
        return True

    def set_password(self, raw_password):
        self.password = make_password(raw_password)
        self._password = raw_password

    def check_password(self, raw_password):
        """
        Return a boolean of whether the raw_password was correct. Handles
        hashing formats behind the scenes.
        """
        def setter(raw_password):
            self.set_password(raw_password)
            # Password hash upgrades shouldn't be considered password changes.
            self._password = None
            self.save(update_fields=["password"])
        return check_password(raw_password, self.password, setter)

    def set_unusable_password(self):
        # Set a value that will never be a valid hash
        self.password = make_password(None)

    def has_usable_password(self):
        """
        Return False if set_unusable_password() has been called for this user.
        """
        return is_password_usable(self.password)

    def _legacy_get_session_auth_hash(self):
        # RemovedInDjango40Warning: pre-Django 3.1 hashes will be invalid.
        key_salt = 'django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash'
        return salted_hmac(key_salt, self.password, algorithm='sha1').hexdigest()

    def get_session_auth_hash(self):
        """
        Return an HMAC of the password field.
        """
        key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"
        return salted_hmac(
            key_salt,
            self.password,
            # RemovedInDjango40Warning: when the deprecation ends, replace
            # with:
            # algorithm='sha256',
            algorithm=settings.DEFAULT_HASHING_ALGORITHM,
        ).hexdigest()

    @classmethod
    def get_email_field_name(cls):
        try:
            return cls.EMAIL_FIELD
        except AttributeError:
            return 'email'

    @classmethod
    def normalize_username(cls, username):
        return unicodedata.normalize('NFKC', username) if isinstance(username, str) else username




class PermissionsMixin(models.Model):
    """
    Add the fields and methods necessary to support the Group and Permission
    models using the ModelBackend.
    """
    is_superuser = models.BooleanField(
        _('superuser status'),
        default=False,
        help_text=_(
            'Designates that this user has all permissions without '
            'explicitly assigning them.'
        ),
    )
    groups = models.ManyToManyField(
        Group,
        verbose_name=_('groups'),
        blank=True,
        help_text=_(
            'The groups this user belongs to. A user will get all permissions '
            'granted to each of their groups.'
        ),
        related_name="user_set",
        related_query_name="user",
    )
    user_permissions = models.ManyToManyField(
        Permission,
        verbose_name=_('user permissions'),
        blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="user_set",
        related_query_name="user",
    )

    class Meta:
        abstract = True

    def get_user_permissions(self, obj=None):
        """
        Return a list of permission strings that this user has directly.
        Query all available auth backends. If an object is passed in,
        return only permissions matching this object.
        """
        return _user_get_permissions(self, obj, 'user')

    def get_group_permissions(self, obj=None):
        """
        Return a list of permission strings that this user has through their
        groups. Query all available auth backends. If an object is passed in,
        return only permissions matching this object.
        """
        return _user_get_permissions(self, obj, 'group')

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

    def has_perm(self, perm, obj=None):
        """
        Return True if the user has the specified permission. Query all
        available auth backends, but return immediately if any backend returns
        True. Thus, a user who has permission from a single auth backend is
        assumed to have permission in general. If an object is provided, check
        permissions for that object.
        """
        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        # Otherwise we need to check the backends.
        return _user_has_perm(self, perm, obj)

    def has_perms(self, perm_list, obj=None):
        """
        Return True if the user has each of the specified permissions. If
        object is passed, check if the user has all required perms for it.
        """
        return all(self.has_perm(perm, obj) for perm in perm_list)

    def has_module_perms(self, app_label):
        """
        Return True if the user has any permissions in the given app label.
        Use similar logic as has_perm(), above.
        """
        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        return _user_has_module_perms(self, app_label)

在AbstractUser中定义了username、first_name、last_name、email、is_staff、is_active、date_joined字段,在AbstractBaseUser中定义了password、last_login字段,在PermissionsMixin中定义了is_superuser、groups 、user_permissions字段,对应起来就是Admin的用户管理界面中的内容。

先定义一个自己的用户表,修改原来的plcrm中的UserProfile:

class UserProfile(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(verbose_name='邮件地址',max_length=255,unique=True)
    name = models.CharField(max_length=32,verbose_name="账户的用户名")
    roles = models.ManyToManyField("Role", blank=True, verbose_name='用户对应的角色')
    dateofcreate = models.DateTimeField(verbose_name='创建日期')
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'   # 指定哪个字段作为登录的账户名,这里指定email作为登录的账户名
    REQUIRED_FIELDS = ['name'] # 指定哪些字段是必须的,即必须填写

    # objects = MyUserProfileManager()

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin
    class Meta:
        verbose_name_plural ="账号表"

 修改好后,删除了原来的数据库重建,然后重新生成表,如下出现错误:

 这时,在项目的settings.py中增加如下配置:

AUTH_USER_MODEL = 'plcrm.UserProfile'

这一步是指定系统使用哪个模型来做用户表,默认是django.contrib.auth.models.User,要使用自己定义的,就要在配置中指定。

配置上面语句后,就可以正常makemigrations和migrate了。

成功后,创建超级用户:

提示: AttributeError: 'Manager' object has no attribute 'get_by_natural_key',这就要涉及定义用户表中的objects = xxx这一句,

设置: objects = UserProfileManager()

然后创建UserProfileManager类

class UserProfileManager(BaseUserManager):
    def create_user(self, email, name, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            name=name,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, name, password=None):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(
            email,
            password=password,
            name=name,
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

这个管理类提供了两个方法,create_user和create_superuser,就是用来创建普通用户和创建超级用户的,在manage.py createsuperuser,就应该调用这个类的方法。其参数是email,就是我们指定的账户名,是必须的,第二个参数是name,是我们在UserProfile中设置的必填字段,然后是password密码。

 注意,这时输入的就是邮件地址,作为账户名。

此时,再登录:

进入后:

 

 AUTHENTICATION AND AUTHORAZATION应用中已经没有Users表了,现在使用的是我们自定义的账号表(这里显示的是UserProfile的verbose_name_plural的值)。

 点击这个链接Add,增加用户:

 

可以看到,password、邮件地址和账户的用户名是必填的,粗体提示了,有问题的是密码应该是密码输入框,这里显示明文了。并且保存后,密码是以输入的明文保存的,应该是密文 。

上面是没有Admin配置类,默认全部字段显示,进行个性化定制:

在项目的admin.py中进行配置,

# ###########以下是使用自定义UserProfile在这里必须有的一些代码####################
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.core.exceptions import ValidationError
from django.utils.translation import gettext, gettext_lazy as _
from plcrm.models import UserProfile

class UserProfileCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
        fields, plus a repeated password."""
    password1 = forms.CharField(label='Password',widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation',widget=forms.PasswordInput)

    class Meta:
        model = UserProfile
        fields = ('email','name')

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

class UserProfileChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    disabled password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = UserProfile
        fields = ('email', 'password', 'name', 'is_active', 'is_admin')
    

class UserProfileAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserProfileChangeForm
    add_form = UserProfileCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('email', 'name', 'is_admin')
    list_filter = ('is_admin',)
    fieldsets = (    # 这个字段,是点击已有的用户,显示的界面字段,可进行修改
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('name',)}),
        ('Permissions', {'fields': ('is_admin','is_active','groups','user_permissions')}),
        ('roles', {'fields': ('roles',)}),
        ('Date:', {'fields': ('dateofcreate',)}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (    # 这个字段是配置增加用户时,界面显示的字段
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'name', 'password1', 'password2','dateofcreate'),
        }),
        ('Roles',{
            'classes':('wide',),
            'fields':('roles',)
        }),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ()
# ####################################

# 然后注册
admin.site.register(models.UserProfile,UserProfileAdmin)  # 配置上UserProfileAdmin

如上的代码后,就可以按个性化的界面进行用户管理,如创建用户,修改用户等,但是,重置用户密码没有实现,缺少了重置密码的链接,通过对Django的Admin的源代码查看,对UserProfileChangeForm进行完善:

class UserProfileChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    disabled password hash display field.
    """
    password = ReadOnlyPasswordHashField(label=_("Password"),
        help_text=_(
            'Raw passwords are not stored, so there is no way to see this '
            'user’s password, but you can change the password using '
            '<a href="{}">重置密码</a>.'    # 这个链接是进行密码重置的链接地址,需要在__init__中初始化
        ),)

    class Meta:
        model = UserProfile
        fields = ('email', 'password', 'name', 'is_active', 'is_admin')
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        password = self.fields.get('password')
        if password:
            password.help_text = password.help_text.format('../password/')   # 这是对密码给出的帮助中的链接的赋值
        user_permissions = self.fields.get('user_permissions')
        if user_permissions:
            user_permissions.queryset = user_permissions.queryset.select_related('content_type')

在ReadOnlyPasswordHashField这个函数中增加help_text,其中有一个链接,在__init__中对这个链接进行赋值,可以转到重置密码页面,进行密码的重置。这里因为是继承过来的,__init__()函数可以不写,这里主要是给出其实现的细节,弄清楚原理。

这样,我们就可以对UserProfile进行个性化的扩展,需要什么字段,就添加什么字段,一般是角色、组、机构等一起配置。

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

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

相关文章

juc-1-进程/线程/创建线程代码

1 场景&#xff1a; 1&#xff1a;执行的任务&#xff0c;短而快。不能是很耗时的任务。 2&#xff1a;异步写日志(日志框架底层就是)。 3&#xff1a;异步发送邮件&#xff0c;短信。 用MQ 最好。 4&#xff1a;多线程下载 2 进程与线程 进程&#xff1a; 进程&#xff1…

Centerfusion算法环境配置及模型训练

Centerfusion算法环境配置及模型训练概述1. 配置conda环境1.1 新建conda环境1.2 安装cuda1.3 安装cudnn1.4 安装pytorch1.5 安装cocoapi2. 配置Centerfusion2.1 克隆CenterFusion的github库2.2 安装依赖包2.3 安装DCNv22.4 下载nuscenes-devkit包3. 数据集准备3.1 下载数据集3.…

细粒度图像分类论文研读-2019

文章目录Cross-X Learning for Fine-Grained Visual Categorization&#xff08;by end-to-end&#xff09;AbstractIntroductionApproachPreliminariesCross- Category Cross-Semantic RegularizerCross-Layer RegularizerOptimizationLearning a Mixture of Granularity-Spec…

公司刚来的京东架构师:看完我写的 spring 笔记,甩给了我一份文档

Spring 是分层的 full-stack&#xff08;全栈&#xff09; 轻量级开源框架&#xff0c;以 IoC 和 AOP 为内核&#xff0c;提供了展现层 SpringMVC 和业务层事务管理等众多的企业级应⽤技术&#xff0c;还能整合开源世界众多著名的第三⽅框架和类库&#xff0c;已经成为使⽤最多…

优维助力国内某省级商业银行同城异地灾备自动化建设

银监会在《商业银行数据中心监管指引》中明确要求“商业银行每年至少进行一次重要信息系统专项灾备切换演练&#xff0c;每三年至少一次重要信息系统全面灾备切换演练&#xff0c;以真实业务接管为目标&#xff0c;验证灾备系统有效接管生产系统与安全回切的能力&#xff0c;并…

SpringSecurity概念以及整合ssm框架

基本概念 Spring中提供安全认证服务的框架&#xff0c;认证&#xff1a;验证用户密码是否正确的过程&#xff0c;授权&#xff1a;对用户能访问的资源进行控制 用户登录系统时我们协助 SpringSecurity 把用户对应的角色、权限组装好&#xff0c;同时把各个资源所要求的权限信息…

毕业设计-基于大数据技术的旅游推荐系统-python

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

前端基础(十一)_Float浮动、清除浮动的几种方法

浮动 1、什么是浮动&#xff1f; 目的&#xff1a;为了让多个块级元素在同一行显示&#xff1b; 文档流&#xff1a;可显示的对象在排列时所占的位置&#xff1b; 浮动&#xff1a;使元素脱离正常的文档流&#xff0c;按照指定的顺序&#xff0c;方向发生移动&#xff0c;直到…

疫情下景区管理

开发工具(eclipse/idea/vscode等)&#xff1a;idea 数据库(sqlite/mysql/sqlserver等)&#xff1a;mysql 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;模块划分&#xff1a;公告类型、公告信息、用户信息、用户咨询、地区信息、景区信息、景区开放、景区预约、统计…

【Flask框架】——17 Flask蓝图

在一个Flask 应用项目中&#xff0c;如果业务视图过多&#xff0c;可否将以某种方式划分出的业务单元单独维护&#xff0c;将每个单元用到的视图、静态文件、模板文件等独立分开&#xff1f; 例如从业务角度上&#xff0c;可将整个应用划分为用户模块单元、商品模块单元、订单…

应急响应-windows/Linux主机加固

windows/Linux主机加固 1,账户安全 首先要确保电脑上的账户均为经常使用的账户&#xff0c;要禁止Guest用户&#xff0c;禁用其他无用账户&#xff0c;一段时间后无反馈即可删除&#xff0c;同时要留意是否有隐藏账户存在。 查看本地用户和组&#xff1a;右键此电脑>计算机管…

PG::FunboxEasy

nmap -Pn -p- -T4 --min-rate1000 192.168.58.111 nmap -Pn -p 22,80,33060 -sCV 192.168.58.111 查看80端口的页面&#xff0c;未发现可用信息。 对路径进行爆破 gobuster dir -u http://192.168.58.111/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt…

Vue3 —— 使用Vite配置环境变量

文章目录 一、为什么要配置环境变量?二、在Vite中配置环境变量 1.环境变量和模式2.环境变量3.生产环境替换4.env 文件总结一、为什么要配置环境变量? 在一个产品的前端开发过程中&#xff0c;一般来说会经历本地开发、测试脚本、开发自测、测试环境、预上线环境&#xff0c;然…

后疫情时代,VR全景创业的应用场景有哪些?

在数字化转型的进程中&#xff0c;VR技术可以帮助各个行业领域的企业商家更便捷地搭建沉浸式服务体验&#xff0c;帮助商家提高展示以及加快企业沟通效率。后疫情时代&#xff0c;企业数字化转型加速发展&#xff0c;VR技术已经成为企业云服务的标配工具&#xff0c;因此VR全景…

半入耳蓝牙耳机什么牌子好?音质最好的半入耳式蓝牙耳机

跑步或者游泳的时候带着耳机听音乐或者有声书&#xff0c;是一家很惬意舒心的事情&#xff0c;市面上有那么多的蓝牙耳机品牌&#xff0c;很多人在选购的时候总是犯了难&#xff0c;不知道哪款耳机值得入手&#xff0c;半入二的佩戴更加舒适&#xff0c;深受很多人的喜爱&#…

用于音频信号去噪的谱相减和陷波滤波的比较(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 谱相减减少背景&#xff08;加性&#xff09;噪声影响的最流行方法之一是谱相减。背景噪声是降低录音中语音质量和清晰度的最常…

const成员和static成员详解

const成员和static成员详解1.const成员函数2.static成员&#xff08;1&#xff09;静态成员变量&#xff08;2&#xff09;静态成员函数&#xff08;3&#xff09;静态成员使用场景1.const成员函数 将const修饰的“成员函数”称之为const成员函数&#xff0c;const修饰类成员函…

热点新品—类器官代谢组学

01为什么研究类器官如此重要&#xff1f; 类器官技术是近年来生物医学领域最具突破性的前沿技术之一&#xff0c;更是科技部发布了“十四五”国家重点研发计划的6个重点专项之一。因模型本身具有极高的创新性&#xff0c;深受基金申请和高分杂志的青睐。并且由于人源化类器官可…

让你室友、工友、小孩、断网的骚操作!ARP攻击演示!

前提&#xff1a; ① 、你需要 和 你室友处于同一个局域网&#xff0c;互相能ping通 ②、你需要知道你室友的IP ③、您可能需要一个linux 设备&#xff0c;手机也行&#xff08;需要安装termux 来执行命令&#xff09;、linux系统电脑、树莓派等都可以。 -----------------…

PCB入门学习—原理图的绘制2

目录 2.2 TEA5767音频模块的绘制 2.3 ENC28J60以太网模块的绘制 学习目录&#xff1a; 2.2 TEA5767音频模块的绘制 首先有个问题&#xff1a;为什么这个电容放在原理图上怎么移动也对不齐&#xff1f;&#xff1f; 解决方法&#xff1a;把原理图上的栅格这个东西设置成1mil…