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 Role(db.Document, RoleMixin): name = db.StringField(required=True, unique=True, max_length=80) description = db.StringField(max_length=255) def __str__(self): return str(self).encode('utf-8') def __unicode__(self): return self.name meta = { 'collection': 'role', 'indexes': ['name'], }
class Comment(db.Document): id = db.SequenceField(primary_key=True) created_at = db.DateTimeField(default=datetime.now, required=True) content = db.StringField(verbose_name='Comment', required=True) author = db.ReferenceField(User) @property def post_type(self): return self.__class__.__name__
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) 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'] }
class SocialConnection(db.Document): user = fields.ReferenceField(User) provider = db.StringField(max_length=255) profile_id = db.StringField(max_length=255) username = db.StringField(max_length=255) email = db.StringField(max_length=255) access_token = db.StringField(max_length=255) secret = db.StringField(max_length=255) first_name = db.StringField(max_length=255, help_text=_('First Name')) last_name = db.StringField(max_length=255, help_text=_('Last Name')) cn = db.StringField(max_length=255, help_text=_('Common Name')) profile_url = db.StringField(max_length=512) image_url = db.StringField(max_length=512) def get_user(self): return self.user @classmethod def by_profile(cls, profile): provider = profile.data['provider'] return cls.objects(provider=provider, profile_id=profile.id).first() @classmethod def from_profile(cls, user, profile): if user and not user.is_anonymous(): user = None if not user or user.is_anonymous(): email = profile.data.get('email') provider = profile.data.get('provider') first_name = profile.data.get('first_name') last_name = profile.data.get('last_name') if provider not in ('Twitter', 'Douban') and not email: msg = 'Cannot create new user, authentication provider need provide email' # noqa raise Exception(_(msg)) if email is None: conflict = User.objects(first_name=first_name, last_name=last_name).first() else: conflict = User.objects(email=email).first() if conflict: msg = 'Cannot create new user, email {} is already used. Login and then connect external profile.' # noqa msg = _(msg).format(email) raise Exception(msg) now = datetime.now() user = User( email=email, first_name=first_name, last_name=last_name, confirmed_at=now, active=True, ) user.save() login_user(user) connection = cls(user=user, **profile.data) connection.save() return connection def __unicode__(self): return self.display_name meta = { 'collection': 'socialconnection', 'indexes': ['user', 'profile_id'], }
class Quote(Post): content = db.StringField(required=True) author = db.ReferenceField(User)
class Image(Post): image_url = db.StringField(required=True, max_length=255)
class Video(Post): embed_code = db.StringField(required=True)