class Post(db.Document): id = db.SequenceField(primary_key=True) created_at = db.DateTimeField(default=datetime.utcnow, required=True) title = db.StringField(max_length=255, required=True) content = db.StringField(required=True) views = db.IntField(default=0) # 有了登录系统author就是必选项 author = db.ReferenceField(User) comments = db.ListField(db.ReferenceField('Comment')) category = db.ReferenceField(Category) def url(self): return url_for('post.detail', id=self.id) def __unicode__(self): return self.title @property def post_type(self): return self.__class__.__name__ @property def recent_activity_time(self): if self.comments: activity = self.comments[-1].created_at else: activity = self.created_at return timesince(activity, locale=g.locale) meta = { 'allow_inheritance': True, 'indexes': ['-created_at', 'id'], 'ordering': ['-created_at'] }
class Category(db.Document): id = db.SequenceField(primary_key=True) created_at = db.DateTimeField(default=datetime.utcnow, required=True) name = db.StringField(max_length=50, required=True, unique=True) _slug = db.StringField(max_length=50, unique=True) description = db.StringField(max_length=120, required=True) priority = db.IntField(default=0) posts = db.ListField(db.ReferenceField('Post')) def url(self): return url_for('category.detail', kwargs={'slug': self.slug}) def __unicode__(self): return self.name @property def slug(self): return self._slug @slug.setter def slug(self, value): self._slug = '-'.join(filter(lambda x: x, self._slug.split(' '))) @property def color(self): return CATEGORY_COLORS[self.id - 1] meta = {'indexes': ['-priority', 'name', 'id'], 'ordering': ['-priority']}
class Comment(db.Document): id = db.SequenceField(primary_key=True) created_at = db.DateTimeField(default=datetime.utcnow, required=True) content = db.StringField(verbose_name='Comment', required=True) author = db.ReferenceField(User) ref_id = db.IntField(default=0) @property def post_type(self): return self.__class__.__name__ def get_replies(self): return Comment.objects.filter(ref_id=self.id)
class User(db.Document, UserMixin): id = db.SequenceField(primary_key=True) created_at = db.DateTimeField(default=datetime.utcnow, required=True) name = db.StringField(max_length=25) email = db.StringField(max_length=255) encrypted_password = db.StringField(max_length=255) current_sign_in_at = db.DateTimeField(default=datetime.utcnow, required=True) last_sign_in_at = db.DateTimeField(default=datetime.utcnow) current_sign_in_ip = db.StringField(max_length=255) last_sign_in_ip = db.StringField(max_length=255) following = db.ListField(db.ReferenceField('User')) follower = db.ListField(db.ReferenceField('User')) blocked_user_id = db.ListField(db.IntField(), default=[]) active = db.BooleanField(default=True) # we can deactive spammer. confirmed_at = fields.DateTimeField() # use social provider register at created = fields.DateTimeField(default=datetime.utcnow()) first_name = db.StringField(max_length=120) last_name = db.StringField(max_length=120) roles = fields.ListField(fields.ReferenceField(Role, reverse_delete_rule=DENY), default=[]) def url(self): return url_for('user', kwargs={'name': self.name}) def avatar(self, size=48): return "%s%s.jpg?size=%s".format( current_app.config['GRAVATAR_BASE_URL'], self.email_md5, size) @staticmethod def generate_encrypted_password(password): return security.generate_password_hash( current_app.config['SECRET_KEY'] + password) @staticmethod def create_token(length=16): return security.gen_salt(length) def reset_password(self): redis_store.set(self.name + 'token', self.create_token()) redis_store.expire(self.name + 'token', 3600) msg = Message("Reset your password", sender=current_app.config['MAIL_DEFAULT_SENDER'], recipients=[self.email]) msg.body = "link to check token callback" mail.send(msg) def verify_reset_password_token(self, token): if token != redis_store.get(self.name + 'token'): return False, 'token expired or wrong' else: return True, 'success' def change_password(self, password, token): result = self.verify_reset_password_token(token) if result[0]: if self.encrypted_password == User.generate_encrypted_password( password): return False, 'duplicate password' else: self.encrypted_password = User.generate_encrypted_password( password) self.save() redis_store.remove(self.name + 'token') return True, 'success' else: return result def __unicode__(self): return self.name @property def cn(self): if not self.first_name or not self.last_name: return self.email return '{} {}'.format(self.first_name, self.last_name) @property def id(self): return self.pk @classmethod def by_email(cls, email): return cls.objects(email=email).first() def social_connections(self): return SocialConnection.objects(user=self) meta = {'indexes': ['id'], 'ordering': ['id']}