1. 程式人生 > >沿用Python+Flask+Mysql的web建設技術開發網站

沿用Python+Flask+Mysql的web建設技術開發網站

ref 默認 修改密碼 save esc 代碼 程序 興趣 switch

1 系統概要說明

1.1 開發目的

閑暇時光想看看電影?我要看些什麽好呢?百度推薦出來的爛片也不在其數,如果有一個真實反映影片的平臺該多好,這就是淘智寶的產生,為電影連續劇愛好人群提供一個可以自由言論的平臺,我喜歡的電影我可以發上去,看看別人是否也會喜歡,綜合評價下來,影視愛好者一定能收獲自己最想看的年度好片。

好片是千人的智慧產生,而不摻雜廣告票房目的,如果我們都看過這部片,評論區交流一下一拍即合,也許我們能夠成為好朋友呢?我看你的個人中心你喜歡的電影我都看過,我們是不是就有說不完的話題了呢?

1.2 需求分析

那麽首先,我們需要註冊一個用戶,用戶名和密碼的長度6-12位為宜,註冊用戶後我們需要登錄上去,最好是去個人中心上傳你的頭像,讓更多人註意到你,然後,就可以開始發布一篇新影評了,發布上去後,根據時間的排序,你的影評很快就會被人看到,他們評論了你的影評,也覺得這部電影很好,就會收藏到收藏夾,下次想看電影的時候翻出來看看,或者是給你點了個贊,但是還沒有特別的喜歡,可能只是你的影評寫的不錯。為了賬戶的安全,我們還可以去個人中心定期修改一下密碼,覺得最近的自拍照很好看,也可以更換頭像讓大家看到。

如果我只是一名遊客,我不想註冊新用戶,那麽我可以去排行榜看看大家到底喜歡什麽電影,如果還是看不出來,我可以去詳情頁下載電子書劇情介紹,覺得不錯再去電影院看。每個人都有自己喜歡的電影類型,可以按分類篩選,如果遊客對一部電影早有耳聞,只想看看評價,那麽在搜索框模糊搜索電影的名字,或者主人公的名字,都能夠搜索出來。

2 網站結構設計

2.1 結構分析

技術分享圖片

2.2 開發方案及使用技術

目前市場流行影視網站網站,用戶都可以在上面與一起觀看該電影的人分享自己的看法,對於平臺上,更多的數據不是我們產生,而是用戶的上網行為影響到自己所看的內容,我們稱之為人機交互,也就是我們現在所說的WEB2.0開發模式。

前端框架,使用的是DIV+CSS的布局,同時使用了AJAX技術,提高了用戶的體現。

後端框架,使用的是Python的Flask框架,這是一款累輕量框架。適合開發中小型系統,並且可以快速開發。

2.3 功能用法分析

首頁主要包括:

1) 熱門文章。給用戶推薦平臺上,點擊數量最大的前五本書,讓用戶可以了解大家都喜歡什麽樣的書。

2) 文章列表。每一本書的標題、時間、作者、分享還有簡介的摘要也會以一條條的形式顯示在首頁,而且每一秒都會顯示再新的分享,圖片展示方式更容易吸引眼球。

3) 高級搜索。單一的搜索只能找到書中有過的關鍵字,高級搜索可以將多個條件同時錄入進行搜索。

4) 文章分類。以類別分別顯示文章列表。

5) 註冊。新用戶註冊平臺賬號。

6) 登陸。登錄賬號去管理個人中心中的個人信息。

7) 排行版:查看最近都有哪些熱門電影,越多人喜歡的電影你肯定也會喜歡。

詳情頁是指文章點進去後,顯示文章內容的頁面,其中還包括以下:

1) 推薦文章。推薦你喜歡的文章。

2) 評論。表達用戶對這篇文章的看法。

3) 點贊。覺得寫的好,就點個贊吧。

4) 收藏。把你認為好的,以後還會看收藏起來,在我的個人中心,以後還可以點開來看。

