Django項目學習


title: Django項目學習
date: 2017-12-13 19:32:03
tags: [網頁,Django]
category: [編程學習,網頁製做]
---css

本文主要來自於mooc公開課Django課程html

首先建立一個Django的虛擬環境:

pip install virtualenv,而後使用virtualenv 虛擬環境名創建一個虛擬環境,在windows下面的激活方法是前端

cd django_virtual
cd Script
activate

在linux下只須要將最後一步換位source activatepython

創建Django項目

在PyCharm創建程序時,直接選擇Django程序,選擇解釋器爲virtualenv創建的django環境,便可創建django項目mysql

項目創建以後,咱們獲得了以下的目錄結構,紫色的被標記爲了templet目錄,這樣就能智能提示,若是你想要在import的時候不須要加入絕對路徑,那麼就能夠mark as source rootlinux

接下來咱們先嚐試運行該項目,點擊run,運行這個Django項目,能夠看到運行在了本機的8000端口,點擊該地址便可訪問:git

若是要配置監聽全部ip,那麼咱們須要經過run-Edit configurations,將監聽端口改成0.0.0.0github

安裝好Navicat以後,打開軟件,創建鏈接,以後創建表,設計表的字段,設計完以後按ctrl+s保存,以後就能夠插入數據條目,這就是簡單的使用方法,具體使用會在以後用到的時候詳細介紹。下載地址請點擊web

Django目錄結構

首先看看以前提到的創建django以後的目錄結構,windows使用tree \F .獲得以下結構,linux中使用apt-get install tree,而後tree .便可獲得sql

├mooc_web
  │  manage.py
  ├─mooc_web
  │  │  settings.py
  │  │  urls.py
  │  │  wsgi.py
  │  │  __init__.py
  └─templates
  • templetes文件夾主要放html文件
  • 主文件夾下面有settings.py,以及manage.py
  • 咱們須要創建static文件夾,用於存放css和js文件,以及主要的圖片文件
  • 創建log文件夾,用於存放日誌
  • 創建media文件夾,用於存放用戶上傳的文件
  • 創建apps文件夾,用於存放各個app

創建app

經過pycharm當中的tools-run manage.py task,此時能夠在shell中執行Django命令:

startapp message

此時就有了一個名爲message的文件夾,將其拖入apps文件夾,自動生成了一個__init__.py文件,這樣就讓apps變成一個能夠導入的包,爲了方便導入,那麼咱們須要將apps文件夾remark成source root,這樣每次引用的時候就不須要import apps.message.view 而是能夠直接 import message.view

這樣在pycharm中引用變得方便了,可是在使用命令行運行的時候就會出錯,此時咱們須要在settings.py中將apps加入到根搜索路徑(BASE_DIR)中

├── apps
│   ├── __init__.py
│   └── message
│       ├── admin.py
│       ├── apps.py
│       ├── __init__.py
│       ├── migrations
│       │   └── __init__.py
│       ├── models.py
│       ├── tests.py
│       └── views.py
├── db.sqlite3
├── log
├── manage.py
├── media
├── mooc_web
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── static
└── templates

創建log文件夾用於存放日誌,media用於存放用戶的上傳文件,創建static存放靜態css和js文件

當app比較多的時候,就創建一個apps文件夾,將新創建的app拖進去

使用模板

將html模板放入template文件夾,在static文件夾中創建css文件夾,並放入style.css文件

settings配置

更改數據庫配置

由於Django默認用的是sqlite數據庫,咱們要改爲mysql數據庫,打開項目的settings.py,找到DATABASES,將其中的:

  • ENGINE改成django.db.backends.mysql
  • NAME改成Navicat中看到的testDjango
  • USER改成數據庫的user名,我這裏是root
  • PASSWORD改成數據庫的password,我這裏也是root
  • HOST改成localhost,也就是127.0.0.1
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testDjango',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '127.0.0.1'
    }
}

migration生成數據表

