社交web允许用户之间相互联系。

例如:

关注者、好友、联系人、联络人或伙伴。

记录两个用户之间的定向联系,在数据库查询中也要使用这种联系。

一、论数据库关系

一对多关系

数据库使用关系建立记录之间的联系。其中,一对多关系是最常用的关系类型,它把一个记录和一组相关的记录联系在一起。实现这种关系,要在“多”这一层加一个外键,指向“一”这一侧,例如下列代码:

class Role(db.Model):
__tablename__ = 'roles'   id = db.Column(db.Integer,primary_key = True)
#...
users = db.relationship('User', backref='role', lazy='dynamic') class User(UserMixin, db.Model):
__tablename__ = 'users'
#...
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

其中,users的数据库表中添加了一个外键role_id 指向了roles表的id

大部分的其他关系类型都可以从一对多类型中衍生。

多对一关系从“多”这一侧看,就是一对多关系。一对一关系类型是简化版的一对多关

多对多关系

解决方法是添加第三张表,这个表称为关联表。多对多关系可以分解成原表和关联表之间的两个一对多关系。

用SQLAlchemy实现图中的关系。

registrations = db.Table('registrations',
db.Column('student_id', db.Integer, db.ForeignKey('students.id')),
db.Column('class_id', db.Integer, db.ForeignKey('classes.id'))
)
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
classes = db.relationship('Class',
secondary=registrations,
backref=db.backref('students', lazy='dynamic'),
lazy='dynamic')
class Class(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String)

多对多关系仍使用定义一对多关系的db.relationship() 方法进行定义,但在多对多关系中,必须把secondary 参数设为关联表。多对多关系可以在任何一个类中定义,backref 参数会处理好关系的另一侧。关联表就是一个简单的表,不是模型,SQLAlchemy 会自动接管这个表。

自引用关系

如果关系中的两侧都在同一个表中,这种关系称为自引用关系。

高级多对多关系

使用多对多关系时,往往需要存储所联两个实体之间的额外信息。对用户之间的关注来说,可以存储用户关注另一个用户的日期,这样就能按照时间顺序列出所有关注者。这种
信息只能存储在关联表中,但是在之前实现的学生和课程之间的关系中,关联表完全是由SQLAlchemy 掌控的内部表。

为了能在关系中处理自定义的数据,我们必须提升关联表的地位,使其变成程序可访问的模型。

app/models/user.py:关注关联表的模型实现

class Follow(db.Model):
__tablename__ = 'follows'
follower_id = db.Column(db.Integer,db.ForeignKey('users.id'),primary_key = True)
followed_id = db.Column(db.Integer,db.ForegnKey('users.id'),primary_key = True)
timestamp = db.Column(db.DateTime,default = datetime.utcnow)

app/models/user.py:使用两个一对多关系实现的多对多关系

class User(UserMixin, db.Model):
# ...
followed = db.relationship('Follow',
foreign_keys=[Follow.follower_id],
backref=db.backref('follower', lazy='joined'),
lazy='dynamic',
cascade='all, delete-orphan')
followers = db.relationship('Follow',
foreign_keys=[Follow.followed_id],
backref=db.backref('followed', lazy='joined'),
lazy='dynamic',
cascade='all, delete-orphan')

程序现在要处理两个一对多关系,以便实现多对多关系。由于这些操作经常需要重复执行,所以最好在User 模型中为所有可能的操作定义辅助方法

app/models.py:关注关系的辅助方法

 #关注关系的辅助方法
def follow(self,user):
if not self.is_following(user):
f = Follow(follower=self,followed=user)
db.session.add(f) def unfollow(self,user):
f = self.followed.filter_by(followed_id = user.id).first()
if f:
db.session.delete(f) def is_following(self,user):
return self.followed.filter_by(follow_id = user.id).first() is not None def is_followed(self,user):
return self.followers.filter_by(follow_id = user.id).first() is not None

二、在资料页中显示关注者

app/templates/user.html:在用户资料页上部添加关注信息

{% extends "base.html" %}
{% import "_macros.html" as macros %} {% block title %}微博 - {{ user.username }}{% endblock %} {% block page_content %}
<div class="page-header">
<img class="img-rounded profile-thumbnail" src="{{ user.gravatar(size=256) }}">
<div class="profile-header">
<h1>{{ user.username }}</h1>
{% if user.name or user.location %}
<p>
{% if user.name %}{{ user.name }}<br>{% endif %}
{% if user.location %}
From <a href="http://maps.google.com/?q={{ user.location }}">{{ user.location }}</a><br>
{% endif %}
</p>
{% endif %}
{% if current_user.is_administrator() %}
<p><a href="mailto:{{ user.email }}">{{ user.email }}</a></p>
{% endif %}
{% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %}
<p>创建时间 {{ moment(user.member_since).format('L') }}. 最后访问 {{ moment(user.last_seen).fromNow() }}.</p>
<p>{{ user.posts.count() }} 博客文章.</p>
<p>
{% if current_user.can(Permission.FOLLOW) and user != current_user %}
{% if not current_user.is_following(user) %}
<a href="{{ url_for('.follow', username=user.username) }}" class="btn btn-primary">关注</a>
{% else %}
<a href="{{ url_for('.unfollow', username=user.username) }}" class="btn btn-success">取消关注</a>
{% endif %}
{% endif %}
<a href="{{ url_for('.followers', username=user.username) }}">关注者: <span class="badge">{{ user.followers.count() }}</span></a>
<a href="{{ url_for('.followed_by', username=user.username) }}">被关注: <span class="badge">{{ user.followed.count() }}</span></a>
{% if current_user.is_authenticated and user != current_user and user.is_following(current_user) %}
| <span class="label label-default">关注了你</span>
{% endif %}
</p>
<p>
{% if user == current_user %}
<a class="btn btn-default" href="{{ url_for('.edit_profile') }}">编辑个人资料</a>
{% endif %}
{% if current_user.is_administrator() %}
<a class="btn btn-danger" href="{{ url_for('.edit_profile_admin', id=user.id) }}">编辑个人资料 [管理员]</a>
{% endif %}
</p>
</div>
</div>
<h3>Posts by {{ user.username }}</h3>
{% include '_posts.html' %}
{% if pagination %}
<div class="pagination">
{{ macros.pagination_widget(pagination, '.user', username=user.username) }}
</div>
{% endif %}
{% endblock %}