5) 下載。下載電子書,劇情先知道。

對於有以登錄的用戶,平臺還提供了個人中心去管理自己的信息:

1) 上傳頭像。用戶可以自定義自己的頭像,默認是一個黑色的頭像,上傳有自己個性的頭像,可以讓別人更加容易記得自己。

2) 修改密碼。為了賬號安全,定期修改密碼。

3) 我的收藏。把你認為好的,以後還會看收藏起來,在我的個人中心,以後還可以點開來看。

4) 我的發布。自己曾經發布過的文章可以再次打開的看,也可以有不對的地方再次編輯。

5) 我的評論。你對別人的評論,可以在這裏看到,也可刪除你認為說法有誤的評論。

3 模塊詳細設計

3.1 註冊

# 註冊


@app.route(‘/register/‘, methods=[‘GET‘, ‘POST‘])
def register():
if request.method == ‘GET‘:
return render_template(‘register.html‘)
else:
username = request.form.get(‘username‘)
password = request.form.get(‘password‘)
say = request.form.get(‘say‘)
user = User.query.filter(User.username == username).first()
# 判斷用戶名是否存在
if user:
return u‘ username existed‘
else:
user = User(username=username, password=password, say=say)
db.session.add(user)
db.session.commit()
return redirect(url_for(‘login‘))

3.2 登錄

# 登錄

@app.route(/login/, methods=[GET, POST])

def login():

    if request.method == GET:

        return render_template(denglu.html)

    else:

        usern = request.form.get(username)

        passw = request.form.get(password)

        user = User.query.filter(User.username == usern).first()

        # 判斷用戶名是否存在

        if user:

            if user.check_password(passw):

                session[user] = usern  # 字典鍵值

                session[userid] = user.id

                session.permanent = True

                return redirect(url_for(index))

            else:

                return u password error

        else:

            return u username  not existed





# 判斷是否登陸,有則在導航欄顯示用戶名

@app.context_processor

def mycontext():

    usern = session.get(user)

    user = User.query.filter(User.username == usern).first()

    if usern:

        return {username: usern, user: user}

    else:

        return {}





# 登出,清除session

@app.route(/logout)

def logout():

    session.clear()

    return redirect(url_for(index))

3.3 發布



# 發布前登陸裝飾器

def loginFirst(func):  # 參數是函數

    @wraps(func)

    def wrapper(*args, **kwargs):  # 定義個函數將其返回

        if session.get(user):

            return func(*args, **kwargs)

        else:

            return redirect(url_for(login))



    return wrapper  # 返回一個函數
#發布問答
1.編寫要求登錄的裝飾器

from functools import wraps

def loginFirst(func): #參數是函數

@wraps(func)

      def wrapper(*args, ** kwargs): #定義個函數將其返回

          #要求登錄

          return func(*args, ** kwargs)

      return wrapper #返回一個函數

 

2.應用裝飾器,要求在發布前進行登錄,登錄後可發布。

@app.route(/question/,methods=[GET,POST])
@loginFirst
def question():

 

 

#發布前登陸裝飾器

def loginFirst(func):  # 參數是函數

    @wraps(func)

    def wrapper(*args, **kwargs):  # 定義個函數將其返回

        if session.get(user):

            return func(*args, **kwargs)

        else:

            return redirect(url_for(login))

    return wrapper  # 返回一個函數

 

 

3.建立發布內容的對象關系映射。

class Question(db.Model):

4.完成發布函數。

  保存到數據庫。

  重定向到首頁。

 

#登陸前驗證,進入評論進入問答頁

@app.route(/question/,methods=[GET,POST])

@loginFirst

def question():

    if request.method==GET:

        return render_template(question.html)

    else:

        title=request.form.get(title)

        detail = request.form.get(detail)

        author_id = User.query.filter(User.username ==session.get(user)).first().id

        question = Question(title=title, detail=detail, author_id=author_id)

        db.session.add(question)

