統達能源宣布進軍中國大陸電動車市場

台灣統振集團旗下統達能源宣布,將聯合易能電網科技以及中國機車公司奔馬實業,共同進軍中國大陸電動車市場,以電動機車用鋰電池交換系統搶攻中國商機,最快將在2016年下半年於廣東、福建地區成立營運示範據點。

統達能源過去著重歐洲電動自行車店員市場開發,在歐洲已有10%市占率,本次為首度跨入電動機車電源的供應鏈。總經理楊模樺表示,合作夥伴易能電網科技整合了桶達的動力電池系統與台灣IBM的技術,打造「MIT(台灣製造)」的智能化電池交換服務系統,並已在台灣搭配電動機車實際上路。

奔馬實業去年在中國大陸共生產了20萬輛機車,帶來10億元人民幣的營收。本次與統達能源的合作,聚焦在電動機車與電池交換站營運事業。奔馬實業董事長湛玉娟認為,車店分離電池月租致的商業模式能透過電池交換服務系統的管理與遠端監控來提高電池之可靠性、安全性、壽命,降低營運商維護成本,並與物聯網概念結合。她相信,合作夥伴易能的電池交換系統將有效改善中國大陸電動機車的能源供給問題,也能改善電池環保管理問題。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※試算大陸海運運費!

Model 3 接單爆量部分是膨風?Musk:重複訂單將取消

特斯拉(Tesla Motors)平價電動車「Model 3」3 月 31 日亮相一週就狂接了 32.5 萬筆訂單,執行長 Elon Musk 之後更於 4 月 22 日指稱 Model 3 已接獲近 40 萬筆訂單。   不過,許多人對此抱持懷疑態度,認為或許有顧客重複下單導致數據「膨風」,分析師 Anton Wahlman 上週更在 Seeking Alpha 網站發文宣稱,雖然特斯拉限制每人只能預購兩台 Model 3,但他個人卻已成功下了 20 筆訂單。   Yahoo! Finance 的新聞記者隨後也宣稱,只要以不同表格遞交多筆訂單,就能成功突破每人限購 2 台的限制。   Wahlman 宣稱,這意味著特斯拉接獲的 40 萬筆訂單有一部份也許來自投機客,Model 3 龐大的需求可能只是膨風。   對此,Musk 決定重新檢視顧客的下單狀況,並把多餘的訂單全部取消。MarketWatch 2 日報導,Musk 4 月 29 日透過 Twitter 指出,重複的訂單將被刪除,每位客戶都只限購 2 台,而所有訂單中僅有 5% 預購了 2 台 Model 3,因此不太可能有投機客。   儘管如此,投機客瘋狂預購 Model 3,仍代表這款車種深獲顧客期待,畢竟 Model 3 在還未亮相前,搶著掏錢預訂 Model 3 的粉絲們就已在實體門市外排起超長人龍,這樣的熱絡景象真的是前所未見。   現在特斯拉遇到的問題,應該不是需求疲軟、而是訂單太多。有分析師認為,特斯拉當前產能不足以應付爆量需求,未來可能得籌錢擴產、甚至打造第二座組裝廠。   CNBC、Forbes 4 月中報導,巴克萊分析師 Brian Johnson 表示,他估計特斯拉需要另行籌資 30 億美元,才能滿足如雪片飛來的訂單。他說,特斯拉訂單暴增,或許會以需要打造更多汽車和電池工廠為由,尋求額外資金。   從特斯拉生產情況看來,確實有擴產需要。今年第一季,特斯拉交車數量僅有 14,820 輛,低於預期的 16,000 輛。今年全年特斯拉預計交車 80,000~90,000 輛。這讓外界憂心忡忡,擔心該公司無法從小眾車廠,蛻變為大型公司。特斯拉的加州組裝工廠,以往為通用汽車(GM)和豐田(Toyota)的合資企業,年度產能達 50 萬輛,意味特斯拉仍有大幅增產空間,能加裝設備,生產 Model 3。    (本文內容由授權使用;首圖來源: CC BY 2.0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

django學習與實踐

Django簡介

​ Django是一個由Python寫成的開放源代碼的Web應用框架,它最初是被用來開發管理勞倫斯出版集團旗下的一些以新聞內容為主的網站,即CMS(內容管理系統)軟件。 並於2005年7月在 BSD 許可證下發布。這套框架是以比利時的吉普賽爵士吉他手 Django Reinhardt 來命名的。由於 Django 的是在一個快節奏的新聞編輯室環境下開發的,它的目的是使常見的 Web 開發任務,快速和容易。

Django官網:https://www.djangoproject.com/

Django中文網:https://www.django.cn

Django的框架模式

  • Django採用了MTV設計模式

    M Models 模型
    T Templates 模板
    V Views 視圖

Django是一個Web應用框架,他是如何處理請求和響應的

URL ( urls.py )請求調度,當有緩存頁面的時候直接返回內容。
視圖函數( view.py )執行所請求的操作,通常包括讀寫數據庫。
模型( models.py )定義了 Python 中的數據並與之交互。通常包含在一個關係數據庫( MySQL、PostgreSQL SQLite 等),其他數據存儲是可能的( XML、文本文件、LDAP、等)。
請求執行任務后,視圖返回一個 HTTP 響應對象(通常是經過數據處理的一個模板)。可選的:視圖可以保存一個版本的 HTTP 響應對象,返回攜帶一個時間戳,來告訴瀏覽器這個視圖的更新時間。
模板通常返回 HTML 頁面。Django 模板語言提供了 HTML 的語法及邏輯。

安裝

第一行和第三行都可以隨便使用

網絡不好用第三行

pip install Django==2.1
#用國內的鏡像網站,如下
pip install Django==2.1 -i https://pypi.douban.com/simple

導入Django模塊

import django
print(django.get_version())
#結果:
2.1

基本配置

常用命令

查看django版本
python -m django --version
#結果
2.1
創建項目命令,項目名稱是mysite
django-admin startproject mysite
創建應用程序命令,確保在manage.py文件時在同一個目錄
#如果我們在項目外面,先要進入項目里
cd mysite
#windows使用dir查看當前在哪裡,如果有manage.py就代表我們可以正確使用下面的命令
#創建應用程序
python manage.py startapp app01

啟動django

python manage.py runserver
#默認端口是8000
#使用上面的命令就可以了,下面不經常用
#改端口
python manage.py runserver 8080
#改訪問地址和端口
python manage.py runserver 0.0.0.0:8080

生成模型變化遷移文件

python manage.py makemigrations

運行模型遷移文件遷移到數據庫中

python manage.py migrate

創建管理用戶

python manage.py createsuperuser
user:輸入:admin
email:不寫也行
password:輸入:admin123
驗證password:輸入:admin123
 讓你確認:輸入:y
    

注:自動重新加載 runserver,根據需要開發服務器自動重新加載Python代碼為每個請求。您不需要重新啟動服務器代碼更改生效。然而,像添加文件某些操作不觸發重新啟動,所以你必須重新啟動在這些情況下的服務器。

基本目錄結構及作用:
mysite/ # 項目的容器,名字隨便起
manage.py # 命令行實用工具,以各種方式與該Django項目進行交互
mysite/ # 實際的Python項目
init.py # 空文件,導入不出錯
settings.py # 這個Django項目配置
urls.py # 這個Django項目的URL聲明; 一個Django驅動網站的“目錄”
wsgi.py # 一個入口點為WSGI兼容的Web服務器,以滿足您的項目

Django自帶數據庫,我們也可以選擇不更改,項目開發中一般會更改使用的數據庫,更改數據庫配置在settings.py文件里

由於Django內部連接MySQL時使用的是MySQLdb模塊

目前可以使用mysql來代替pymysql了

我們需要去下載mysql
pip install mysql

在settings中修改DATABASES

DATABASES = {
    'default'{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'你的數據庫名稱',
        'USER':'你的用戶名',
        'PASSWORD':'你的密碼',
        'HOST':'127.0.0.1',
        'PORT':'3306',
    }           
}

模板

也在settings里修改,主要放html文件

TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)

