Skip to main content

收藏功能实现

收藏功能实现—多对多关系模型

添加模型及对应关系,代码如下:

# models.py

class User(db.Model,UserMixin):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
username = db.Column(db.String(100),nullable=False)
email = db.Column(db.String(100),nullable=False,unique=True)
password = db.Column(db.String(100),nullable=False)
# 多对多关系
favorites = db.relationship('Course',secondary='collections',
backref=db.backref('user',lazy='dynamic'),
lazy='dynamic')


class Course(db.Model):
course_id = db.Column(db.String(100),primary_key=True,nullable=False)
product_id = db.Column(db.String(100),nullable=False)
product_type = db.Column(db.Integer, nullable=False)
product_name = db.Column(db.String(125), nullable=False)
provider = db.Column(db.String(125), nullable=False)
score = db.Column(db.Float(2))
score_level = db.Column(db.Integer)
learner_count = db.Column(db.Integer)
lesson_count = db.Column(db.Integer)
lector_name = db.Column(db.String(125))
original_price = db.Column(db.Float(2))
discount_price = db.Column(db.Float(2))
discount_rate = db.Column(db.Float(2))
img_url = db.Column(db.String(125))
big_img_url = db.Column(db.String(125))
description = db.Column(db.Text)



class Sale(db.Model):
id = db.Column(db.Integer,autoincrement=True,primary_key=True,nullable=False)
course_id = db.Column(db.String(100),db.ForeignKey('course.course_id'))
product_name = db.Column(db.String(125), nullable=False)
learner_count = db.Column(db.Integer)
create_time = db.Column(db.Date,default= datetime.today())
# 关联关系
course = db.relationship('Course',backref=db.backref('sale',lazy='dynamic'))


collections = db.Table('collections',
db.Column('user_id',db.Integer,db.ForeignKey('user.id')),
db.Column('course_id',db.String(100),db.ForeignKey('course.course_id'))
)

执行迁移命令:

flask db migrate

flask db upgrade

在shell中测试,执行命令:

flask shell

输入如下命令

>>> from app import db
>>> from app.models import User, Course
>>> User.query.all()
[<User 2>]
>>> user = User.query.get(2)
>>> user.username
'test'
>>> course1 = Course.query.get('1002781006')
>>> course2 = Course.query.get('1002781014')
>>> user.favorites.append(course1)

执行完成后,数据库中新增一个collection表,只有2个字段,user_id和course_id.

在shell中可以查看收藏的信息。

>>> user.favorites
<sqlalchemy.orm.dynamic.AppenderQuery object at 0x10ea257d0>
>>> user.favorites.all()
[<Course 1002781014>, <Course 1002781006>]
>>> course1.user
<sqlalchemy.orm.dynamic.AppenderQuery object at 0x10e8e8910>
>>> course1.user.first()
<User 2>

切换收藏与取消收藏按钮

templates/detail.html 详情页代码如下:

{% extends 'base.html' %}

{% block content%}

<div class="container">
<div class="row" style="margin:20px auto;">
<div class="col-sm-6">
<img src="{{ course.big_img_url }}" class="card-img-top"
alt="..." width="450px" height="260px">
</div>
<div class="col-sm-6">
<h4>{{ course.product_name }}</h4>
<div class="course-info">课程讲师:{{ course.lector_name }}</div>
<div class="course-info">所属机构:{{ course.provider }}</div>
<div class="course-info">课程评分:{{ course.score }}</div>
<div class="course-info">学习人数:{{ course.learner_count}}</div>
<div class="course-price">
{% if course.discount_price %}
¥{{course.discount_price}}
<span style="color: #666666;font-size: 14px;text-decoration: line-through;">¥{{course.original_price}}</span>
{% elif not course.original_price %}
免费
{% else %}
¥{{course.original_price}}
{% endif %}
</div>
<div>
{% if current_user.is_authenticated %}
<button class="btn btn-success" id="collect">
收藏
</button>
{% endif %}
<a href="https://study.163.com/course/introduction/{{course.course_id}}.htm" target="view_window">
<button type="button" class="btn btn-danger" >直达网易云</button>
</a>
</div>
</div>
</div>

