「Flask實戰」魚書項目實戰三

「Flask實戰」魚書項目實戰三

資源介紹參數
資源類別: Python
如遇問題: 聯繫客服/留言反饋
釋放雙眼,帶上耳機,聽聽看~!

flask-python

flask魚書項目實戰


修剪原始數據,獲取真正需要的數據

app下新建一個view_modles文件夾,用來存放view modle,然後新建一個book.py文件處理從yushu_book.py中獲取的原始數據。因為在網頁中,需要獲取作者搜尋關鍵字等信息,而從魚書api中獲取的信息有所不同,所以這個view modle就是用來處理這些原始數據,把他轉化成我們需要的數據結構的模塊。

├── app
│    ├──forms
│    │    └── BookForm.py
│    ├── web
│    │    ├── __init_.py
│    │    ├── book.py
│    │    ├── setting.py
│    │    └── secure.py
│    ├──libs
│    │    ├── helper.py
│    │    └── HttpRequest.py
│    ├──view_modles
│    │    └── book.py
│    ├──spider
│    │    └── yushu_book.py
│    ├──models
│    │    └── sql_book.py
│    └── __init__.py
├── static 
├── templates
├── fisher.py
# view_modle/book.py

class BookViewModle:
    @classmethod
    def package_single(cls,data,keyword):
        returned = {
            'books':[],
            'total':0,
            'keyword':keyword,
        }

        if data:
            returned['total']= 1
            returned['books']= [cls.__cut_book_data(data)]
        return returned

    @classmethod
    def package_collection(cls,data,keyword):
        returned = {
            'books': [],
            'total': 0,
            'keyword': keyword,
        }

        if data:
            returned['total'] = data['total']
            returned['books'] = [cls.__cut_book_data(book) for book in data['books'] ]
            # 運用列表推導式簡化代碼量
        return returned

    @classmethod
    def __cut_book_data(cls,data):
        book = {
            'title':data['title'],
            'publisher':data['publisher'],
            'pages':data['pages'] or '',   # 這裡當pages的值是null的時候返回空,有利於後期範本渲染
            'price':data['price'] or '',
            'author':'、'.join(data['author']), # 通過join方法快速拼接作者
            'summary':data['summary'] or '',
            'image':data['image'],
        }
        return book

然後在web/book.py接收修剪後的數據。

# web/book.py

·····
from app.view_models.book import BookViewModle

·····

if isbn_or_key == 'isbn':
    result = YuShuBook.search_by_isbn(q)
    result = BookViewModle.package_single(result,q)
else:
    result = YuShuBook.search_by_keyword(q,page)
    result = BookViewModle.package_collection(result,q)

·····

然後就可以看到修剪後的數據效果了。

推倒前面的偽面向對象

發現面向對象中絕大多數都是code>@classmethod,如果面向對象中出現大量可以被作為code>@classmethod的方法,就可以說他是一個偽面向對象,不是用面向對象的思想構建的。例如yushu_book.py下的YuShuBook類,之所以出現這種問題是因為這個類自身並不會去儲存數據,而是把所有數據都返回給了調用方,只是包裝了一系列方法,去除了這個類名,他依然可以調用,所以應該把這些類的特徵儲存在這個類中,而不是返回給調用方。所以重構一下YuShuBook

#spider/yushu_book.py
from app.libs.HttpRequest import HTTP
from flask import current_app

class YuShuBook:
    isbn_url = 'http://t.yushu.im/v2/book/isbn/{}'
    keyword_url = 'http://t.yushu.im/v2/book/search?q={}&start={}&count={}'

    def __init__(self):
        self.total = 0
        self.books = []

    def search_by_isbn(self,isbn):
        url = self.isbn_url.format(isbn)
        # 如果中沒有這個屬性就會從類屬性中去找
        result = HTTP.get(url)
        self.__file_single(result)

    def search_by_keyword(self,keyword,page=1):
        url = self.keyword_url.format(keyword,self.get_start_page(page),current_app.config['PRE_PAGE'])
        result = HTTP.get(url)
        self.__file_conllection(result)

    def __file_single(self,data):
        if data:
            self.total = 1
            self.books.append(data)

    def __file_conllection(self,data):
        if data:
            self.total = data['totak']
            self.books = data['books']

    def get_start_page(page):
        return (page-1) * current_app.config['PRE_PAGE']

推倒整個BookViewModle,重寫view_modles下的book.py

# view_modles/book.py
class BookViewModle:
    def __init__(self,book):
        self.title = book['title']
        self.title = book['title']
        self.publisher= book['publisher']
        self.pages= book['pages']
        self.price = book['price']
        self.author = '、'.join(book['author'])
        self.summary = book['summary']
        self.image= book['image']

class BookCollection:
    def __init__(self):
        self.total = 0
        self.books =[]
        self.keyword = ''

    def fill(self, yushu_book, keyword):
        self.total = yushu_book.total
        self.keyword = keyword
        self.books = [BookViewModle() for book in yushu_book.books]

重寫主視圖函式下的serach視圖函式

#web/book.py
@web.route('/book/search')

·····
from app.view_models.book import BookViewModle
from app.view_models.book import BookCollection
·····

def search():
    form = SearchForm(request.args)
    books = BookCollection()
    if form.validate():
        q = form.q.data.strip()
        page = form.page.data
        isbn_or_key = is_isbn_or_key(q)
        yushu_book = YuShuBook()
        if isbn_or_key == 'isbn':
            yushu_book.search_by_isbn(q)
        else:
            yushu_book.search_by_keyword(q,page)
        books.fill(yushu_book,q)
        return jsonify(books)
        #注意這個時候在查詢是得不到數據的,因為這時候是一個對象實例,python不能把一個實例  序列化,因為之後的範本渲染不需要json所以這裡不需要繼續操作
    else: 
        return jsonify(form.errors) 
        #這裡不採用自訂的錯誤了,直接返回表單驗證的錯誤信息

理解一下這個順序,首先把BookCollection實例化,然後如果表單驗證通過,實例化YuShuBook來接收數據,然後分別判斷isbnkeyword,進行調用類方法來獲取數據,並且儲存在yushu_book這個對象中,最後調用books這個對象的fill方法,來修剪得到的數據,返回我們需要的數據並且存在books這個對象中。整個過程還是挺抽象的。

如果你想返回一個json對象,那麼你可以這樣做


····· import json ····· return json.dumps(books,default=lambda o:o.__dict__) #將return jsonify(books)替換
聲明:本文為原創作品,版權歸作者所有。未經許可,不得轉載或用於任何商業用途。如若本站內容侵犯了原著者的合法權益,可聯繫我們進行處理。

給TA打賞
共{{data.count}}人
人已打賞
0 條回復 A文章作者 M管理員
    暫無討論,說說你的看法吧