靜態文件

也在settings里修改,放css,js等文件

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

路由系統

路由系統就像我們我們的書本的目錄,書本的目錄會告訴你那一頁是什麼,你翻到那一頁就能看到相關的文字,路由系統就是,你對這個路由系統里的一個url地址發起了請求,路由系統會到對應的views函數去進行相關的處理,即這個url要用某個指定的views函數去處理。

來看下示例,django是怎麼規定構造路由的

from app01 import views
urlpatterns = [
    path(r'^login$',views.LoginView),
    path(r'^register$',views.RegisterView),
]
from app1 import views
urlpatterns = [
url(r'^manage1/(\d)', views.manage1),
url(r'^manage2/(?P\w)/(?P\d)', views.manage2),
url(r'^manage3/(?P\w)', views.manage3,{'id':333}),]

注意:

url多傳一個參數,那views對應的函數就要多接收一個參數

要不然會報錯的

二級路由

如果映射url太多了,全寫在一個urls.py文件里顯得繁瑣,所以出現了二級路由

就是項目的urls.py文件負責接收客戶發過來請求它判斷你傳來的東西有沒有它下面應用里的urls.py文件里有沒有,如果有就告訴應用的的urls來接收,讓它去處理,沒有就給你報錯

一級路由寫法

項目的urls.py文件里

from django.urls import path, include
urlpatterns = [
    path(r'app01/',include('app1.urls'))
]

Django是如何處理一個請求的

當用戶請求從您的 Django 的網站頁面,這是該系統遵循以確定哪些 Python 代碼執行的算法:

Django 請求是 URL 配置模塊配置。通常通過值 ROOT_URLCONF 設置,但如果傳入 HttpRequest 對象具有 urlconf 屬性(由中間件設置),它的值將代替的可以使用 ROOT_URLCONF 的設置。
Django 的負載是 Python 模塊並尋找變量 urlpatterns。這是一個 django.conf.urls.url() 實例。
Django 的貫穿每個 URL 模式,從而,在所請求的 URL 匹配的第一個停止。
一旦某個正則表達式相匹配,就運行相對應的視圖函數(或基於類的視圖)。該視圖被傳遞以下參數:
HttpRequest 對象。
如果匹配的正則表達式沒有返回命名組,然後從正則表達式比賽是作為位置參數。
關鍵詞參數是由由正則表達式匹配的任何命名組,由指定的可選參數的任何覆蓋的 kwargs參數 django.conf.urls.url()。
如果沒有正則表達式匹配,或者如果一個異常在這個過程中的任何一點時提出,Django的調用適當的錯誤處理視圖。

官方示例

from django.conf.urls import url

from . import views

urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),]

注意事項:

要捕獲從URL中的值,用 括號括起來,會當參數傳入views視圖

沒有必要添加一個斜體,因為每個URL都有。例如,它^articles不是^/articles.

在‘r’前面的每一個正則表達式是可選的,建議,它告訴python字符串是原始的,沒有字符要轉義

舉例請求:

請求/articles/2005/03/將匹配列表中的第三項,Django將調用該函數。

views.month_archive(request,‘2005’,‘03’)

/articles/2005/3/ 不會匹配任何 URL 模式,因為在列表中的第三項中需要兩位数字的月份。

/articles/2003/ 將匹配的列表,而不是第二個第一圖案,因為該圖案,以便測試,第一個是在第一測

試通過。隨意利用順序插入特殊情況是這樣的。在這裏,Django的將調用該函數

views.special_case_2003(request)

/articles/2003 不匹配任何這些模式,因為每個模式要求 URL 以斜線結束。

/articles/2003/03/03/ 將匹配的最終格局。Django 的將調用該函數。

views.article_detail(request,’2003′, ’03’, ’03’)

命名組

上面的例子使用了簡單的,非命名的正則表達式組(通過括號)來捕獲URL的位,並通過他們的位置參數的視圖,在更高級的用法,它可以使用命名正則表達式組成來捕獲URL位,將它們作為關鍵字參數傳遞給視圖。

例子:

from django.conf.urls import url
from .import views
urlpatterns = [
    url(r'^articles/2003/$',views.special_case_2003),
    url(r'^articles/(?P[0-9]{4})/$',views.year_archive),
    url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[0-9]{2})/$',views.article_detail),
]

