溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Django之入門 CMDB系統(tǒng) (三) 登錄注銷

發(fā)布時間:2020-05-23 16:43:12 來源:網(wǎng)絡(luò) 閱讀:466 作者:295631788 欄目:系統(tǒng)運維

Django之入門 CMDB系統(tǒng) (三) 登錄注銷


前言

作者: 何全,github地址: https://github.com/hequan2017 QQ交流群: 620176501

通過此教程完成從零入門,能夠獨立編寫一個簡單的CMDB系統(tǒng)。

目前主流的方法開發(fā)方式,分為2種:mvc 和 mvvc方式。本教程為 mvc 方式,即 django負責渲染html。后面會推出 mvvc(前后端分離)的入門教程。

教程項目地址: https://github.com/hequan2017/husky/

教程文檔地址: https://github.com/hequan2017/husky/tree/master/doc
Django之入門 CMDB系統(tǒng)  (三) 登錄注銷

首頁

pycharm : 菜單欄 tools --> 選擇 run manage.py task

manage.py@husky > startapp system # 創(chuàng)建一個APP ,用來管理系統(tǒng)

具體內(nèi)容請看實際頁面,下面只是把重點代碼 進行展示。


Django之入門 CMDB系統(tǒng)  (三) 登錄注銷

  • husky/urls.py
from django.contrib import admin
from django.urls import path
from system.views import index
from django.conf.urls import include   

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index),
    path('index', index, name="index"),
    path('system/', include('system.urls', namespace='system')),  ## 引入 system 的urls 文件
]
  • system/__init.py 新建空白文件

  • system/views.py 負責邏輯處理
@login_required(login_url="/system/login")
def index(request):
    """
    首頁
    :param request:
    :return:
    """
    return render(request, 'system/index.html',{})  #render  結(jié)合一個給定的模板和一個給定的上下文字典,并返回一個渲染后的 HttpResponse 對象。

登錄

  • system/modesl.py 表結(jié)構(gòu)

    繼承user表結(jié)構(gòu),重建user表

?用?一個 Python 類來描述數(shù)據(jù)表, 我們 稱之為 模型(model) 。 運?用這個類,你可以通過簡單的
Python 的代碼來創(chuàng)建、檢索、更更新、刪除 數(shù)據(jù)庫中的記錄?而?無需寫?一條?又?一條的SQL語句句,這
就是傳說中的ORM(Object Relation Mapping)

from django.db import models
from django.contrib.auth.models import AbstractUser  

class Users(AbstractUser):  # AbstractUser  重寫 user 需要集成表
    """
    基于django表  添加字段 , 如有需要調(diào)用user的情況,請使用此表
    """
    position = models.CharField(max_length=64, verbose_name='職位信息', blank=True, null=True)
    avatar = models.CharField(max_length=256, verbose_name='頭像', blank=True, null=True)
    mobile = models.CharField(max_length=11, verbose_name='手機', blank=True, null=True)

    class Meta:
        db_table = 'users'
        verbose_name = '用戶信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

因為更改了默認的user表,需要先把庫刪了。再進行重建。

drop database husky;
create database husky;

pycharm : 菜單欄 tools --> 選擇 run manage.py task

makemigrations 生成數(shù)據(jù)文件

migrate 根據(jù)文件,執(zhí)行生成表結(jié)構(gòu)

createsuperuser

  • settings.py 增加系統(tǒng)配置
import sys
INSTALLED_APPS = [   # 這里填寫 創(chuàng)建的app  ,結(jié)構(gòu)為, 一個項目 可以有多個APP
    "system",
    'bootstrap3' 
]

AUTH_USER_MODEL = 'system.users'
AUTHENTICATION_BACKENDS = ('system.views.CustomBackend',)  ## 重新登錄驗證,增加郵箱名字也可以用作登錄

SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_AGE = 432000
LOGIN_URL = '/auth/login'
LANGUAGE_CODE = 'zh-Hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True
USE_L10N = False
USE_TZ = True
DATETIME_FORMAT = 'Y-m-d H:i:s'
DATE_FORMAT = 'Y-m-d'