db.session.commit()


return redirect(url_for(‘index‘))

 

3.4 條件組合搜索

# 查找
@app.route(/search/)
def search():
    qu = request.args.get(q)
    c = ‘‘ if request.args.get(classflyList) == None else request.args.get(classflyList)
    t = -creat_time if request.args.get(creat_time) == None else creat_time if request.args.get(
        creat_time) == 0 else -creat_time
    y = ‘‘ if request.args.get(year) == None else request.args.get(year)
    ques = Question.query.filter(
        or_(
            Question.xiazai.contains(qu), Question.detail.contains(qu)
        ),
        Question.classify.like(% + c + %),
        Question.creat_time.like(% + y + %),
    ).order_by(t).all()
    return render_template(index.html, questions=ques)


# 高級查詢
@app.route(/highSearch/)
def highSearch():
    if request.args.get(click):  # 判斷get請求中是否有這個變量傳入值
        click = request.args.get(click)  # basic.html中獲取click的限定條數
        ques = Question.query.filter(
            Question.click >= click
        ).order_by(-creat_time)
        # 如果該問題點贊數大於click中指定的數字,則查找出來,放到ques,並把ques賦值給questions(全部問答顯示的列表)顯示出來
        return render_template(index.html, questions=ques)

    if request.args.get(comment):  # 判斷get請求中是否有這個變量傳入值
        comment = request.args.get(comment)  # basic.html中獲取comment的限定條數
        com = Question.query.all()  # 獲取Question表中的所有問答信息,存到com
        result = []  # 定義一個空列表result
        for qu in com:  # 如果每一個問答信息中的總評論數大於comment中的評論數,就把內容增加到result列表中
            if len(qu.comment) >= int(comment):
                result.append(qu)
                # 把列表內容賦值給questions
        return render_template(index.html, questions=result)

3.5 收藏

# 收藏
@app.route(/col, methods=[GET, POST])
@loginFirst
def col():
    user = User.query.filter(User.id == session.get(userid)).first()
    context = {
        questions: user.collection.all(),
        tj: Question.query.all()[0:5],
    }

    return render_template(collect.html, **context)

3.6 修改密碼

# 修改密碼
@app.route(/setPassword/<user_id>, methods=[GET, POST])
@loginFirst
def setPassword(user_id):
    if request.method == GET:
        if request.args.get(info):
            info = request.args.get(info)
        else:
            info = None
        return render_template(editPassword.html,info=info)
    else:
        user = User.query.filter(User.id == user_id).first()
        if user:
            if user.check_password(request.form.get(old)):
                user.password = request.form.get(new1)
                db.session.commit()
                info = 修改成功
            else:
                info = 原密碼錯誤
                return redirect(url_for(setPassword,user_id=user_id,info=info))
        else:
            info = 未知錯誤
        return redirect(url_for(personcenter, user_id=user_id, info=info))

3.7 上傳頭像

#上傳頭像
@app.route(/uploadLogo/<user_id>, methods=[GET, POST])
def uploadLogo(user_id):
    user = User.query.filter(User.id == user_id).first()
    edimg = request.files[edimg]
    basepath = os.path.dirname(__file__)  # 當前文件所在路徑
    upload_path = os.path.join(basepath, static/uploads, edimg.filename)  # 註意:沒有的文件夾一定要先創建,不然會提示沒有該路徑
    edimg.save(upload_path)
    user.image = uploads/ + edimg.filename
    db.session.commit()
    return redirect(url_for(personcenter, user_id=user_id));

3.8 評論