這正好完成同樣的事情,前面的例子,一個細微的差別:捕獲的值傳遞給查看功能作為關鍵字參數,而不是位置參數。例如:

請求/articles/2005/03/會調用函數來代替,views.month_archive(request, year=’2005′,month=’03’)views.month_archive(request, ‘2005’, ’03’)
請求/articles/2003/03/03/會調用該函數,views.article_detail(request, year=’2003′,month=’03’, day=’03’)
在實踐中,這意味着你的 URLconf 稍微更明確,不容易參數順序錯誤 – 你可以在你的意見’函數定義重新排序的參數。當然,這些優點來在簡短的費用; 一些開發任務命名組的語法醜陋,太冗長。

匹配/分組算法
這裏的URL配置解析器遵循算法,相對於正則表達式命名組與非命名組:

如果有任何命名參數,它會使用這些,而忽略非命名參數。
否則,它會通過所有非命名參數作為位置參數。
在這兩種情況下,被賦予按任何額外的關鍵字參數傳遞額外的選項來查看功能也將被傳遞給視圖請求/articles/2005/03/會調用函數來代替,views.month_archive(request,year=‘2005’,month=‘03’)

3> What the URLconf searches against
The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name.

For example, in a request to https://www.example.com/myapp/, the URLconf will look for myapp/.

In a request to https://www.example.com/myapp/?page=3, the URLconf will look for myapp/.

該URL配置不看請求方法。換言之,所有的請求的方法,GET,POST 等將被路由到為相同的URL,相同的功能。

4> 捕獲的參數總是字符串
每個捕獲的參數發送到視圖作為普通的 Python 字符串,無論什麼樣的匹配正則表達式匹配。

例如,在該URL配置行:

url(r’^articles/(?P[0-9]{4})/$’, views.year_archive),
…的 year參數傳遞給 views.year_archive()將是一個字符串,

不是一個整數,即使 [0-9]{4} 將只匹配整数字符串。

5> 指定view的默認設置
一個方便的技巧是你的觀點的論據指定默認參數。下面是一個例子的 RLconf 和看法:

urlconf

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^blogs/$',views.page),
    url(r'blog/page(?P[0-9]+)/$',views.page),
]

views.py

def page(request,num='1'):
    '''
    處理語句塊
    '''

視圖層

對邏輯負責處理用戶的請求並返回相應,返回可以是HTML內容的網頁,或者重定向,或者錯誤,或者字典

每個應用都有views.py文件

返回快捷鍵功能

render()
render(request,template_name,context=None,content_type=None,status=None,using=None)[source]

結合給定的模板與一個給定的上下文,返回一個字典HttpRespone在渲染文本對象

所需的參數

template_name 一個模板的使用或模板序列名稱全稱。如果序列是給定的,存在於第一個模板將被使用。

可選參數

context 一組字典的值添加到模板中,默認情況下這是一個孔子點

content_type MIME類型用於生成文檔

status 為響應狀態代碼,默認值為200

using這個名字一個模板引擎將使用的模板

例子:

from django.shortcuts import render
def my_view(request):
    return render(request,'myapp/index.html',{'fpp','bar',},content_type='application/xhyml+xml')

重定向

redirect()

redirect(to,permanent=False,*args,**kwargs)[source]
默認情況下,為臨時重定向,通過permanent=True設置永久重定向

例子:

def my_view(request):
    ...
    return redirect('/some/url/')
def my_view(request):
    ...
obj = MyModel.opbjects.get(...)
return redirect(object,permanent=True)

請求和響應對象

django使用請求和響應對象在系統間傳遞狀態

當請求一個頁面時,django創建一個HttpRequest對象包含原數據的請求,然後django加載適當的視圖,通過HttpRequest作為視圖函數的第一個參數,每個視圖負責返回一個HttpResponse目標

HttpRequest對象

HttpRequest.scheme

一個字符串表示請求的計劃方案(HTTP或者HTTPS)

通常HttpRequest.path

一個字符串的完整路徑的請求

HTTPRequest.method

請求HTTP的方法,這裏保證要大寫

#偽代碼
if request.method == 'GET':
    '''
    執行業務代碼
    返回結果
    '''
    return HttpResponse('結果')
#業務邏輯:如果請求來的是GET,你返回個GET字符串
#真代碼
class GETView(objects):
    def getview(self,request):
        if request.method == 'GET':
            return HttpResponse('GET')
  
if request.method == 'GET':
    return HttpResponse('GET')
elif request.method == 'POST':
    return HttpResponse('POST')
elif request.method == 'PUT':
    return HttpResponse('PUT')
elif request.method == 'DELETE':
    return HttpResponse('DELETE')
else:
    return HttpResponse('來了老弟!')

字典包含所有給定的HTTP GET 參數對象

HttpRequest.GET

字典包含所有給定的HTTP POST 參數對象,提供請求包含表單數據

HttpRequest.POST

一個標準的python字典,包含所有的COOKIES,KEY和VALUES都是字符串

字典包含所有上傳的文件

HttpRequest.FILES

語法:

HttpRequest.FILES
filename #上傳的文件名
content_type #上傳文件的類型
content #上傳文件的內容

HttpRequest.META

一個標準的Python字典包含所有可用的HTTP頭,可用標題取決於客戶端和服務器。以下是例子