經過tools-Run manage.py Task來鏈接數據庫,首先須要安裝mysqlclient,用pip install mysqlclient安裝:

> makemigrations   # 用於生成一個基於你對模型改變的遷移,在這裏就是數據庫類型從sqlite遷移到mysql
> migrate         # 用於應用改變

此時Django自動生成了一大堆數據庫表,在Navicat中能夠看到表的名稱:

此時能夠點擊run運行整個系統,能夠在127.0.0.1:8000上訪問該網址

配置static文件夾地址

可是此時的style.css沒法被找到,咱們要在settings.py中配置一下static文件夾的地址,由於STATICFILES_DIRS 可能不止一個,因此用list的形式進行賦值,其中BASE_DIR是項目文件的根目錄:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static')
]

urls.py配置和views.py函數

在urls.py中添加新的頁面,頁面的處理函數要在apps-message-views.py 中新增,首先咱們在view.py 中構造以下函數,直接return render的模板,其中request參數是Django的請求,每一個views函數都得有:

def getform(request):
    return render(request, template_name='course-comment.html')

項目配置流程

總體來講,先設置數據庫和STATICFILES_DIRS,以後這一塊再也不動,主要就是views.py寫後端邏輯,urls.py寫頁面地址url配置

Django orm 模型設計

普通的數據庫調用方法,鏈接(connect),生成cursor,excute sql語句,cursor.fetchall( )

orm就是把一個表映射成一個類,好比要找出name只須要調用book.name

下面咱們開始使用orm進行設計數據庫:

找到message下面的models.py文件,在其中定義一個UserMessage類,用於存放咱們須要的數據,全部model都要繼承models.Model類:

class UserMessage(models.Model):
    name = models.CharField(max_length=20, verbose_name='用戶名')
    email = models.EmailField(verbose_name='郵箱')
    address = models.CharField(max_length=100, verbose_name='地址')
    message = models.CharField(max_length=500, verbose_name='留言信箱')

    class Meta:
        verbose_name = '用戶留言信息'
        verbose_name_plural = verbose_name
        ordering = '-id'  # 排序方式爲反向的id
        db_table = 'my_table'  #設置table的名字

其中每個字段都定義一個類型,經常使用的有CharField,EmailField,DateTimeField, IntergerField, ForeignKey, IPAddressField, FileField, ImageField

其中max_length表示最大長度,verbose_name表示別名.

本身定義的model還有一個內部類Meta,用於存放全部不是Field的字段,好比排序的順序,數據表的名稱等等

應用模型的改變

點擊Tools-Run manage.py,執行命令,發現找不到message這個model,全部咱們要去settings.py中INSTALLED_APPS加入'app.message'

再次執行

> makemigrations message
> migragate message

對數據表進行增刪改查

查找數據

先引入model對象,from apps.message.models import UserMessage ,,利用model對象的objects方法,對數據進行操做

all_message = UserMessage.objects.all()  #這個是能夠循環的
for message in all_messages:
    print(message.name)

filterd_data = UserMessage.objects.filter(name='jeffrey',address='beijing')  #filter方法能夠對數據進行過濾,中間的逗號表示多個條件,這裏是取出的name爲jeffrey,address爲北京的值
for message in filterd_data:
    print(message.name)

這裏的all就是取出全部值,filter就是取出特定條件的值

增長數據

定義一個新的對象,並對其各個field賦值

user_message = UserMessage()
user_message.name = 'a'
user_message.message = 'a@a.com'
user_message.message = 'aaaaa'
user_message.save()

這樣每次訪問form頁面的時候均可以存入一條記錄

在html文件中須要進行以下更改:

<form action="/form/" method="post" class="smart-green">
在action中填入網頁地址

須要加入CSRF安全機制,

還能夠經過頁面的表單提交增長新的數據,request的POST屬性中,以字典的形式存儲了表單中提交的值,能夠用python的get方法獲取這些值,get的第二個參數爲獲取不到時候的默認值:

if request.method == 'POST':
    name = request.POST.get('name','')
    email = request.POST.get('email', '')
    message = request.POST.get('message', '')
    
    user_message = UserMessage()
    user_message.name = 'a'
    user_message.email = 'a@a.com'
    user_message.message = 'aaaaa'
    user_message.save()
刪除數據

直接先查找到對象,而後用delete方法就能夠刪除對象

all_message = UserMessage.objects.fileter(name='bob')
all_message.delete()

顯示數據庫中的數據到頁面

在view.py中,咱們能夠先取出數據,而後在render的時候,把須要傳入的參數以一個dict的形式,傳遞給context,這樣咱們就能夠在html文件中進行調用

def getform(request):
    message = None
    all_message = UserMessage.objects.filter(name='boobytest')
    if all_message:
        message = all_message[0]
    return render(request, template_name='course-comment.html',context={'message':message,})

在HTML文件中調用參數的方法是兩個大括號,input就輸入在value裏面,textarea就輸入在兩個標籤之間:

<input id="email" type="email" value={ { message.email } } name="email" placeholder="請輸入郵箱地址"/>
<textarea id="message" name="message"  placeholder="請輸入你的建議">{ { message.message } }</textarea>

在HTML文件中使用python邏輯

在HTML文件中,使用python邏輯的方法是大括號加百分號,{ % python expression % }

if和end if成對出現

<input id="name" type="text" value="{% if not message.name == 'boobytest' %}
boobyhastest{% else %}booby no test
{% endif %}" name="name" class="error" placeholder="請輸入您的姓名"/>

好比在HTML中使用if和else的方法如上,固然if a==b 也可使用 ifequal a b代替,取前五位也可使用message.name|split:'5'

{% ifequal a b%}  {% endif %}#用於表示等於

Django提供了不少內置的方法,具體能夠查看Django template built-in tags

使用別名關聯url和HTML

url在配置過程當中可能會改變,所以咱們須要爲url設置一個不變的名字供HTML調用

在url.py中:

url(r'^form/$', getform,name='form')

在comment.html中:

<form action="{% url 'form' %}" method="post" class="smart-green">

注意,在url配置中必定要加上/$ 表示以/結尾,否則再進行正則匹配的時候可能會匹配到別的網頁

url匹配

必須在url前面加上^,後面加上/$,這樣不會匹配出錯

mooc開發實戰

app設計

新建虛擬環境

mkvirtualenv mooc
cd mooc/Script
activate
pip install Django mysqlclient

新建Django項目

經過pycharm創建Django項目,名字爲MxOnline,首先在settings.py中更改數據庫引擎

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mxonline',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '127.0.0.1',
    }
}

經過Tools-run manage.py task來生成數據庫的表

makemigrations
migragate

擴展user表

首先startapp users,在models當中,新建一個UserProfile,繼承django.contrib.auth.models.AbstractUser,加入你須要的自定義字段,並定義好meta信息中的verbose_name

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

# Create your models here.
class UserProfile(AbstractUser):
    nick_name = models.CharField(max_length=50,verbose_name='暱稱',default='')
    birthday = models.DateField(verbose_name='生日',null=True,blank=True)
    gender = models.CharField(max_length=5,choices=(('male','男'),('female','女')),default='')
    address = models.CharField(max_length=100,default='')
    mobile = models.CharField(max_length=11, null=True, blank=True)
    image = models.ImageField(upload_to='image/%Y/%m',default='image/default.png')


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

而後run manage.py,經過makemigrations usersmigragate users生成新的user表,可能會報錯,報錯時只須要將以前生成的全部表刪除後從新生成便可

循環引用

避免交叉引用,否則會出錯,使用上層app引用下層app

加入郵件驗證碼和輪播圖