# 登陸前驗證,進入評論進入問答頁
@app.route(/question/, methods=[GET, POST])
@loginFirst
def question():
    if request.method == GET:
        return render_template(question.html)
    else:
        xiazai = request.form.get(xiazai)
        title = request.files[title]
        basepath = os.path.dirname(__file__)  # 當前文件所在路徑
        upload_path = os.path.join(basepath, static/fengmian, title.filename)  # 註意:沒有的文件夾一定要先創建,不然會提示沒有該路徑
        title.save(upload_path)  # 存進服務器
        detail = request.form.get(detail)
        author_id = User.query.filter(User.username == session.get(user)).first().id
        classify = request.form.get(classify)
        question = Question(title=http://127.0.0.1:5000/static/fengmian/ + title.filename, xiazai=xiazai, detail=detail, author_id=author_id, classify=classify)
        # question.author=author_id
        db.session.add(question)
        db.session.commit()
        return redirect(url_for(index))

4 數據庫設計

技術分享圖片

4.2 程序模型現實

# 收藏表
Collection = db.Table(
    collection,
    db.Column(id, db.Integer, primary_key=True, autoincrement=True),
    db.Column(q, db.Integer, db.ForeignKey(question.id)),  # 評論對應的文章的id
    db.Column(u, db.Integer, db.ForeignKey(user.id)),  # 收藏用戶的id
)

 

#用戶表
class User(db.Model):
    __tablename__ = user
    # 建立一個表user
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(20), nullable=False)
    _password = db.Column(db.String(200), nullable=False)
    image = db.Column(db.String(100), default=uploads/default_logo.jpg)
    say = db.Column(db.String(50))
    collection = db.relationship(Question, secondary=Collection, backref=db.backref(user, lazy=dynamic),
                                 lazy=dynamic)

    @property
    def password(self):  # 外部使用
        return self._password

    @password.setter
    def password(self, row_password):
        self._password = generate_password_hash(row_password)

    def check_password(self, row_password):
        result = check_password_hash(self._password, row_password)
        return result

# 建立一表question
class Question(db.Model):
    __tablename__ = question

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    detail = db.Column(db.Text, nullable=False)
    xiazai = db.Column(db.Text, nullable=False)
    creat_time = db.Column(db.DateTime, default=datetime.now)
    author_id = db.Column(db.Integer, db.ForeignKey(user.id))
    author = db.relationship(User, backref=db.backref(question))
    classify = db.Column(db.Enum(都市言情, 青春校園, 古裝玄幻, 懸疑驚悚), nullable=False)
    click = db.Column(db.INT, default=0)

 

# 評論表

class Comment(db.Model):
    __tablename__ = comment
    # 建立一個表log
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    author_id = db.Column(db.Integer, db.ForeignKey(user.id))
    question_id = db.Column(db.Integer, db.ForeignKey(question.id))
    creat_time = db.Column(db.DateTime, default=datetime.now)
    detail = db.Column(db.Text, nullable=False)
    question = db.relationship(Question, backref=db.backref(comment, order_by=creat_time.desc))
    author = db.relationship(User, backref=db.backref(comment))

5 系統實現的關鍵算法與數據結構

5.1 背景開關燈的實現

運行JavaScript代碼,添加點擊事件,來響應並改變背景的CSS樣式,則達到開關燈的功能。

function mySwitch() {
    var oBody = document.getElementById("myBody");
    var ogood = document.getElementById("mygood");
    var oOnOff = document.getElementById("myOnOff");

    if (oOnOff.src.match(bulbon)) {

        oOnOff.src = "http://www.runoob.com/images/pic_bulboff.gif";
        oBody.style.backgroundColor = "black";

        oBody.style.color = "white";
         ogood.style.display="none";
    } else {
        oOnOff.src = "http://www.runoob.com/images/pic_bulbon.gif";
        oBody.style.backgroundColor = "white";
        oBody.style.color = "black";
        
         ogood.style.display="block";

    }
}

5.2 圖片與文件的上傳下載實現

一鍵下載電子書,以txt文件形式保存到你的電腦,更方便快捷下次查看

    <span style="width:300px;float:left;margin-top: 230px;margin-left:-235px">電子書下載: <input id="fat-btn"
                                                                                          class="btn btn-default"
                                                                                        type="button"
                                                                                        value=Download
                                                                                        onclick="location.href=‘{{ url_for(‘download‘,filename=‘static‘,question_id=ques.xiazai) }}‘"></span>