CONTENT_LENGTH 請求體的長度(一個字符串
CONTENT_TYPE 請求體的類型
HTTP_ACCEPT 為響應–可以接受的內容類型
HTTP_ACCEPT_ENCODING 接受編碼的響應
HTTP_ACCEPT_LANGUAGE 接受語言的反應
HTTP_HOST 客戶端發送的HTTP主機頭
HTTP_REFERER 參考頁面
HTTP_USER_AGENT 客戶端的用戶代理字符串
QUERY_STRING 查詢字符串,作為一個單一的(分析的)字符串
REMOTE_ADDR 客戶端的IP地址
REMOTE_HOST 客戶端的主機名
REMOTE_USER 用戶通過Web服務器的身份驗證
REQUEST_METHOD 字符串,如”GET”或”POST”
SERVER_NAME 服務器的主機名
SERVER_PORT 服務器的端口(一個字符串)

HttpResponse對象

對於HttpRequest 對象來說,是由django自動創建的,但是,HttpResponse 對象就必須我們自己創建。每個 view 請求處理方法必須返回一個 HttpResponse 對象。

HttpResponse 類在 django.http.HttpResponse

字符串使用:
典型的用法是通過頁面的內容,為一個字符串

for django.http import HttpResponse
response = HttpResponse("hello world")
response = HttpResponse("hello world",content_type="text/plain")

如果你想添加內容的增量

response = HttpResponse()
response.write("hello world")
response.write("你好")
#特性與方法:
HttpResponse.content
一個bytestring代表內容HttpResponse.charset

一個字符串的字符集表示的響應將編碼

HttpResponse.status_code

HTTP狀態代碼為響應碼

HttpResponse.streaming

這個屬性永遠為假,一般用於中間件

HttpResponse.closed

方法:

先寫的代碼,后寫的註釋

HttpResponse.__init__(content='',content_type=None,status=200,reason=None,charset=None)[source]
#實例化類自動執行的方法
HttpResponse.__setitem__(header,value)
#為給定值給定的標題名稱,都是字符串
HttpResponse.__delitem__(header)
#刪除標題的名稱,不區分大小寫
HttpResponse.__getitem__(header)
#獲取給定標題名稱。不區分大小寫。
HttpResponse.has_header(header)

#檢查是否具有給定名稱的一個標題
HttpResponse.setdefault(header, value)

#設置一個標題,除非它已經設置。
HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)

#設置一個cookie。參數跟標準庫的Cookie對象差不多
HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True)

#加密cookice,可以用 HttpRequest.get_signed_cookie() 獲取,當然你也可以加鹽
HttpResponse.delete_cookie(key, path='/', domain=None)

#刪除Cookie與給定鍵。

#HttpResponse子類:
class HttpResponseRedirect[source]

構造函數的第一個參數是必需的路徑redirectto,這是一個完全合格的URL,一個合格的URL(https://www.baidu.com/搜索/),沒有一個絕對的路徑(例如:域搜索//),甚至是相對路徑(如‘/’),

optionalconstructor參數。請注意,這將返回一個HTTP狀態代碼302。
class HttpResponsePermanentRedirect[source]

像httpresponseredirect,但它返回一個永久重定向(HTTP狀態代碼301)而不是“發現”的重定向(狀態代碼302)
class HttpResponseNotModified[source]

構造函數不帶任何參數和NO含量應該被添加到這一反應。使用指定一個頁面沒有被modifiedsince用戶的最後一個請求(狀態代碼304)。
class HttpResponseBadRequest[source]

就像HttpResponse但使用400狀態碼
class HttpResponseNotFound[source]

就像HttpResponse但使用404狀態碼
class HttpResponseForbidden[source]

就像HttpResponse但使用403狀態碼
class HttpResponseNotAllowed[source]

像HttpResponse,但使用405狀態碼。第一argumentto構造函數要求准許清單的方法(如(get,后])
class HttpResponseGone[source]

就像HttpResponse但使用410狀態碼
class HttpResponseServerError[source]

就像HttpResponse但使用500狀態碼

模板層

作為一個Web框架,Django需要模板,模板包含所需的HTML輸出靜態部分以及動態內容插入。
模板的執行
from datetime import datetime
def current_datetime(request):
    now = datetime.datetime.now()
    html = "it is now %s" % now
    return HttpResponse(html)

from django import template
t = template.Templatge("my name is {{name}}")
c = template.Context({"name":"老王"})
print(t.render(c))


import datetime
from django import template
import DjangoDemo.settings
now = datetime.datetime.now()
fp = open(settings.BASE_DIR+"/templates/home/index.html")
t = template.Template(fp.read())
fp.close()
html = t.render(template.Context({'current_date':now}))
return HttpResponse(html)

from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
    now = datetime.datetime.now()
    t = get_template('current_datetime.html')
    html = t.render(Content({'current_date':now}))
    return HttpResponse(html)
reurn render_to_response("Account/login.html",data,context_instance=RequestContext(request))

模板語言

模板中也有自己的語言,該語言實現數據展示
{{item}}
{% for item in item_list %}
    {{item}}
{% endfor %}
forloop.counter
forloop.first
forloop.last
{% if ordered_warranty %}
    {% else %}
{% endif %}
母板:{% block title %}{% endblock %}
子板: {% extends"base.html" %}
幫助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}

自定義simple_tag

在app中創建templatetags模塊

創建任意名字的.py文件

!/usr/bin/env python
coding:utf-8

from django import template
from django.utils.safestring import makesafe
from django.template.base import resolve_variable,Node,TemplateSyntaxError
register = template.Libary()
@register.simple_tag
def my_simple_time(a1,a2,a3):
    return a1+a2+a3
@register.simple_tag
def my_input(id,arg):
    result = "    "%(id,arg)
    return mark_safe(result)

在使用自定義simple_tag的html文件中導入之前創建任意名字的.py文件

{% load xx %}
//使用simple_tag
{% my_simple_time 123 %}

在settings中配置當前app,不然django無法找到自定義的simple_tag

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
)

Models層

Django提供了一個抽象層(Model)的構建和管理Web應用程序的數據

每個模型是一個python類,子類 django.db.models.model

模型中的每個屬性代表數據庫中的一個字段。

例子:

from django.db import models
class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

參數與字段