</div>

<script>
$('#collect').click(function(){
// 异步加载数据
var url = '/collect/' + {{ course.course_id }}
that = this
$.get(url).done(function (data) {
if (data.result == 'error'){
alert('系统异常,请稍后重试!')
}
// 请求成功,修改对于文字
var text = $(that).text();
if (text.trim() == '收藏'){
$(that).text('取消收藏');
} else {
$(that).text('收藏');
}
})
})
</script>

{% endblock %}

Ajax异步请求实现收藏与取消收藏

routes.py文件中添加collect方法,代码是如下:

# routes.py

@app.route('/collect/<course_id>')
@login_required
def collect(course_id):
# 判断是否收藏过
if current_user.is_favorite(course_id):
# 取消收藏
if current_user.del_favorite(course_id):
data = {'result': 'success'}
else:
data = {'result': 'error'}
else:
# 添加收藏
if current_user.add_favorite(course_id):
data = {'result': 'success'}
else:
data = {'result': 'error'}
return json.dumps(data)

上面的代码中包含了3个方法is_favorite, del_favorite, add_favorite, 接下来,在models.py中的User类中定义这3个方法。

# models.py

class User(db.Model,UserMixin):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
username = db.Column(db.String(100),nullable=False)
email = db.Column(db.String(100),nullable=False,unique=True)
password = db.Column(db.String(100),nullable=False)
# 多对多关系
favorites = db.relationship('Course',secondary='collections',
backref=db.backref('user',lazy='dynamic'),
lazy='dynamic')

# 定义收藏相关的方法
def is_favorite(self,course_id):
courses = self.favorites.all()
course_list = [course.course_id for course in courses]
if course_id in course_list:
return True

def add_favorite(self,course_id):
try:
course = Course.query.get(course_id)
self.favorites.append(course)
db.session.commit()
return True
except:
return


def del_favorite(self,course_id):
try:
course = Course.query.get(course_id)
self.favorites.remove(course)
db.session.commit()
return True
except:
return

查看我的收藏

routes.py文件中创建favorites路由,代码如下:

@app.route('/favorites')
@login_required
def favorites():
page = request.args.get('page',1,type=int)
courses = current_user.favorites.paginate(page,per_page=20)
return render_template('favorites.html',courses=courses)

templates下创建favorites.html模板,代码如下:

{% extends 'base.html' %}
{% import 'page.html' as pg %}
{% block content %}

<div class="container">
{% if courses.total %}
<div class="text-monospace" style="margin: 15px 0 0 5px;">
共收藏<span class="font-weight-bold">{{ courses.total }}</span>门课程
</div>
<div class="link-top"></div>
<!-- 显示课程开始 -->
<div class="row" style="text-align:center;">
{% for course in courses.items %}
<div class="col-sm-3" style="padding: 20px">
<a href="/course/{{course.course_id}}" style="text-decoration: none;color:inherit;">
<div class="card" style="height:280px">
<img src="{{course.big_img_url}}" class="card-img-top"
alt="..." height="170px">
<div class="card-body">
<p class="card-title" style="font-weight: bold;">{{course.product_name[0:20]}}</p>
<p class="card-text">
{% if not course.original_price %}
免费
{% elif course.discount_rate %}
¥{{course.discount_price}}元
{% else %}
¥{{course.original_price}}元
{% endif %}
</p>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
<!-- 显示课程结束 -->
<!-- 分页开始 -->
{{ pg.page(courses) }}
<!-- 分页结束 -->
{% else%}
<div style="text-align:center;">
<img src="{{url_for('static',filename='images/no_results.png')}}" width="35%" height="35%">
<h4>暂无相关结果</h4>
<p>换个搜索关键词试试吧:)</p>
</div>
{% endif %}
</div>
<script>
$(".page-link").click(function(){
var page = $(this).data('page')
matchUrl('page',page); // 生成URL
})
</script>
{% endblock %}