class EmailVerifyRecord(models.Model):
    code = models.CharField(max_length=20, verbose_name='驗證碼')
    email = models.EmailField(max_length=50, verbose_name= '郵箱')
    send_type = models.CharField(choices=(('register','註冊'),('forget','找回密碼')),max_length=10)
    send_time = models.DateTimeField(default=datetime.now) #記得去掉datetime.now的括號,否則只會記錄class生成的時間
    class Meta:
        verbose_name = '郵箱驗證碼'
        verbose_name_plural = verbose_name

class Banner(models.Model):
    title = models.CharField(max_length=100, verbose_name='標題')
    image = models.ImageField(upload_to='banner/%Y/%m', verbose_name='輪播圖')
    url = models.URLField(max_length=500, verbose_name='訪問地址')
    index = models.IntegerField(default=100, verbose_name='順序')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '輪播圖'
        verbose_name_plural = verbose_name

課程model設計

Course -- 課程基本信息
Lesson -- 章節信息
Video -- 視頻
CourseResource -- 課程資源

一共有上述四張表

from django.db import models
from datetime import datetime

# Create your models here.
class Course(models.Model):
    name = models.CharField(max_length=50, verbose_name='課程名稱')
    desc = models.CharField(max_length=300, verbose_name='課程描述')
    detail = models.TextField(verbose_name='課程詳情')
    degree = models.CharField(choices=(('cj','初級'),('zj','中級'),('gj','高級')),verbose_name='課程難度',max_length=2)
    learn_time = models.IntegerField(default=0, verbose_name='學習時長(分鐘數)')
    students = models.IntegerField(default=0, verbose_name='學習人數')
    fav = models.IntegerField(default=0, verbose_name='收藏人數')
    image = models.ImageField(upload_to='courses/%Y/%m', verbose_name='封面圖', max_length=100)
    click_num = models.IntegerField(default=0, verbose_name='點擊數')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name='課程'
        verbose_name_plural = verbose_name

class Lesson(models.Model):
    course = models.ForeignKey(Course, verbose_name='課程')
    name = models.CharField(max_length=100, verbose_name='章節名')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '章節'
        verbose_name_plural = verbose_name

class Video(models.Model):
    lesson = models.ForeignKey(Lesson, verbose_name='章節')
    name = models.CharField(max_length=100, verbose_name='視頻名')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '視頻'
        verbose_name_plural = verbose_name

class CourseResource(models.Model):
    course = models.ForeignKey(Course, verbose_name='課程')
    download = models.FileField(upload_to='courses/resource/%Y/%m',max_length=100)
    name = models.CharField(max_length=100, verbose_name='資源名稱')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '課程資源'
        verbose_name_plural = verbose_name

添加organization的model

CourseOrg -- 課程機構基本信息
Teacher -- 教師基本信息
CityDict -- 城市信息

添加以下

from django.db import models
from datetime import datetime

# Create your models here.

class CourseOrg(models.Model):
    city = models.ForeignKey(CityDict,verbose_name='所在城市')
    name = models.CharField(max_length=50,verbose_name='機構名稱')
    desc = models.TextField(verbose_name='機構描述')
    click_nums = models.IntegerField(default=0, verbose_name='點擊數')
    fav_nums =  models.IntegerField(default=0, verbose_name='收藏數')
    image = models.ImageField(upload_to='org/%Y/%m',verbose_name='封面圖')
    address = models.CharField(max_length=150,verbose_name='地址')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '課程機構'
        verbose_name_plural = verbose_name

class CityDict(models.Model):
    name = models.CharField(max_length=20,verbose_name='城市')
    desc = models.CharField(max_length=200, verbose_name='描述')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '城市'
        verbose_name_plural = verbose_name

class Teacher(models.Model):
    org = models.ForeignKey(CourseOrg, verbose_name='所屬機構')
    name = models.CharField(max_length=20,verbose_name='教師名')
    work_years = models.IntegerField(default=0, verbose_name='工做年限')
    work_company = models.CharField(max_length=50,verbose_name='就任公司')
    work_position = models.CharField(max_length=50,verbose_name='公司職位')
    points = models.CharField(max_length=50, verbose_name='教學特色')
    click_nums = models.IntegerField(default=0, verbose_name='點擊數')
    fav_nums =  models.IntegerField(default=0, verbose_name='收藏數')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '教師'
        verbose_name_plural = verbose_name