# 下載
@app.route(/<filename>/<question_id>)
def download(filename, question_id):
    quest = Question.query.filter(Question.id == question_id).first()  # 從Question表查找出對應的問答id
    context = {
        questions: Question.query.order_by(-creat_time).all()

    }

    return render_template(detail.html, **context, ques=quest)

上傳頭像,讓他人更好的認識你

# 上傳頭像
@app.route(/uploadLogo/<user_id>, methods=[GET, POST])
def uploadLogo(user_id):
    user = User.query.filter(User.id == user_id).first()
    edimg = request.files[edimg]
    basepath = os.path.dirname(__file__)  # 當前文件所在路徑
    upload_path = os.path.join(basepath, static/uploads, edimg.filename)  # 註意:沒有的文件夾一定要先創建,不然會提示沒有該路徑
    edimg.save(upload_path)
    user.image = uploads/ + edimg.filename
    db.session.commit()
    return redirect(url_for(personcenter, user_id=user_id));

5.3 修改密碼提示

# 修改密碼
@app.route(/setPassword/<user_id>, methods=[GET, POST])
@loginFirst
def setPassword(user_id):
    if request.method == GET:

        if request.args.get(info):
            info = request.args.get(info)
        else:
            info = None
        return render_template(editPassword.html,info=info)
    else:
        user = User.query.filter(User.id == user_id).first()
        if user:
            if user.check_password(request.form.get(old)):
                user.password = request.form.get(new1)
                db.session.commit()
                info = 修改成功
            else:
                info = 原密碼錯誤
                return redirect(url_for(setPassword,user_id=user_id,info=info))
        else:
            info = 未知錯誤
        return redirect(url_for(personcenter, user_id=user_id, info=info))

 

 頁面中:通過定義info提示框實現在後臺應用js代碼

<script>
    {% if info %}
        alert({{ info }})
    {% endif %}
</script>

6 成品展示

1網站父模板統一布局

技術分享圖片

2註冊、登錄、註銷

技術分享圖片

技術分享圖片

技術分享圖片

點擊註銷,呈現的內容不一樣,收藏夾需要登錄前驗證

技術分享圖片

3.發布引用編輯插件、影評列表div+css顯示

技術分享圖片

技術分享圖片

4.詳情頁

技術分享圖片

夜晚開啟護眼模式:

技術分享圖片

5.評論、列表顯示

技術分享圖片

6.個人中心

技術分享圖片

我對這個作者有興趣,我想看看她的資料(用戶中心):

技術分享圖片

7.搜索,條件組合搜索

Eg:這是點贊數10以上、評論2以上的

技術分享圖片

8.文章分類、顯示(古裝玄幻類為例)

技術分享圖片

9點贊、收藏

Eg:點了個贊變成27:

技術分享圖片

Eg:沒收藏的時候是這樣的:

技術分享圖片

Eg:收藏後是這樣的:

技術分享圖片

10修改密碼、頭像、上傳頭像

技術分享圖片

上傳頭像和預覽如下:

技術分享圖片

覺得可以就點擊upload就換好頭像

技術分享圖片

11我的發布、點贊、收藏、評論

我發過的影評在這裏(可刪除自己的影評):

技術分享圖片

我發過的評論在這裏(可刪除自己的評論):

技術分享圖片

收藏過的影評:

技術分享圖片

12高級搜索

可同時按分類按時間排序:

技術分享圖片

13熱門文章、推薦文章

推薦的作品在詳情頁可以看到:技術分享圖片

熱門的作品在排行榜可以看到:技術分享圖片

14下載文件

點擊電子書下載,可以下載到我的電腦

技術分享圖片

沿用Python+Flask+Mysql的web建設技術開發網站