models.AutoField
#自增=int(11),如果沒有的化,默認會生成一個名稱為id的列,如果要显示的自定義的一個自增列,必須將給列設置為主鍵,主鍵設置方式:primary_key=True
models.CharField
#字符串字符段,必須有max_length參數
models.BooleanField
#布爾類型=tinyint(1),不能為空,Blank=True
models.ComaSeparatedlntegerField
#用逗號分隔的数字=varchar,繼承CharField,所以必須max_length參數
models.DateField
#日期類型 date,對於參數,auto_now=True則每次更新都會更新這個事件,auto_now_add則只是第一次創建添加,之後的更新不再改變
models.DateTimeField
#日期類型 datetime 同DateField參數一樣
models.Decimal
#十進制小數類型=decimal,必須制定整數位max_digits和小數位decimal_places
models.EmailField
#字符串類型(正則表達式郵箱)=varchar,對字符串進行正則表達式
models.FloatField
#浮點類型=double
models.IntegerField
#整型
models.BigIntegerField
#長整型
integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
models.IPAddressField
#字符串類型(ipv4正則表達式)
models.GenericIPAddressField
#字符串類型(ipv4和ivp6是可選的),參數protocol可以是:both、ipv、ipv6,驗證時,會根據設置報錯
models.NullBooleanField
#允許為空的布爾類型
models.PositivenlntegerField
#正integer
models.PositiveSmallIntegerField
#正smallinteger
models.SlugField
#減號、下劃線、字母、数字
models.SmallInterField
#数字,數據庫中的字段有:tinyint、smallint、int、bigint
models.TextField
#字符串=longtext
models.TimeField
#時間 HH:MM[:ss[.uuuuuuu]]
models.URLField
#字符串,地址正則表達式
models.BinaryField
#二進制
models.ImageField
#圖片
models.FilePathField
#文件
null=True
#數據庫中字段是否可以為空
blank=True
#django的Admin中添加數據是是否允許空值
primary_key=False
#主鍵,對AutoField設置主鍵后,就會代替原來的自增id列
auto_now
#自動創建,無論添加或修改,都是當前操作的時間
auto_now_add
#自動創建愛你,永遠是創建時的時間
choices
#choices例子
GENDER_CHOICE = (
(u'M',u'Male'),
(u'F',u'Female'),
)
gender = models.CharField(max_length=2,choices=GENDER_CHOICE)
max_length
default
#默認值
verbose_name
#Admin中字段的显示名稱
nameidb_column
#數據庫中的字段名稱
unique=True
#不允許重複
db_index=True
#數據庫索引
editable=True
#在Admin里是否可編輯
error_messages=None
#錯誤提示
auto_created=False
#自動創建

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※試算大陸海運運費!

【Elasticsearch 7 探索之路】(三)倒排索引

上一篇,我們介紹了 ES 文檔的基本 CURE 和批量操作。我們都知道倒排索引是搜索引擎非常重要的一種數據結構,什麼是倒排索引,倒排索引的原理是什麼。

1 索引過程

在講解倒排索引前,我們先了解索引創建,下圖是 Elasticsearch 中數據索引過程的流程。

從上圖可以看到,文檔未在 ES 中進行索引,而是 由 Analyzer 組件對其執行一些操作並將其拆分為 token/term。然後將這些術語作為倒排索引存儲在磁盤中。假設我們有兩個名為 name 和 age 字段,當要將文檔索引到 ES 時,Analyzers 組件 以某些定界符(有默認定界符,例如空格,句號等)將它們分割開獲取 token,再對每個 token 應用特定的過濾器。經過分析的這些標記稱為 term。然後將這些 term 針對該字段)存儲在倒排列表中。

2 倒排索引

2.1 正排與倒排索引

一般在我們閱讀圖書,我們會根據目錄快速定位想要閱讀的章節,過了一段時間,你想要的回顧之前某一個知識點,你發現從目錄難以查找到對應的地方,這時你可能就會從索引頁從去查找對應內容索引,從而找到頁碼。

搜索引擎其實跟我們的使用圖書很相似,下面我來對圖書和搜索引擎進行一個簡單的類比,來看一下搜素引擎中正排和倒排索引。

  • 圖書
    • 正排索引-目錄頁
    • 倒排索引-索引頁
  • 搜索引擎
    • 正排索引-文檔 Id 到文檔內容和單詞的關聯
    • 倒排索引-單詞到文檔 Id 的關係

2.2 倒排索引的核心組成

舉個例子,假設我們有 3 個文檔:

Doc 1:breakthrough drug for schizophrenia

Doc 2:new schizophrenia drug 

Doc 3:new approach for treatment of schizophrenia

經過分析,文件中的術語如下

文檔 分詞結果
Doc 1 breakthrough,drug,for,schizophrenia
Doc 2 new,schizophrenia,drug
Doc 3 new,approach,for,treatment,of

倒排列表的元數據結構:

(DocID;TF;<POS>)

其中:

  • DocID:出現某單詞的文檔ID

  • TF(詞頻):單詞在該文檔中出現的次數

  • POS:單詞在文檔中的位置

則它們生成的倒排索引

單詞 逆向文檔頻率 倒排列表(DocID;TF; ))
breakthrough 1 (1;1;<1>)
drug 2 (1;1;<2>),(2;1;<3>)
for 2 (1;1;<3>),(3;1;<3>)
schizophrenia 2 (1;1;<4>),(2;1;<2>)
new 2 (2;1;<1>),(3;1;<1>)
approach 1 (3;1;<2>)
treatment 1 (3;1;<4>)
of 1 (3;1;<5>)
  • ES 倒排索引包含兩個部分

    • 單詞詞典 (Term Dictionary),索引最小單位,記錄所有文檔的單詞,記錄單詞到倒排列表的關聯關係
      • 單詞詞典一般都會非常多,通過 B+ 樹或 Hash 表方式以滿足高性能的插入與查詢
    • 倒排列表(Posting List)-由倒排索引項(Posting)組成
      • 文檔 ID
      • 詞頻 TF,該單詞在文檔中出現的次數,用於相關性評分
      • 位置(Position),單詞在文檔中分詞的位置。用於語句搜索(phrase query)
      • 偏移(Offset),記錄單詞的開始結束位置,實現高亮显示

ES 也可以指定對某些字段不做索引

  • 優點:節省存儲空間
  • 缺點:字段無法被搜索

3 總結

在之前文章說了 ES 的文檔是基於 JSON 格式,在我們創建索引的時候,對每一個文檔記錄對應索引相關的信息。在對倒排索引進行搜索時,查詢單詞是否在單詞字典,獲取單詞在倒排列表的指針,獲取有該單詞單詞的文檔 Id 列表,通過 ES 的倒排索引,我們輕易對全文進行快速搜素。

系列文章

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

遏制空污 新德里裝空污預警系統

摘錄自2018年10月2日中央社新德里報導