添加operation的model

UserAsk -- 用戶諮詢
CourseComments -- 用戶評論
UserFavorite -- 用戶收藏
UserMessage -- 用戶消息
UserCourse -- 用戶學習的課程

添加以下:

from django.db import models
from datetime import datetime
from users.models import UserProfile
from courses.models import Course
from organization.models import CourseOrg


# Create your models here.
class UserAsk(models.Model):
    name = models.CharField(max_length=20,verbose_name='姓名')
    mobile = models.CharField(max_length=11, verbose_name='手機')
    course_name = models.CharField(max_length=50,verbose_name='課程名稱')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '用戶諮詢'
        verbose_name_plural = verbose_name

class CourseComments(models.Model):
    user = models.ForeignKey(UserProfile, verbose_name='用戶')
    course = models.ForeignKey(Course, verbose_name='課程')
    comments = models.CharField(max_length=500,verbose_name='評論')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '課程評論'
        verbose_name_plural = verbose_name

class UserFavorite(models.Model):
    user = models.ForeignKey(UserProfile, verbose_name='用戶')
    fav_id = models.IntegerField(default=0, verbose_name='數據id')
    fav_type = models.IntegerField(choices=((1,'課程'),(2,'課程機構'),(3,'講師')),default=1,verbose_name='收藏類型')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '用戶收藏'
        verbose_name_plural = verbose_name

class UserMessage(models.Model):
    user = models.IntegerField(default=0,verbose_name='接收用戶')# 不用外鍵,由於有多是發給全部人的消息,用0表示發送給全部人的消息,用int表示用戶的id
    message = models.CharField(max_length=500, verbose_name='消息內容')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    has_read = models.BooleanField(default=False,verbose_name='是否已讀')
    class Meta:
        verbose_name = '用戶消息'
        verbose_name_plural = verbose_name

class UserCourse(models.Model):
    user = models.ForeignKey(UserProfile, verbose_name='用戶')
    course = models.ForeignKey(Course, verbose_name='課程')
    add_time = models.DateTimeField(datetime.now, verbose_name='添加時間')
    class Meta:
        verbose_name = '用戶課程'
        verbose_name_plural = verbose_name

將全部app放到同一個文件夾下面

創建new python package, 把全部的app放到apps這個包下面,注意選擇不改相對引用,並mark apps爲source root

將apps這個文件夾加入到settings當中

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR,'apps'))

創建後臺管理系統

直接在run manage.py task中輸入createsuperuser,輸入用戶名,郵箱和密碼就能夠登陸

更改語言和時區:

LANGUAGE_CODE = 'zh-hans'  #將語言改成中文
TIME_ZONE = 'Asia/Shanghai' #將時區改成上海
USE_TZ = False # 系統使用本地時間而不是utc時間

由於咱們更改了admin的auth.user的model,所以須要註冊user的model,在users庫中的admin.py文件中註冊:

from users.models import UserProfile
# Register your models here.

class UserProfileAdmin(admin.ModelAdmin):  #userprofile的管理器
    pass

admin.site.register(UserProfile,UserProfileAdmin) #admin和model的關聯註冊

登陸http://127.0.0.1:8000/admin就能夠對用戶進行修改

  • pycharm全局搜索的快捷鍵是ctrl+shift+f

使用xadmin

使用xadmin,由於我安裝的Django 2.0.1版本,因此須要安裝專門的xadmin for Django2.0

pip install git+git://github.com/sshwsfc/xadmin.git@django2

在url.py中引入xadmin

import xadmin
urlpatterns = [url(r'^xadmin/', xadmin.site.urls),]

在settings.py中註冊xadmin和crispy_forms:

INSTALLED_APPS = [
    'django.contrib.admin',
.......
    'xadmin',
    'crispy_forms',
]

接下來同步xadmin的表:

> makemigrations
> migragate

再打開http://127.0.0.1:8000/xadmin就能夠訪問xadmin的後臺管理了

在管理用戶信息的時候,會出現錯誤,這是因爲咱們用的Django是2.0.1版本,而教程中用到的是1.0+,根據pycharm報錯的最後一條,打開widget.py文件,在74行修改以下

input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('/><') if ht != '']
if (len(input_html) > 1):
    input_html[0] = input_html[0] + "/>"
    input_html[1] = "<" + input_html[1]

經過源碼安裝xadmin

在mxonline下創建一個python package文件夾extra_apps,下載xadmin並解壓,拷貝其中的xadmin文件夾到其中,並把extra_apps mark as source root,這樣引入xadmin的時候就會從相對文件引入

同時在settings.py中把xadmin文件夾加入根搜索路徑

註冊郵箱驗證碼model

註冊方法相似於admin的註冊方式,只不過不是在admin.py中註冊,而是要新建adminx.py,而且admin繼承的是object

import xadmin
from users.models import EmailVerifyRecord

class EmailVerifyRecordAdmin(object):
    pass


xadmin.site.register(EmailVerifyRecord, EmailVerifyRecordAdmin)  # 註冊方法

修改顯示的郵件驗證碼存儲記錄的str名稱:

class EmailVerifyRecord(models.Model):
    code = models.CharField(max_length=20, verbose_name='驗證碼')
    email = models.EmailField(max_length=50, verbose_name= '郵箱')
.......
    def __str__(self):
        return '{0}({1})'.format(self.code,self.email)
  • 注意:全部註冊的Model名字都應該爲class Model名+Admin

添加搜索和顯示列

在其中加入list_display(顯示列), search_fields(搜索域), list_filter(過濾器)

class LessonAdmin(object):
    list_display = ['course','name','add_time']
    search_fields = ['course','name','add_time']
    list_filter = ['course','name','add_time']

若是要使用外鍵進行搜索,能夠用兩個下劃線表示

class LessonAdmin(object):
    list_filter = ['course__name','name','add_time']

xadmin全局配置

將全站的配置放在user app的admix.py中,新建一個class BaseSetting,用於配置主題

from xadmin import views

class BaseSettings:
    enable_themes = True   #容許使用主題
    use_bootswatch = True   #容許多主題
xadmin.site.register(views.BaseAdminView,BaseSettings)

創建一個class GlobalSettings配置標題名稱和footer名稱

class GlobalSettings:
    site_title = '慕學後臺管理系統'
    site_footer = '慕學在線網'
    menu_style = 'accordion' #摺疊model
xadmin.site.register(views.CommAdminView,GlobalSettings)

更改model名稱

在每一個model文件夾中的apps.py文件中加入verbose_name

from django.apps import AppConfig


class CoursesConfig(AppConfig):
    name = 'courses'
    verbose_name = '課程'

而後在__init__.py 中加入default_app_config

default_app_config = 'courses.apps.CoursesConfig'

完成用戶的登陸功能

首先將前端給的Index.html(首頁)文件和login.html(登陸頁)文件放入templates文件夾中

在根目錄下創建static文件夾,存放css,images,js,media文件,並在settings.py中聲明STATICFILES_DIRS=[os.path.join(BASE_DIR,'static')],注意:這裏的STATICFILES_DIRS必須設置爲list或者tuple形式,不然會報錯

此時,將html文件中的全部css,js的文件路徑修改成/static/css/static/js

接下來配置url,在url.py中引入TemplateView

from django.views.generic import TemplateView
urlpatterns = [
    url(r'^xadmin/', xadmin.site.urls),
    url(r'^$',TemplateView.as_view(template_name='index.html'),name='index'),
    url(r'^login/', TemplateView.as_view(template_name='login.html'), name='login')

]

這樣就完成了頁面配置,重啓項目後就能夠訪問首頁和登陸頁面

實現使用用戶名或者郵箱均可以登陸