基于python的web应用开发-添加关注者的更多相关文章

  1. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)

    目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构   前言 学习Python也有一个半月时间了,学到现在感觉 ...

  2. 基于Python的WEB接口开发与自动化测试 pdf(内含书签)

    基于Python的WEB接口开发与自动化测试 目录 目 录O V目 录章 Python 学习必知 ................................................... ...

  3. 基于Python的Web应用开发实践总结

    基于Python的Web应用开发学习总结 项目地址   本次学习采用的是Flask框架.根据教程开发个人博客系统.博客界面如图所示. 整个学习过程收获很多,以下是学习总结. 1.virtualenv ...

  4. 学习参考《Flask Web开发:基于Python的Web应用开发实战(第2版)》中文PDF+源代码

    在学习python Web开发时,我们会选择使用Django.flask等框架. 在学习flask时,推荐学习看看<Flask Web开发:基于Python的Web应用开发实战(第2版)> ...

  5. FlaskWeb开发:基于Python的Web应用开发实战

    所属网站分类: 资源下载 > python电子书 作者:熊猫烧香 链接:http://www.pythonheidong.com/blog/article/63/ 来源:python黑洞网,专注 ...

  6. 基于Python的Web应用开发实战——3 模板

    要想开发出易于维护的程序,关键在于编写形式简洁且结构良好的代码. 当目前为止,你看到的示例都太简单,无法说明这一点,但Flask视图函数的两个完全独立的作用却被融合在了一起,这就产生了一个问题. 视图 ...

  7. 基于Python的Web应用开发实战——2 程序的基本结构

    2.1 初始化 所有Flaks程序都必须创建一个程序实例. Web服务器使用一种名为Web服务器网关接口(Web Server Gateway Interface,WSGI)的协议,把接收自客户端的所 ...

  8. 基于python的互联网软件测试开发(自动化测试)-全集合

    基于python的互联网软件测试开发(自动化测试)-全集合 1   关键字 为了便于搜索引擎收录本文,特别将本文的关键字给强调一下: python,互联网,自动化测试,测试开发,接口测试,服务测试,a ...

  9. 关于基于.net的WEB程序开发所需要的一些技术归纳

    前提: 最近公司里有一个同事,年龄比我大几岁,但是由于是转行来做开发的,许多的关于.net开发技术不是很入行,所以总是会问我一些东西,基于自己以前的一些 经验,总是会愿意给他讲一些总结性的东西,希望他 ...

随机推荐

  1. c# word文档与二进制数据的相互转换

    最近项目出使用到了将word文档以二进制的方法存到数据库中,并再次读取出二进制数据转换为word文档.最后总结了一下,不多说看示例方法: 代码 , content.Length);           ...

  2. ASP.NET没有魔法——ASP.NET MVC 过滤器(Filter)

    上一篇文章介绍了使用Authorize特性实现了ASP.NET MVC中针对Controller或者Action的授权功能,实际上这个特性是MVC功能的一部分,被称为过滤器(Filter),它是一种面 ...

  3. 【S2-052】漏洞复现(CVE-2017-9805)

    一.漏洞描述 Struts2 的REST插件,如果带有XStream组件,那么在进行反序列化XML请求时,存在未对数据内容进行有效验证的安全隐患,可能发生远程命令执行. 二.受影响版本 Struts2 ...

  4. 2017-11-22 Intall Ubuntu Log

    重启之后进入不了系统,安装工具check defect也不好用(问题尚不清楚),决定重做系统 直接用u盘(Universal_USB_Installer制作的安装工具,之前用都没有问题)安装,前面一起 ...

  5. 手 Q 人脸识别动画实现详解

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 前言 开门见山,先来看下效果吧. 看到这么酷炫的效果图,不得不赞叹一下我们的设计师.然而,站在程序员的角度上看,除了酷炫之外更多的是复杂.但是 ...

  6. JAVA基础面试(二)

    11.是否可以从一个static方法内部发出对非static方法的调用? 不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用 ...

  7. asp.net core 2.0集成signalr

    在博客园也很多年了,一直未曾分享过什么东西,也没有写过博客,但自己也是汲取着博客园的知识成长的: 这两天想着不能这么无私,最近.NET CORE貌似挺流行的,闲来无事也自己搞了个asp.net cor ...

  8. 《java.util.concurrent 包源码阅读》26 Fork/Join框架之Join

    接下来看看调用ForkJoinTask的join方法都发生了什么: public final V join() { // doJoin方法返回该任务的状态,状态值有三种: // NORMAL, CAN ...

  9. head first python菜鸟学习笔记(第七章) ——web应用之为数据建模

    问题1. #意思是从athletelist.py中导入AthleteListfrom athletelist import AthleteList 源程序代码 import pickle from a ...

  10. debug断点调试

    debug断点调试  1,虫子启动2,F6   执行断点的下一步,下一个语句     F5    进入方法     F8   执行到结束    查看表达式的值:选中查看的表达式,接着按   ctrl ...