印度新德里空氣污染嚴重程度經常位居世界前幾名,新德里高層官員表示,2018年在進入空污嚴重的冬天前,空污預警系統即將啟用,預計在10月底或11月初安裝,可預測兩天後的空氣品質,以提前遏制空污。

空污系統安裝好後,將從印度中央污染控制局(Central Pollution Control Board,CPCB)、德里污染控制委員會(Delhi Pollution Control Committee)和空氣品質及天氣預測與研究系統機構(System of Air Quality & Weather Forecasting and Research,SAFAR)旗下的36個空氣品質監測站獲得數據,同時從美國國家航空暨太空總署(NASA)衛星獲取即時氣候資料,綜合研判後,對空氣品質進行預測。

協助這項預警系統設置的印度熱帶研究所普恩分所(Indian Institute of Tropical Meteorology-Pune)科學家谷德表示,系統安裝後的第一年,僅空污濃度指標PM2.5(細懸浮微粒)數據被輸入系統,未來幾年將把PM10、二氧化硫(SO2)、二氧化氮(NO2)濃度等數據都納入系統,使空污預測更加準確。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※試算大陸海運運費!

研擬非洲送電到中東 波灣六國還要減少石油依賴

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

台中搬家,彰化搬家,南投搬家前需注意的眉眉角角,別等搬了再說!

Python多線程與隊列

Python多線程與Queue隊列多線程在感官上類似於同時執行多個程序,雖然由於GIL的存在,在Python中無法實現線程的真正并行,但是對於某些場景,多線程仍不失為一個有效的處理方法:

1,不緊急的,無需阻塞主線程的任務,此時可以利用多線程在後台慢慢處理;
2,IO密集型操作,比如文件讀寫、用戶輸入和網絡請求等,此時多線程可以近似達到甚至優於多進程的表現;

多線程的基本使用不再贅述,以下語法便可輕鬆實現:

1 def task(args1, args2):
2     pass
3 
4 Thread(
5     target=task,
6     args=(args1, args2)
7 ).start()

這裏我們重點關注線程通信。

假設有這麼一種場景:有一批源數據,指定一個操作係數N,需要分別對其進行與N的加減乘除操作,並將結果匯總。
當然這裏的加減乘除只是一種簡單處理,在實際的生產環境中,它其實代表了一步較為複雜的業務操作,並包含了較多的IO處理。

自然我們想到可以開啟多線程處理,那麼緊接着的問題便是:如何劃分線程,是根據處理步驟劃分,還是根據源數據劃分?

對於前者,我們把涉及的業務操作單獨劃分位一個線程,即有4個線程分別進行加減乘除的操作,顯然上一個線程的結果是下一個線程的輸入,這類似於流水線操作;

而後者則是把源數據分為若干份,每份啟動一個線程進行處理,最終把結果匯總。一般來說,我們推薦第一種方式。因為在一個線程中完成所有的操作不如每步一個線程清晰明了,

尤其是在一些複雜的場景下,會加大單個線程的出錯概率和測試難度。

那麼我們將開闢4個線程,分別執行加減乘除操作。最後一個除法線程結束則任務完成:

 

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 
 4 from Queue import Queue
 5 from threading import Thread
 6 
 7 
 8 class NumberHandler(object):
 9     def __init__(self, n):
10         self.n = n
11 
12     def add(self, num):
13         return num + self.n
14 
15     def subtract(self, num):
16         return num - self.n
17 
18     def multiply(self, num):
19         return num * self.n * self.n
20 
21     def divide(self, num):
22         return num / self.n
23 
24 
25 class ClosableQueue(Queue):
26     SENTINEL = object()
27 
28     def close(self):
29         self.put(self.SENTINEL)
30 
31     def __iter__(self):
32         while True:
33             item = self.get()
34             try:
35                 if item is self.SENTINEL:
36                     return
37                 yield item
38             finally:
39                 self.task_done()
40 
41 
42 class StoppableWorker(Thread):
43     def __init__(self, func, in_queue, out_queue):
44         super(StoppableWorker, self).__init__()
45         self.in_queue = in_queue
46         self.out_queue = out_queue
47         self.func = func
48 
49     def run(self):
50         for item in self.in_queue:
51             result = self.func(item)
52             self.out_queue.put(result)
53             print self.func
54 
55 
56 if __name__ == '__main__':
57     source_queue = ClosableQueue()
58     add_queue = ClosableQueue()
59     subtract_queue = ClosableQueue()
60     multiply_queue = ClosableQueue()
61     divide_queue = ClosableQueue()
62     result_queue = ClosableQueue()
63 
64     number_handler = NumberHandler(5)
65 
66     threads = [
67         StoppableWorker(number_handler.add, add_queue, subtract_queue),
68         StoppableWorker(number_handler.subtract, subtract_queue, multiply_queue),
69         StoppableWorker(number_handler.multiply, multiply_queue, divide_queue),
70         StoppableWorker(number_handler.divide, divide_queue, result_queue),
71     ]
72 
73     for _thread in threads:
74         _thread.start()
75 
76     for i in range(10):
77         add_queue.put(i)
78 
79     add_queue.close()
80     add_queue.join()
81     print 'add job done...'
82     subtract_queue.close()
83     subtract_queue.join()
84     print 'subtract job done...'
85     multiply_queue.close()
86     multiply_queue.join()
87     print 'multiply job done...'
88     divide_queue.close()
89     divide_queue.join()
90     print 'divide job done...'
91     result_queue.close()
92 
93     print "%s items finished, result: %s" % (result_queue.qsize(), result_queue)
94 
95     for i in result_queue:
96         print i

運行結果:

線程執行日誌:

 

 

 總的結果:

 

 可見線程交叉運行,但是任務卻是順序結束,這符合我們的預期。

值得注意的是,我們在ClosableQueue定義了一個close()方法,通過放入一個特殊的類變量SENTINEL告訴隊列應該關閉。此外,由於直接加減乘除結果不變,因此我特意乘了兩次來便於我們判斷結果。

總結:

1. Queue是一種高效的任務處理方式,它可以把任務處理流程劃分為若干階段,並使用多條python線程來同時執行這些子任務;

2. Queue類具備阻塞式的隊列操作、能夠指定緩衝區尺寸,而且還支 持join方法,這使得開發者可以構建出健壯的流水線。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※試算大陸海運運費!

java property 配置文件管理工具框架,避免寫入 property 亂序

property

是 java 實現的 property 框架。

特點

  • 優雅地進行屬性文件的讀取和更新

  • 寫入屬性文件后屬性不亂序

  • 靈活定義編碼信息

  • 使用 OO 的方式操作 property 文件

  • 支持多級對象引用

變更日誌

快速開始

環境依賴

Maven 3.x

Jdk 1.7+

Maven 引入依賴

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>property</artifactId>
    <version>0.0.4</version>
</dependency>

入門案例

讀取屬性

PropertyBs.getInstance("read.properties").get("hello");

read.properties 為文件路徑,hello 為存在的屬性值名稱。

讀取屬性指定默認值

final String value = PropertyBs.getInstance("read.properties")
                .getOrDefault("hello2", "default");

read.properties 為文件路徑,hello2 為不存在的屬性值名稱,default 為屬性不存在時返回的默認值。

設置屬性

PropertyBs.getInstance("writeAndFlush.properties").setAndFlush("hello", "world-set");

writeAndFlush.properties 為文件路徑,hello 為需要設置的屬性信息。

引導類方法概覽

序號 方法 說明
1 getInstance(propertyPath) 獲取指定屬性文件路徑的引導類實例
2 charset(charset) 指定文件編碼,默認為 UTF-8
3 get(key) 獲取 key 對應的屬性值
4 getOrDefault(key, defaultValue) 獲取 key 對應的屬性值,不存在則返回 defaultValue
5 set(key, value) 設置值(內存)
6 remove(key) 移除值(內存)
7 flush() 刷新內存變更到當前文件磁盤
9 flush(path) 刷新內存變更到指定文件磁盤
10 set(map) 設置 map 信息到內存
11 set(bean) 設置 bean 對象信息到內存
12 asMap() 返回內存中屬性信息,作為 Map 返回
13 asBean(bean) 返回內存中屬性信息到 bean 對象中

對象

簡介

我們希望操作 property 可以想操作對象一樣符合 OO 的思想。

設置值

User user = new User();
user.setName("hello");
user.setHobby("hobby");

final long time = 1574147668411L;
user.setBirthday(new Date(time));

PropertyBs propertyBs = PropertyBs.getInstance("setBean.properties")
        .set(user);

Assert.assertEquals("hobby", propertyBs.get("myHobby"));
Assert.assertEquals("1574147668411", propertyBs.get("birthday"));

讀取值

PropertyBs propertyBs = PropertyBs.getInstance("setBean.properties"
        .set("myHobby", "play")
        .set("birthday", "1574147668411");
User user = new User();
propertyBs.asBean(user);
Assert.assertEquals("play", user.getHobby());
Assert.assertEquals(1574147668411L, user.getBirthday().getTime());

對象定義

  • User.java
public class User {

    private String name;

    @PropertyField("myHobby")
    private String hobby;

    @PropertyField(converter = DateValueConverter.class)
    private Date birthday;

}

@PropertyField 註解

序號 屬性 默認值 說明
1 value 當前字段名稱 對應的 property 屬性名稱
2 converter 默認轉換實現 DefaultValueConverter 對當前字段進行屬性的轉換處理

自定義轉換類

  • DateValueConverter.java

這個就是我們針對 Date 類型,自己實現的處理類型。

實現如下:

public class DateValueConverter implements IValueConverter {

    @Override
    public Object fieldValue(String value, IFieldValueContext context) {
        return new Date(Long.parseLong(value));
    }

    @Override
    public String propertyValue(Object value, IPropertyValueContext context) {
        Date date = (Date)value;
        return date.getTime()+"";
    }

}

集合

說明

有時候一個屬性可能是集合或者數組,這裏暫時給出比較簡單的實現。

將字段值直接根據逗號分隔,作為屬性值。

測試案例

UserArrayCollection userArrayCollection = buildUser();
PropertyBs propertyBs = PropertyBs.getInstance("setBeanArrayCollection.properties")
        .set(userArrayCollection);
Assert.assertEquals("array,collection", propertyBs.get("alias"));
Assert.assertEquals("array,collection", propertyBs.get("hobbies"));

對象定義

  • UserArrayCollection.java
public class UserArrayCollection {

    private List<String> alias;

    private String[] hobbies;
}

暫時只支持 String 類型,不想做的過於複雜。

後期將考慮添加各種類型的支持。

多級對象

說明

有時候我們在一個對象中會引用其他對象,比如 對象 a 中包含對象 b。

這裏採用 a.b.c 這種方式作為屬性的 key, 更加符合使用的習慣。

測試案例

設置

Book book = new Book();
book.name("《海底兩萬里》").price("12.34");
UserEntry user = new UserEntry();
user.name("海倫").book(book).age("10");
PropertyBs propertyBs = PropertyBs.getInstance("setBeanEntry.properties")
        .set(user);
Assert.assertEquals("海倫", propertyBs.get("name"));
Assert.assertEquals("10", propertyBs.get("age"));
Assert.assertEquals("《海底兩萬里》", propertyBs.get("book.name"));
Assert.assertEquals("12.34", propertyBs.get("book.price"));

讀取

Map<String, String> map = new HashMap<>();
map.put("name", "海倫");
map.put("age", "10");
map.put("book.name", "《海底兩萬里》");
map.put("book.price", "12.34");
UserEntry userEntry = new UserEntry();
PropertyBs.getInstance("setBeanEntry.properties")
        .set(map)
        .asBean(userEntry);
Assert.assertEquals("UserEntry{name='海倫', age=10, book=Book{name='《海底兩萬里》', price=12.34}}",
        userEntry.toString());

對象定義

  • UserEntry.java
public class UserEntry {

    private String name;

    private String age;

    @PropertyEntry
    private Book book;

}
  • Book.java
public class Book {

    private String name;

    private String price;

}

@PropertyEntry 說明

@PropertyEntry 註解用來標識一個字段是否採用多級對象的方式表示。

這個註解只有一個屬性,就是 value(),可以用來給當前字段指定一個別稱,和 @PropertyField 別稱類似。

後續特性

  • 提供更多內置的類型轉換實現

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※試算大陸海運運費!

使用Spring安全表達式控制系統功能訪問權限

一、SPEL表達式權限控制

spring security 3.0開始已經可以使用spring Expression表達式來控制授權,允許在表達式中使用複雜的布爾邏輯來控制訪問的權限。Spring Security可用表達式對象的基類是SecurityExpressionRoot。

表達式函數 描述
hasRole([role]) 用戶擁有指定的角色時返回true (Spring security默認會帶有ROLE_前綴),去除前綴參考
hasAnyRole([role1,role2]) 用戶擁有任意一個指定的角色時返回true
hasAuthority([authority]) 擁有某資源的訪問權限時返回true
hasAnyAuthority([auth1,auth2]) 擁有某些資源其中部分資源的訪問權限時返回true
permitAll 永遠返回true
denyAll 永遠返回false
anonymous 當前用戶是anonymous時返回true
rememberMe 當前用戶是rememberMe用戶返回true
authentication 當前登錄用戶的authentication對象
fullAuthenticated 當前用戶既不是anonymous也不是rememberMe用戶時返回true
hasIpAddress('192.168.1.0/24')) 請求發送的IP匹配時返回true