# logging
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '[argus] %(levelname)s %(asctime)s %(module)s %(message)s'
        }
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'stream': sys.stdout,
            'formatter': 'verbose'
        },
    },
    'loggers': {
        'tasks': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'asset': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

# 表格table
PAGINATION_SETTINGS = {
    'PAGE_RANGE_DISPLAYED': 3,
    'MARGIN_PAGES_DISPLAYED': 2,
    'SHOW_FIRST_PAGE_WHEN_INVALID': True,
}

# 表格table 一頁 展示數(shù)據(jù)
DISPLAY_PER_PAGE = 15

  • system/views.py

    View 包含了了項?目的業(yè)務邏輯,我們稱之為視圖,也是我們開發(fā)過程中主要編寫的內(nèi)容

def login_view(request):
    """
    登錄
    :param request: username,password
    :return:
    """

    error_msg = "用戶名或密碼錯誤,或者被禁用,請重試"

    if request.method == "GET":
        return render(request, 'system/login.html', {'error_msg': error_msg, })

    if request.method == "POST":
        u = request.POST.get("username")
        p = request.POST.get("password")
        user = authenticate(request, username=u, password=p)
        if user is not None:
            if user.is_active:
                login(request, user)
                request.session['is_login'] = True
                login_ip = request.META['REMOTE_ADDR']
                return redirect('/index')  ## 重定向到的一個具體的網(wǎng)址
            else:
                return render(request, 'system/login.html', {'error_msg': error_msg, })
        else:
            return render(request, 'system/login.html', {'error_msg': error_msg, })

class CustomBackend(ModelBackend):
    """
    用戶名字/郵箱名字 登錄
    :param request:
    :return:
    """
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = Users.objects.get(Q(username=username) | Q(email=username))
            if user.check_password(password):
                return user
        except Exception as e:
            logger.error(e)
            return None
  • system/urls.py 路由

指出了了什什么樣的 URL 調(diào)?用什什么的視圖。 在這個例例?子中 /latest/ URL 將會調(diào)?用 latest_books() 這
個函數(shù)。 換句句話說,如果你的域名是example.com,任何?人瀏覽?網(wǎng)址 http://example.com/latest/ 將
會調(diào)?用 latest_books()這個函數(shù)返回結(jié)果給?用戶

from django.urls import path
from system.views import login_view

app_name = "system"

urlpatterns = [
    path('login', login_view, name="login")
]
  • templates/system/login.html

簡單來說就是html 模板,它描述了了項?目的界?面結(jié)構(gòu)。 模板引擎也內(nèi)置了了?一些tag 。

登錄不繼承 base.html ,為一個單獨頁面

  <h4>歡迎登錄 系統(tǒng)</h4>
        <form class="m-t" role="form" action="{% url "system:login" %}" method="POST">
            {% csrf_token %}
            <div class="form-group">
                <input type="text" name="username" class="form-control" placeholder="用戶名" required="">
            </div>
            <div class="form-group">
                <input type="password" name="password" class="form-control" placeholder="密碼" required="">
            </div>
            <button type="submit" class="btn btn-primary block full-width m-b">登錄</button>

            <a href="#">
                <span > {{ error_msg }}</span><br>
              不推薦使用IE/360瀏覽器(兼容模式)瀏覽!<br />

            </a>
            <div id="login_container"></div>

        </form>

注銷

  • system/views.py
def logout_view(request):
    """
    注銷
    :param request:
    :return:
    """
    logout(request)
    return redirect('system:login')
  • system/urls.py
path('logout', logout_view, name="logout"),
  • templates/base/_navbar-static-top.html
 <li>
        <a href="{% url "system:logout" %}">
                    <i class="fa fa-sign-out"></i> 注銷
                </a>
            </li>

更改密碼

  • system/form.py

用戶表單是Web端的一項基本功能,大而全的Django框架中自然帶有現(xiàn)成的基礎(chǔ)form對象,本文就Python的Django框架中forms表單類的使用方法詳解。

  • Form表單的功能
    • 自動生成HTML表單元素
    • 檢查表單數(shù)據(jù)的合法性
    • 如果驗證錯誤,重新顯示表單(數(shù)據(jù)不會重置)
    • 數(shù)據(jù)類型轉(zhuǎn)換(字符類型的數(shù)據(jù)轉(zhuǎn)換成相應的Python類型)
from django import forms

class UserPasswordForm(forms.Form):
    old_password = forms.CharField(max_length=128, widget=forms.PasswordInput, label='舊密碼')
    new_password = forms.CharField(min_length=8, max_length=128, widget=forms.PasswordInput, label='新密碼',
                                   help_text="* 你的密碼必須包含至少 8 個字符,不能是大家都愛用的常見密碼,不能全部為數(shù)字")
    confirm_password = forms.CharField(min_length=8, max_length=128, widget=forms.PasswordInput, label='確認密碼',
                                       help_text="* 和上面密碼一致")

    def __init__(self, *args, **kwargs):
        self.instance = kwargs.pop('instance')
        super().__init__(*args, **kwargs)

    def clean_old_password(self):
        old_password = self.cleaned_data['old_password']
        if not self.instance.check_password(old_password):
            raise forms.ValidationError('舊密碼錯誤')
        return old_password

    def clean_confirm_password(self):
        new_password = self.cleaned_data['new_password']
        confirm_password = self.cleaned_data['confirm_password']

        if new_password != confirm_password:
            raise forms.ValidationError('新密碼與確認密碼不一致')
        return confirm_password

    def save(self):
        password = self.cleaned_data['new_password']
        self.instance.set_password(password)
        self.instance.save()
        return self.instance
  • system/views.py

    class UserPasswordUpdateView(LoginRequiredMixin, UpdateView):
    """
    修改密碼
    :param request:
    :return:
    """
    template_name = 'system/password.html'
    model = Users
    form_class = UserPasswordForm
    success_url = reverse_lazy('system:logout')
    
    def get_object(self, queryset=None):
        return self.request.user
    
    def get_context_data(self, **kwargs):
        return super().get_context_data(**kwargs)
    
    def get_success_url(self):
        return super().get_success_url()
  • system/urls.py
    path('password_update', UserPasswordUpdateView.as_view(), name="password_update"),
  • templates/system/password.html

    <div class="wrapper wrapper-content animated fadeInRight">
    <form method="post" class="form-horizontal" action="" enctype="multipart/form-data">
        {% csrf_token %}
    
        {% if form.non_field_errors %}
            <div class="alert alert-danger" >
                {{ form.non_field_errors }}
            </div>
        {% endif %}
        <div class="form-group">
            <div class="col-sm-10 col-sm-offset-0"> {{ msg }}
                {% bootstrap_field form.old_password layout="horizontal" %}
                {% bootstrap_field form.new_password layout="horizontal" %}
                {% bootstrap_field form.confirm_password layout="horizontal" %}</div>
        </div>
    
        <div class="hr-line-dashed"></div>
        <div class="form-group">
            <div class="col-sm-4 col-sm-offset-3">
    
                <button id="submit_button" class="btn btn-primary" type="submit">提交</button>
                <button class="btn btn-white" type="reset">重置</button>
            </div>
        </div>
    </form>
    </div>

后臺

  • system/admin.py

    后臺界面配置文件,每個APP 可以創(chuàng)建一個

from django.contrib import admin
from system.models import Users
from django.contrib.auth.admin import UserAdmin

class UsersAdmin(UserAdmin):
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        ('基本信息', {'fields': ('first_name', 'last_name', 'email')}),
        ('權(quán)限', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
        ('登錄時間', {'fields': ('last_login', 'date_joined')}),
        ('其他信息', {'fields': (
            'position', 'avatar', 'mobile',)}),
    )

    @classmethod
    def show_group(self, obj):
        return [i.name for i in obj.groups.all()]

    @classmethod
    def show_user_permissions(self, obj):
        return [i.name for i in obj.user_permissions.all()]

    list_display = ('username', 'show_group', 'show_user_permissions')
    list_display_links = ('username',)
    search_fields = ('username',)
    filter_horizontal = ('groups', 'user_permissions')

admin.site.register(Users, UsersAdmin)
admin.site.site_header = '管理后臺'
admin.site.site_title = admin.site.site_header

其他

  • migrations 目錄為存放django自動生成的表結(jié)構(gòu)文件,系統(tǒng)會根據(jù)生成的這些文件 創(chuàng)建數(shù)據(jù)庫表,如要重新生成數(shù)據(jù)庫,需要把里面的生成文件刪除掉。
向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI