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 User(db.Document, UserMixin): id = db.SequenceField(primary_key=True) created_at = db.DateTimeField(default=datetime.utcnow, required=True) username = db.StringField(max_length=25) email = db.StringField(max_length=255) 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', dbref=True)) follower = db.ListField(db.ReferenceField('User', dbref=True)) blocked_user_id = db.ListField(db.StringField(), 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 __str__(self): return self.cn def url(self): return url_for('user.detail', id=str(self.id)) @property def email_md5(self): email = self.email.strip() if isinstance(email, unicode): email = email.encode('utf-8') return hashlib.md5(email).hexdigest() def avatar(self, size=48): return "{0}{1}.jpg?size={2}".format( current_app.config['GRAVATAR_BASE_URL'], self.email_md5, size ) @staticmethod def generate_password(password): return security.generate_password_hash( current_app.config['SECRET_KEY'] + password ) @staticmethod def create_token(length=16): return security.gen_salt(length) @classmethod def create_user(cls, username, email, password, **kwargs): password = cls.generate_password(password) return cls.objects.create( username=username, email=email, password=password, **kwargs ) def set_password(self, password): self.password = self.generate_password(password) def check_password(self, password): return security.check_password_hash( self.password, current_app.config['SECRET_KEY'] + password ) def reset_password(self): redis_store.set(self.username + 'token', self.create_token()) redis_store.expire(self.username + '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.username + '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.password == User.generate_password(password): return False, 'duplicate password' else: self.password = User.generate_password(password) self.save() redis_store.remove(self.username + 'token') return True, 'success' else: return result def __unicode__(self): return self.username @property def cn(self): return ' '.join([name.encode('utf-8') for name in (self.first_name, self.last_name) if 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'] }