部分朋友可能會對Authority和Role有些混淆。Authority作為資源訪問權限可大可小,可以是某按鈕的訪問權限(如資源ID:biz1),也可以是某類用戶角色的訪問權限(如資源ID:ADMIN)。當Authority作為角色資源權限時,hasAuthority(’ROLE_ADMIN’)與hasRole(’ADMIN’)是一樣的效果。

二、SPEL在全局配置中的使用

我們可以通過繼承WebSecurityConfigurerAdapter,實現相關的配置方法,進行全局的安全配置(之前的章節已經講過) 。下面就為大家介紹一些如何在全局配置中使用SPEL表達式。

2.1.URL安全表達式

config.antMatchers("/system/*").access("hasAuthority('ADMIN') or hasAuthority('USER')")
      .anyRequest().authenticated();

這裏我們定義了應用/person/*URL的範圍,只有擁有ADMIN或者USER權限的用戶才能訪問這些person資源。

2.2.安全表達式中引用bean

這種方式,比較適合有複雜權限驗證邏輯的情況,當Spring Security提供的默認表達式方法無法滿足我們的需求的時候。首先我們定義一個權限驗證的RbacService。

@Component("rbacService")
@Slf4j
public class RbacService {
    //返回true表示驗證通過
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        //驗證邏輯代碼
        return true;
    }
    public boolean checkUserId(Authentication authentication, int id) {
        //驗證邏輯代碼
        return true;
    }
}

對於”/person/{id}”對應的資源的訪問,調用rbacService的bean的方法checkUserId進行權限驗證,傳遞參數為authentication對象和person的id。該id為PathVariable,以#開頭表示。

config.antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)")
      .anyRequest().access("@rbacService.hasPermission(request,authentication)");

三、 Method表達式安全控制

如果我們想實現方法級別的安全配置,Spring Security提供了四種註解,分別是@PreAuthorize , @PreFilter , @PostAuthorize 和 @PostFilter

3.1.開啟方法級別註解的配置

在Spring安全配置代碼中,加上EnableGlobalMethodSecurity註解,開啟方法級別安全配置功能。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

3.2 使用PreAuthorize註解

@PreAuthorize 註解適合進入方法前的權限驗證。只有擁有ADMIN角色才能訪問findAll方法。

@PreAuthorize("hasRole('ADMIN')")
List<Person> findAll();

3.3 使用PostAuthorize註解

@PostAuthorize 在方法執行后再進行權限驗證,適合根據返回值結果進行權限驗證。Spring EL 提供返回對象能夠在表達式語言中獲取返回的對象returnObject。下文代碼只有返回值的name等於authentication對象的name才能正確返回,否則拋出異常。

@PostAuthorize("returnObject.name == authentication.name")
Person findOne(Integer id);

3.4 使用PreFilter註解

PreFilter 針對參數進行過濾,下文代碼錶示針對ids參數進行過濾,只有id為偶數才能訪問delete方法。

//當有多個對象是使用filterTarget進行標註
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {

3.5 使用PostFilter 註解

PostFilter 針對返回結果進行過濾,特別適用於集合類返回值,過濾集合中不符合表達式的對象。

@PostFilter("filterObject.name == authentication.name")
List<Person> findAll();

期待您的關注

  • 博主最近新寫了一本書:
  • 本文轉載註明出處(必須帶連接,不能只轉文字):。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

台灣寄大陸海運貨物規則及重量限制?

大陸寄台灣海運費用試算一覽表

打破松下壟斷,特斯拉擬向Samsung SDI採購車用電池

美商特斯拉(Tesla)所生產的電動車所使用之車用蓄電池,至目前仍幾乎都由日本松下(Panasonic)供應,幾乎形成壟斷狀況。日媒報導,特斯拉計畫拓展電池採購對象,目前已與韓商Samsung SDI展開最終協調。

《日經中文網》一篇報導指出,特斯拉為供應需求日漸成長的純電動車所需的蓄電池,計畫推行多樣化採購對象,且與Samsung SDI的合作,目前已到了最終階段。據報導,Samsung SDI的純電動車用鋰電池已送至位於美國加州的特斯拉開發基地,但由於數量較大,因此被認為已到了正式採用前的試驗階段,而非產品試驗用品。

松下所供應的電動車用蓄電池在質、量兩方面一直占有市場優勢,因此佔據電動車市場供應的大宗。松下與特斯拉於2015年在美國內華達州展開的Gigafactory建設計畫仍在持續,且有部分產能陸續投產,預計將在今年七月底初步完工。

Gigafactory原先規劃的產能為2020年時50GWh,但由於特斯拉還發表了儲能設備Powerpack 和Powerwall ,且市場對Tesla Model 3的反應熱烈,使特斯拉客戶對鋰電池的需求大增,因此有擴增Gigafactory產量的計畫。

而目前供應純電動車用鋰電池的廠商,除了松下、Samsung SDI之外,另一主要廠商為韓國LG Chem,但供應量不大。

(照片來源:Samsung SDI)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※試算大陸海運運費!