1. 程式人生 > >搭建自己的部落格(二十七):自定義使用者模型

搭建自己的部落格(二十七):自定義使用者模型

2、變化的部分

{% load staticfiles %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- 根據螢幕自動響應佈局 -->
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>
        {#  用來放標題  #}
        {% block title %}

        {% endblock %}
    
</title> {# 載入css程式碼 #} <link rel="stylesheet" href="{% static 'bootstrap4.1/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'css/base.css' %}"> {% block header_extends %} {# 用來做頭部擴充套件,如載入某些靜態檔案 #} {% endblock %} </head> <
body> {# 導航欄 #} <nav class="navbar navbar-expand-lg navbar-light bg-light sticky-top"> <a class="navbar-brand" href="{% url 'home' %}">Felix Blog</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls
="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item nav-home"><a href="{% url 'home' %}" class="nav-link">首頁</a></li> <li class="nav-item nav-blog"><a href="{% url 'blog_list' %}" class="nav-link">部落格</a></li> </ul> <ul class="navbar-nav"> {% if not user.is_authenticated %} <li class="nav-item"> <a class="nav-link" href="{% url 'login' %}?from={{ request.get_full_path }}">登入</a> </li> <li class="nav-item"> <a class="nav-link" href="{% url 'register' %}?from={{ request.get_full_path }}">註冊</a> </li> {% else %} <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> {{ user.username }} </a> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{% url 'user_info' %}">個人資料</a> {% if user.is_staff or user.is_superuser %} <a class="dropdown-item" href="{% url 'admin:index' %}">後臺管理</a> {% endif %} <div class="dropdown-divider"></div> <a class="dropdown-item" href="{% url 'logout' %}?from={{ request.get_full_path }}">登出</a> </div> </li> {% endif %} </ul> </div> </nav> {# 用來放內容 #} {% block content %} {% endblock %} <!-- Modal 登入模態框 --> <div class="modal fade" id="login_model" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <form id="login_model_form" action="" method="post"> <div class="modal-header"> <h5 class="modal-title">登入</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> {% csrf_token %} {% for field in login_model_form %} <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} {% endfor %} <span id="login_model_tip" class="text-danger"></span> </div> <div class="modal-footer"> <button type="submit" class="btn btn-primary">登入</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">關閉</button> </div> </form> </div> </div> </div> <script> $('#login_model_form').submit(function (event) { $('#login_model_tip').text(''); event.preventDefault(); // 阻止原事件提交 $.ajax({ url: '{% url 'login_for_model' %}', type: 'POST', data: $(this).serialize(), cache: false, success: function (data) { if (data['status'] === 'SUCCESS') { window.location.reload(); } else { $('#login_model_tip').text('使用者名稱或密碼不正確') } } }); }) </script> {# js程式碼放在後面可以增加效能 #} <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="{% static 'js/jquery-3.3.1.min.js' %}"></script> <script src="{% static 'bootstrap4.1/popper.min.js' %}"></script> <script src="{% static 'bootstrap4.1/bootstrap.min.js' %}"></script> {# 匯入資源建議放在js程式碼前 #} {# 用來放js程式碼 #} {% block js %} {% endblock %} </body> </html>
base.html
{% extends 'base.html' %}

{% block title %}
    我的部落格|登入
{% endblock %}

{% block content %}
    <div class="container">
        <div class="col-xl-6 offset-xl-3">
            {% if not user.is_authenticated %}
                <div class="card">
                    <h5 class="card-header">登入</h5>
                    <div class="card-body">
                        <form action="" method="post">
                            {% csrf_token %}
                            {% for field in login_form %}
                                <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                                {{ field }}
                                <p class="text-danger">{{ field.errors.as_text }}</p>
                            {% endfor %}
                            <span class="text-danger float-left">{{ login_form.non_field_errors }}</span>
                            <input type="submit" value="登入" class="btn btn-primary float-right">
                        </form>
                    </div>
                </div>
                {# 未登入跳轉到首頁 #}
            {% else %}
                <script>
                    window.location.href = '{% url 'home' %}'
                </script>
            {% endif %}
        </div>
    </div>
{% endblock %}

{% block js %}
    {# 將首頁這個按鈕設定啟用狀態 #}
    <script>
        $(".nav-home").addClass("active").siblings().removeClass("active");
    </script>
{% endblock %}
login.html
{% extends 'base.html' %}

{% block title %}
    我的部落格|註冊
{% endblock %}

{% block content %}
    <div class="container">
        {% if not user.is_authenticated %}
            <div class="col-xl-6 offset-xl-3">
            <div class="card">
                <h5 class="card-header">註冊</h5>
                <div class="card-body">
                    <form action="{% url 'register' %}" method="post">
                        {% csrf_token %}
                        {% for field in reg_form %}
                            <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                            {{ field }}
                            <p class="text-danger">{{ field.errors.as_text }}</p>
                        {% endfor %}
                        <span class="text-danger float-left">{{ login_form.non_field_errors }}</span>
                        <input type="submit" value="註冊" class="btn btn-primary float-right">
                    </form>
                </div>
            </div>
        {% else %}
            <script>
                window.location.href = '{% url 'home' %}'
            </script>
        {% endif %}
        </div>
    </div>
{% endblock %}

{% block js %}
    {# 將首頁這個按鈕設定啟用狀態 #}
    <script>
        $(".nav-home").addClass("active").siblings().removeClass("active");
    </script>
{% endblock %}
register.html
{% extends 'base.html' %}

{% block title %}
    個人資料
{% endblock %}

{% block content %}
    <div class="container">
        <div class="col-xl-8 offset-xl-2">
            <h2>{{ user.username }}</h2>
            {% if user.is_authenticated %}
                <ul>
                    <li>暱稱: <a href="">修改暱稱</a></li>
                    <li>
                        郵箱:
                        {% if user.email %}
                            {{ user.email }}
                        {% else %}
                            未繫結 <a href="">繫結郵箱</a>
                        {% endif %}
                    </li>
                    <li>上一次登入時間:{{ user.last_login|date:"Y-m-d H:i:s" }}</li>
                    <li><a href="">修改密碼</a></li>
                </ul>
            {% else %}
                {# 未登入跳轉到首頁 #}
                <script>
                    window.location.href = '{% url 'home' %}'
                </script>
            {% endif %}
        </div>
    </div>
    </div>
{% endblock %}

{% block js %}
    {# 將首頁這個按鈕設定啟用狀態 #}
    <script>
        $(".nav-home").addClass("active").siblings().removeClass("active");
    </script>
{% endblock %}
user_info.html
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User

from .models import Profile


# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class ProfileInline(admin.StackedInline):
    model = Profile
    can_delete = False


# Define a new User admin
class UserAdmin(BaseUserAdmin):
    inlines = (ProfileInline,)
    list_display = ('username', 'nickname', 'email', 'is_staff', 'is_active', 'is_superuser')

    def nickname(self, obj):
        return obj.profile.nikename

    nickname.short_description = '暱稱'  # 後臺欄位


# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)


@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
    list_display = ('user', 'nikename')
admin.py
from django.db import models
from django.contrib.auth.models import User


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nikename = models.CharField(max_length=20, verbose_name='暱稱',default='')

    def __str__(self):
        return '<Profile: {} for {}>'.format(self.nikename, self.user.username)
models.py