如今users模塊中新建CustomBackend類,繼承ModelBackend,重寫其中的authenticate函數,用Q函數實現或操做

from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = UserProfile.objects.get(Q(username=username)|Q(email=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None

寫本身的login函數login,並將其寫到urls.py中

views.py

def my_login(request):
    if request.method == 'POST':
        user_name = request.POST.get('username','')
        pass_word = request.POST.get('password','')
        user = authenticate(username=user_name,password=pass_word)
        if user:
            login(request, user)
            return render(request, 'index.html',{'userprofile':user})
        else:
            return render(request,'login.html',{'msg':'用戶名或密碼錯誤'})
    elif request.method == 'GET':
        return render(request, 'login.html', {})

urls.py

url(r'^login/', my_login, name='login')

在settings.py中加入AUTHENTICATION_BACKENDS=('users.views.CustomBackend',),將認證後臺改成本身寫的後臺

在點擊登錄後,咱們須要跳轉回首頁或者是報告密碼錯誤,此時request被傳遞到網頁中,能夠在跳轉後顯示本身的用戶名

<dd>{{ request.POST.username }}<img class="down fr" src="/static/images/top_down.png"/></dd>

將用戶登陸改爲類的方法

views.py中加入本身的類:

from django.views.generic import View
class LoginView(View):
    def get(self, request):
        return render(request, 'login.html', {})
    def post(self, request):
        user_name = request.POST.get('username','')
        pass_word = request.POST.get('password','')
        user = authenticate(username=user_name,password=pass_word)
        if user:
            login(request, user)
            return render(request, 'index.html',{'userprofile':user})
        else:
            return render(request,'login.html',{'msg':'用戶名或密碼錯誤'})

在urls.py中將loginview註冊:

url(r'^login/', LoginView.as_view(), name='login')

實現用戶名和密碼的長度和空檢驗

在users模塊彙總創建forms.py用於檢驗表單

forms.py

from django import forms

class LoginForm(forms.Form):
    username = forms.CharField(required=True)
    password = forms.CharField(required=True, min_length=5)

在views.py中加入loginform的驗證,邏輯是若是有效,則提取表單中的username和password,驗證成功後,用login函數登陸,返回index頁面;若是驗證失敗,返回登陸頁顯示用戶或密碼錯誤;若是檢測到form有錯誤,返回登陸頁,顯示錯誤類型

class LoginView(View):
    def get(self, request):
        return render(request, 'login.html', {})
    def post(self, request):
        login_form = LoginForm(request.POST)    #實例化一個login_form,傳入參數爲request.POST,自動驗證其中的username和password,注意這裏名字必須和login.html的form當中的name相同
        if login_form.is_valid():  #這一步以後能夠看到login_form的error類型,存爲一個dict類型
            user_name = request.POST.get('username','')
            pass_word = request.POST.get('password','')
            user = authenticate(username=user_name,password=pass_word)
            if user:
                login(request, user)
                return render(request, 'index.html',{'userprofile':user})
            else:
                return render(request,'login.html',{'msg':'用戶名或密碼錯誤'})
        else:
            return render(request,'login.html',{'login_form':login_form})

在login.html中顯示錯誤類型:

<div class="error btns login-form-tips" id="jsLoginTips">{% for key, error in login_form.errors.items %}
{{ error }}{% endfor %}{{ msg }}</div>

使用cookies進行登陸

http自己是一種無狀態協議,每次發送請求,服務器返回請求的數據,若是要記住登陸狀態就須要cookies

django的cookie由session_key和session_data以及expire_data組成,實現是經過setings.py中的'django.contrib.sessions',
每一個域名之下的cookies是不能互相訪問的

實現user的註冊功能

先拷貝register.html到template中,配置url,

url(r'^register/',RegisterView.as_view,name='register'),

而後在views.py中加入RegisterView類

class RegisterView(View):
    def get(self, request):
        return render(request, 'register.html')

在HTML代碼中修改指向

<a style="color:white" class="fr registerbtn" href="{% url 'register' %}">註冊</a>
<a style="color:white" class="fr loginbtn" href="{% url 'login' %}">登陸</a>

修改其css和js文件的地址,這裏介紹第二種修改的方法
首先在html文件中輸入{%load staticfiles%}
而後在須要修改地址的地方輸入{%static '/css/reset.css'%}

加入驗證碼功能

  • 先安裝django-simple-captcha模塊
pip install  django-simple-captcha
  • 根據官方文檔的提示添加captcha到settings.py當中的INSTALLED_APPS
  • 運行makemigrations,migrate
  • 添加實例到urls.py中
urlpatterns += [
    url(r'^captcha/', include('captcha.urls')),
]

而後在forms.py中加入一個新的register_form,在其中加入captchafiled

from django import forms
from captcha.fields import CaptchaField

class RegisterForm(forms.Form):
    email = forms.EmailField(required=True,error_messages={'invalid':'請輸入一個有效的郵箱地址'})
    password = forms.CharField(required=True,min_length=5,error_messages={'invalid':'密碼至少6個字符','required':'請輸入密碼'})
    captcha = CaptchaField(error_messages={'required': '驗證碼錯誤'})

view.py中加入registerview

class RegisterView(View):
#get方法,先實例化一個RegisterForm,將register_form返回到html中用於獲取驗證碼
    def get(self, request): 
        register_form = RegisterForm()
        return render(request, 'register.html',{'register_form':register_form})

    def post(self, request):
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():
            user_name = request.POST.get('email', '')
            pass_word = request.POST.get('password', '')
            is_used = UserProfile.objects.filter(username=user_name)
            if not is_used:
                user = UserProfile()
                user.username = user_name
                user.email = user_name
                user.password = make_password(pass_word)
                user.save()
                send_register_email(user_name)
                return render(request, 'login.html',{})
            else:
                return render(request, 'register.html', {'msg':'該用戶名已經被佔用','register_form':register_form})
        else:
            return render(request, 'register.html',{'register_form':register_form})

修改register.html

<div class="tab-form">
<!--其中的action用於指定提交到哪一個頁面-->
    <form id="email_register_form" method="post" action="{% url 'register' %}" autocomplete="off">
        <input type='hidden' name='csrfmiddlewaretoken' value='gTZljXgnpvxn0fKZ1XkWrM1PrCGSjiCZ'/>
<!--在class裏面加入{%if register_form.email.errors %}errorput用於出錯時高亮-->
        <div class="form-group marb20 {% if register_form.email.errors %}errorput{% endif %}">
            <label>郵&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱</label>
<!--將value填爲上次填寫的value,這樣出錯時不用用戶每次手動填寫value-->
            <input type="text" id="id_email" name="email" value="{{ register_form.email.value }}"
                   placeholder="請輸入您的郵箱地址"/>
        </div>
        <div class="form-group marb8 {% if register_form.errors.password %}errorput{% endif %}">
            <label>密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;碼</label>
            <input type="password" id="id_password" name="password"
                   value="{{ register_form.password.value }}"
                   placeholder="請輸入6-20位非中文字符密碼"/>
        </div>
        <div class="form-group marb8 captcha1 {% if register_form.errors.password %}errorput{% endif %}">
            <label>驗&nbsp;證&nbsp;碼</label>
            {{ register_form.captcha }}
        </div>
        <div class="error btns" id="jsEmailTips">
        <!--用循環的方式將錯誤顯示出來-->
            {% for key,value in register_form.errors.items %}
                {{ value }}
            {% endfor %}
            {{ msg }}
        </div>
        <div class="auto-box marb8">
        </div>
        <input class="btn btn-green" id="jsEmailRegBtn" type="submit" value="註冊並登陸"/>
        {#                        <input type='hidden' name='csrfmiddlewaretoken' value='5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy'/>#}
        {% csrf_token %}
    </form>
</div>
相關文章
相關標籤/搜索