class LiveJournalImportForm(forms.Form): """This form asks the user for authorisation and import options.""" username = forms.TextField(lazy_gettext(u'LiveJournal username'), required=True, validators=[is_valid_lj_user()]) password = forms.TextField(lazy_gettext(u'LiveJournal password'), required=True, widget=forms.PasswordInput) import_what = forms.ChoiceField(lazy_gettext(u'Import what?'), choices=[(IMPORT_JOURNAL, lazy_gettext(u'My Journal')), (IMPORT_COMMUNITY, lazy_gettext(u'My Posts in Community')), (IMPORT_COMMUNITY_ALL, lazy_gettext(u'Everything in Community'))], help_text=lazy_gettext(u'Importing a community requires '\ u'administrative access to the community.'), default=IMPORT_JOURNAL, required=True, widget=forms.RadioButtonGroup) community = forms.TextField(lazy_gettext(u'Community name')) security_choices = [(SECURITY_DISCARD, lazy_gettext(u'Don’t import')), (SECURITY_PRIVATE, lazy_gettext(u'Private')), (SECURITY_PROTECTED, lazy_gettext(u'Protected')), (SECURITY_PUBLIC, lazy_gettext(u'Public'))] security_custom = forms.ChoiceField(lazy_gettext( u'Convert custom-security entries to'), choices=security_choices, help_text=lazy_gettext(u'Zine only supports public, private and '\ u'protected entries, so you must choose '\ u'what to do with your custom security '\ u'entries.')) categories = forms.Multiple(forms.TextField(), lazy_gettext(u'Categories'), help_text=lazy_gettext(u'Choose categories to '\ u'assign imported posts to.'), widget=forms.CheckboxGroup) getcomments = forms.BooleanField(lazy_gettext(u'Download Comments?')) def __init__(self, initial=None): initial = forms.fill_dict( initial, getcomments=True, import_what=IMPORT_JOURNAL, security_custom=SECURITY_PROTECTED, ) self.categories.choices = [(c.name, c.name) for c in zine.models.Category.query.all()] forms.Form.__init__(self, initial) def context_validate(self, data): lj = LiveJournalConnect(data['username'], data['password']) try: result = lj.login() except xmlrpclib.Fault, fault: raise ValidationError(fault.faultString) if data['import_what'] in [IMPORT_COMMUNITY, IMPORT_COMMUNITY_ALL]: if data['community'] not in result.get('usejournals', []): raise ValidationError(lazy_gettext(u'You do not have access '\ u'to the specified community.'))
class EditCommentForm(_CommentBoundForm): """Form for comment editing in admin.""" author = forms.TextField(lazy_gettext(u'Author'), required=True) email = forms.TextField(lazy_gettext(u'Email'), validators=[is_valid_email()]) www = forms.TextField(lazy_gettext(u'Website'), validators=[is_valid_url()]) text = forms.TextField(lazy_gettext(u'Text'), widget=forms.Textarea) pub_date = forms.DateTimeField(lazy_gettext(u'Date'), required=True) parser = forms.ChoiceField(lazy_gettext(u'Parser'), required=True) blocked = forms.BooleanField(lazy_gettext(u'Block Comment')) blocked_msg = forms.TextField(lazy_gettext(u'Reason')) def __init__(self, comment, initial=None): _CommentBoundForm.__init__(self, comment, forms.fill_dict(initial, author=comment.author, email=comment.email, www=comment.www, text=comment.text, pub_date=comment.pub_date, parser=comment.parser, blocked=comment.blocked, blocked_msg=comment.blocked_msg )) self.parser.choices = self.app.list_parsers() self.parser_missing = comment.parser_missing if self.parser_missing and comment.parser is not None: self.parser.choices.append((comment.parser, _('%s (missing)') % comment.parser.title())) def save_changes(self): """Save the changes back to the database.""" old_parser = self.comment.parser forms.set_fields(self.comment, self.data, 'pub_date', 'parser', 'blocked_msg') if (self.data['text'] != self.comment.text or self.data['parser'] != old_parser): self.comment.text = self.data['text'] # update status if self.data['blocked']: if not self.comment.blocked: self.comment.status = COMMENT_BLOCKED_USER else: self.comment.status = COMMENT_MODERATED # only apply these if the comment is not anonymous if self.comment.anonymous: forms.set_fields(self.comment, self.data, 'author', 'email', 'www')
class QuillsImportForm(forms.Form): """This form asks the user for the Quills blog URL and authorisation.""" blogurl = forms.TextField(lazy_gettext(u'Quills Blog URL'), validators=[is_valid_blog_url()], required=True) username = forms.TextField(lazy_gettext(u'Plone login'), help_text=lazy_gettext(u'Login and password '\ u'required only if you’d like to download '\ u'drafts and protected items that are not'\ u'visible to the public.'), required=False) password = forms.TextField(lazy_gettext(u'Plone password'), required=False, widget=forms.PasswordInput, validators=[is_valid_plone_password()])
class ConfigurationForm(forms.Form): """Markdown configuration form.""" extensions = forms.LineSeparated(forms.TextField(), _(u'Enabled Extensions')) makeintro = forms.BooleanField(_(u'Make Intro Section'), help_text=_(u'Place <!--more--> on a line by itself with blank '\ u'lines above and below to cut the post at that point.'))
class EditCategoryForm(_CategoryBoundForm): """Form that is used to edit or create a category.""" slug = forms.TextField(lazy_gettext(u'Slug'), validators=[is_valid_slug()]) name = forms.TextField(lazy_gettext(u'Name'), max_length=50, required=True, validators=[is_not_whitespace_only()]) description = forms.TextField(lazy_gettext(u'Description'), max_length=5000, widget=forms.Textarea) def __init__(self, category=None, initial=None): if category is not None: initial = forms.fill_dict(initial, slug=category.slug, name=category.name, description=category.description ) _CategoryBoundForm.__init__(self, category, initial) def validate_slug(self, value): """Make sure the slug is unique.""" query = Category.query.filter_by(slug=value) if self.category is not None: query = query.filter(Category.id != self.category.id) existing = query.first() if existing is not None: raise ValidationError(_('This slug is already in use')) def make_category(self): """A helper function that creates a category object from the data.""" category = Category(self.data['name'], self.data['description'], self.data['slug'] or None) self.category = category return category def save_changes(self): """Save the changes back to the database. This also adds a redirect if the slug changes. """ old_slug = self.category.slug forms.set_fields(self.category, self.data, 'name', 'description') if self.data['slug']: self.category.slug = self.data['slug'] elif not self.category.slug: self.category.set_auto_slug() if old_slug != self.category.slug: register_redirect(old_slug, self.category.slug)
def setup(app, plugin): app.connect_event('process-doc-tree', process_doc_tree) app.connect_event('modify-admin-navigation-bar', add_config_link) app.add_url_rule('/options/typography', prefix='admin', endpoint='typography/config') app.add_view('typography/config', show_config) app.add_template_searchpath(TEMPLATES) for ignore, name, default in _rules: app.add_config_var('typography/' + name, forms.TextField(default=default))
def setup(app, plugin): app.add_parser('markdown', MarkdownParser) app.add_config_var(CFG_EXTENSIONS, forms.LineSeparated(forms.TextField(), default=[])) app.add_config_var(CFG_MAKEINTRO, forms.BooleanField(default=False)) app.connect_event('modify-admin-navigation-bar', add_config_link) app.add_url_rule('/options/markdown', prefix='admin', endpoint='markdown_parser/config', view=show_markdown_config) app.add_template_searchpath(TEMPLATES)
class ChangePasswordForm(forms.Form): """The form used on the password-change dialog in the admin panel.""" old_password = forms.TextField(lazy_gettext(u'Old password'), required=True, widget=forms.PasswordInput) new_password = forms.TextField(lazy_gettext(u'New password'), required=True, widget=forms.PasswordInput) check_password = forms.TextField(lazy_gettext(u'Repeat password'), required=True, widget=forms.PasswordInput) def __init__(self, user, initial=None): forms.Form.__init__(self, initial) self.user = user def validate_old_password(self, value): if not self.user.check_password(value): raise ValidationError(_('The old password you\'ve ' 'entered is wrong.')) def context_validate(self, data): if data['new_password'] != data['check_password']: raise ValidationError(_('The two passwords don\'t match.'))
def setup(app, plugin): if not have_pygments: raise SetupError('The pygments plugin requires the pygments library ' 'to be installed.') app.connect_event('modify-admin-navigation-bar', add_pygments_link) app.connect_event('after-request-setup', inject_style) app.add_config_var('pygments_support/style', forms.TextField(default=u'default')) app.add_markup_extension(SourcecodeExtension) app.add_url_rule('/options/pygments', prefix='admin', view=show_config, endpoint='pygments_support/config') app.add_url_rule('/_shared/pygments_support/<style>.css', view=get_style, endpoint='pygments_support/style') app.add_template_searchpath(TEMPLATES)
class BlockCommentForm(_CommentBoundForm): """Form used to block comments.""" message = forms.TextField(lazy_gettext(u'Reason')) def __init__(self, comment, initial=None): self.req = get_request() _CommentBoundForm.__init__(self, comment, initial) def block_comment(self): msg = self.data['message'] if not msg and self.req: msg = _(u'blocked by %s') % self.req.user.display_name self.comment.status = COMMENT_BLOCKED_USER self.comment.bocked_msg = msg
class LoginForm(forms.Form): """The form for the login page.""" user = forms.ModelField(User, 'username', required=True, messages=dict( not_found=lazy_gettext(u'User “%(value)s” does not exist.'), required=lazy_gettext(u'You have to enter a username.') ), on_not_found=lambda user: log.warning(_(u'Failed login attempt, user “%s” does not exist') % user, 'auth') ) password = forms.TextField(widget=forms.PasswordInput) permanent = forms.BooleanField() def context_validate(self, data): if not data['user'].check_password(data['password']): log.warning(_(u'Failed login attempt from “%s”, invalid password') % data['user'].username, 'auth') raise ValidationError(_('Incorrect password.'))
def setup(app, plugin): app.add_config_var('akismet_spam_filter/apikey', forms.TextField(default=u'')) app.add_url_rule('/options/akismet', prefix='admin', endpoint='akismet_spam_filter/config', view=show_akismet_config) app.add_url_rule('/comments/stats', prefix='admin', endpoint='akismet_spam_filter/stats', view=show_akismet_stats) app.connect_event('before-comment-saved', do_spamcheck) app.connect_event('before-comment-mark-spam', do_submit_spam) app.connect_event('before-comment-mark-ham', do_submit_ham) app.connect_event('modify-admin-navigation-bar', add_akismet_links) app.add_template_searchpath(TEMPLATES) app.add_shared_exports('akismet', SHARED) app.add_widget(AkismetBlockedCommentsCounterWidget)
class EditGroupForm(_GroupBoundForm): """Edit or create a group.""" groupname = forms.TextField(lazy_gettext(u'Groupname'), max_length=30, validators=[is_not_whitespace_only()], required=True) privileges = forms.MultiChoiceField(lazy_gettext(u'Privileges'), widget=forms.CheckboxGroup) def __init__(self, group=None, initial=None): if group is not None: initial = forms.fill_dict(initial, groupname=group.name, privileges=[x.name for x in group.privileges] ) _GroupBoundForm.__init__(self, group, initial) self.privileges.choices = self.app.list_privileges() def validate_groupname(self, value): query = Group.query.filter_by(name=value) if self.group is not None: query = query.filter(Group.id != self.group.id) if query.first() is not None: raise ValidationError(_('This groupname is already in use')) def _set_common_attributes(self, group): forms.set_fields(group, self.data) bind_privileges(group.privileges, self.data['privileges']) def make_group(self): """A helper function that creates a new group object.""" group = Group(self.data['groupname']) self._set_common_attributes(group) self.group = group return group def save_changes(self): """Apply the changes.""" self.group.name = self.data['groupname'] self._set_common_attributes(self.group)
class WordPressImportForm(forms.Form): """This form is used in the WordPress importer.""" download_url = forms.TextField(lazy_gettext(u'Dump Download URL'), validators=[is_valid_url()])
def setup(app, plugin): app.add_theme('vessel', TEMPLATE_FILES, plugin.metadata, configuration_page=configure) app.add_shared_exports('vessel_theme', SHARED_FILES) app.add_config_var('vessel_theme/variation', forms.TextField(default=blue_variation))
class ConfigurationForm(forms.Form): """The configuration form for the quotes.""" double_opening_quote = forms.TextField(required=True) double_closing_quote = forms.TextField(required=True) single_opening_quote = forms.TextField(required=True) single_closing_quote = forms.TextField(required=True)
def setup(app, plugin): theme = ZaikiTheme('zaiki', TEMPLATE_FILES, plugin.metadata, THEME_SETTINGS) app.add_theme(theme) app.add_template_filter('timeformat', theme.format_time) app.add_template_filter('avatar', theme.avatar) app.add_template_filter('amp', theme.amp) app.add_shared_exports('zaiki_theme', SHARED_FILES) app.add_config_var('zaiki_theme/blurb', forms.TextField(widget=forms.Textarea)) app.add_config_var('zaiki_theme/blurb_more_page', forms.TextField(default='about')) app.add_config_var('zaiki_theme/copyright', forms.TextField()) app.add_config_var('zaiki_theme/license', forms.TextField()) # Widgets app.add_widget(BlurbWidget) app.add_widget(FlickrWidget) app.add_widget(TwitterWidget) app.add_widget(DopplrWidget) app.add_widget(DailymileWidget) # Flickr widget app.add_config_var('zaiki_theme/flickr_machinetag', forms.TextField()) app.add_config_var('zaiki_theme/flickr_user', forms.TextField()) app.add_config_var('zaiki_theme/flickr_api_key', forms.TextField()) app.add_config_var('zaiki_theme/flickr_api_secret', forms.TextField()) app.add_config_var('zaiki_theme/flickr_pic_count', forms.IntegerField(default=6)) app.add_config_var('zaiki_theme/flickr_pic_display', forms.TextField(default='random')) app.add_config_var('zaiki_theme/flickr_pic_size', forms.TextField(default='s')) # Twitter widget app.add_config_var('zaiki_theme/twitter_user', forms.TextField()) # Dopplr widget app.add_config_var('zaiki_theme/dopplr_user', forms.TextField(default='')) app.add_config_var('zaiki_theme/dopplr_script_id', forms.TextField(default='')) # Dailymile widget app.add_config_var('zaiki_theme/dailymile_user', forms.TextField(default=''))
class ConfigurationForm(forms.Form): """The configuration form.""" api_key = forms.TextField(validators=[is_valid_key()])
class FeedImportForm(forms.Form): """This form is used in the feed importer.""" download_url = forms.TextField(lazy_gettext(u'Feed Download URL'), validators=[is_valid_url()])
class NewCommentForm(forms.Form): """New comment form for authors.""" # implementation detail: the maximum length of the column in the # database is longer than that. However we don't want users to # insert too long names there. The long column is reserved for # pingbacks and such. author = forms.TextField(lazy_gettext(u'Name*'), required=True, max_length=100, messages=dict( too_long=lazy_gettext(u'Your name is too long.'), required=lazy_gettext(u'You have to enter your name.') )) email = forms.TextField(lazy_gettext(u'Mail* (not published)'), required=True, validators=[is_valid_email()], messages=dict( required=lazy_gettext(u'You have to enter a valid e-mail address.') )) www = forms.TextField(lazy_gettext(u'Website'), validators=[is_valid_url( message=lazy_gettext(u'You have to enter a valid URL or omit the field.') )]) body = forms.TextField(lazy_gettext(u'Text'), min_length=2, max_length=6000, messages=dict( too_short=lazy_gettext(u'Your comment is too short.'), too_long=lazy_gettext(u'Your comment is too long.'), required=lazy_gettext(u'You have to enter a comment.') ), widget=forms.Textarea) parent = forms.HiddenModelField(Comment) def __init__(self, post, user, initial=None): forms.Form.__init__(self, initial) self.req = get_request() self.post = post self.user = user # if the user is logged in the form is a bit smaller if user.is_somebody: del self.fields['author'], self.fields['email'], self.fields['www'] def as_widget(self): widget = forms.Form.as_widget(self) widget.small_form = self.user.is_somebody return widget def validate_parent(self, value): if value.post != self.post: #_ this message is only displayed if the user tempered with #_ the form data raise ValidationError(_('Invalid object referenced.')) def context_validate(self, data): if not self.post.comments_enabled: raise ValidationError(_('Post is closed for commenting.')) def make_comment(self): """A handy helper to create a comment from the validated form.""" ip = self.req and self.req.remote_addr or '0.0.0.0' if self.user.is_somebody: author = self.user email = www = None else: author = self['author'] email = self['email'] www = self['www'] return Comment(self.post, author, self['body'], email, www, self['parent'], submitter_ip=ip) def create_if_valid(self, req): """The one-trick pony for commenting. Passed a req it tries to use the req data to submit a comment to the post. If the req is not a post req or the form is invalid the return value is None, otherwise a redirect response to the new comment. """ if req.method != 'POST' or not self.validate(req.form): return # if we don't have errors let's save it and emit an # `before-comment-saved` event so that plugins can do # block comments so that administrators have to approve it comment = self.make_comment() #! use this event to block comments before they are saved. This #! is useful for antispam and other ways of moderation. emit_event('before-comment-saved', req, comment) # Moderate Comment? Now that the spam check any everything # went through the processing we explicitly set it to # unmodereated if the blog configuration demands that if not comment.blocked and comment.requires_moderation: comment.status = COMMENT_UNMODERATED comment.blocked_msg = _(u'Comment waiting for approval') #! this is sent directly after the comment was saved. Useful if #! you want to send mail notifications or whatever. emit_event('after-comment-saved', req, comment) # Commit so that make_visible_for_request can access the comment id. db.commit() # Still allow the user to see his comment if it's blocked if comment.blocked: comment.make_visible_for_request(req) return redirect_to(self.post)
class EditUserForm(_UserBoundForm): """Edit or create a user.""" username = forms.TextField(lazy_gettext(u'Username'), max_length=30, validators=[is_not_whitespace_only()], required=True) real_name = forms.TextField(lazy_gettext(u'Realname'), max_length=180) display_name = forms.ChoiceField(lazy_gettext(u'Display name')) description = forms.TextField(lazy_gettext(u'Description'), max_length=5000, widget=forms.Textarea) email = forms.TextField(lazy_gettext(u'Email'), required=True, validators=[is_valid_email()]) www = forms.TextField(lazy_gettext(u'Website'), validators=[is_valid_url()]) password = forms.TextField(lazy_gettext(u'Password'), widget=forms.PasswordInput) privileges = forms.MultiChoiceField(lazy_gettext(u'Privileges'), widget=forms.CheckboxGroup) groups = forms.MultiChoiceField(lazy_gettext(u'Groups'), widget=forms.CheckboxGroup) is_author = forms.BooleanField(lazy_gettext(u'List as author'), help_text=lazy_gettext(u'This user is listed as author')) def __init__(self, user=None, initial=None): if user is not None: initial = forms.fill_dict(initial, username=user.username, real_name=user.real_name, display_name=user._display_name, description=user.description, email=user.email, www=user.www, privileges=[x.name for x in user.own_privileges], groups=[g.name for g in user.groups], is_author=user.is_author ) _UserBoundForm.__init__(self, user, initial) self.display_name.choices = [ (u'$username', user and user.username or _('Username')), (u'$real_name', user and user.real_name or _('Realname')) ] self.privileges.choices = self.app.list_privileges() self.groups.choices = [g.name for g in Group.query.all()] self.password.required = user is None def validate_username(self, value): query = User.query.filter_by(username=value) if self.user is not None: query = query.filter(User.id != self.user.id) if query.first() is not None: raise ValidationError(_('This username is already in use')) def _set_common_attributes(self, user): forms.set_fields(user, self.data, 'www', 'real_name', 'description', 'display_name', 'is_author') bind_privileges(user.own_privileges, self.data['privileges']) bound_groups = set(g.name for g in user.groups) choosen_groups = set(self.data['groups']) group_mapping = dict((g.name, g) for g in Group.query.all()) # delete groups for group in (bound_groups - choosen_groups): user.groups.remove(group_mapping[group]) # and add new groups for group in (choosen_groups - bound_groups): user.groups.append(group_mapping[group]) def make_user(self): """A helper function that creates a new user object.""" user = User(self.data['username'], self.data['password'], self.data['email']) self._set_common_attributes(user) self.user = user return user def save_changes(self): """Apply the changes.""" self.user.username = self.data['username'] if self.data['password']: self.user.set_password(self.data['password']) self.user.email = self.data['email'] self._set_common_attributes(self.user)
class PostForm(forms.Form): """This is the baseclass for all forms that deal with posts. There are two builtin subclasses for the builtin content types 'entry' and 'page'. """ title = forms.TextField(lazy_gettext(u'Title'), max_length=150, validators=[is_not_whitespace_only()], required=False) text = forms.TextField(lazy_gettext(u'Text'), max_length=65000, widget=forms.Textarea) status = forms.ChoiceField(lazy_gettext(u'Publication status'), choices=[ (STATUS_DRAFT, lazy_gettext(u'Draft')), (STATUS_PUBLISHED, lazy_gettext(u'Published')), (STATUS_PROTECTED, lazy_gettext(u'Protected')), (STATUS_PRIVATE, lazy_gettext(u'Private'))]) pub_date = forms.DateTimeField(lazy_gettext(u'Publication date'), help_text=lazy_gettext(u'Clear this field to update to current time')) slug = forms.TextField(lazy_gettext(u'Slug'), validators=[is_valid_slug()], help_text=lazy_gettext(u'Clear this field to autogenerate a new slug')) author = forms.ModelField(User, 'username', lazy_gettext('Author'), widget=forms.SelectBox) tags = forms.CommaSeparated(forms.TextField(), lazy_gettext(u'Tags')) categories = forms.Multiple(forms.ModelField(Category, 'id'), lazy_gettext(u'Categories'), widget=forms.CheckboxGroup) parser = forms.ChoiceField(lazy_gettext(u'Parser')) comments_enabled = forms.BooleanField(lazy_gettext(u'Enable comments')) pings_enabled = forms.BooleanField(lazy_gettext(u'Enable pingbacks')) ping_links = forms.BooleanField(lazy_gettext(u'Ping links')) #: the content type for this field. content_type = None def __init__(self, post=None, initial=None): self.app = get_application() self.post = post if post is not None: initial = forms.fill_dict(initial, title=post.title, text=post.text, status=post.status, pub_date=post.pub_date, slug=post.slug, author=post.author, tags=[x.name for x in post.tags], categories=[x.id for x in post.categories], parser=post.parser, comments_enabled=post.comments_enabled, pings_enabled=post.pings_enabled, ping_links=not post.parser_missing ) else: initial = forms.fill_dict(initial, status=STATUS_DRAFT) # if we have a request, we can use the current user as a default req = get_request() if req and req.user: initial['author'] = req.user initial.setdefault('parser', self.app.cfg['default_parser']) self.author.choices = [x.username for x in User.query.all()] self.parser.choices = self.app.list_parsers() self.parser_missing = post and post.parser_missing if self.parser_missing: self.parser.choices.append((post.parser, _('%s (missing)') % post.parser.title())) self.categories.choices = [(c.id, c.name) for c in Category.query.all()] forms.Form.__init__(self, initial) # if we have have an old post and the parser is not missing and # it was published when the form was created we collect the old # posts so that we don't have to ping them another time. self._old_links = set() if self.post is not None and not self.post.parser_missing and \ self.post.is_published: self._old_links.update(self.post.find_urls()) def find_new_links(self): """Return a list of all new links.""" for link in self.post.find_urls(): if not link in self._old_links: yield link def validate_slug(self, value): """Make sure the slug is unique.""" query = Post.query.filter_by(slug=value) if self.post is not None: query = query.filter(Post.id != self.post.id) existing = query.first() if existing is not None: raise ValidationError(_('This slug is already in use.')) def validate_parser(self, value): """Make sure the missing parser is not selected.""" if self.parser_missing and value == self.post.parser: raise ValidationError(_('Selected parser is no longer ' 'available on the system.')) def as_widget(self, preview=False): widget = forms.Form.as_widget(self) widget.new = self.post is None widget.post = self.post widget.preview = preview widget.parser_missing = self.parser_missing return widget def make_post(self): """A helper function that creates a post object from the data.""" data = self.data post = Post(data['title'], data['author'], data['text'], data['slug'], parser=data['parser'], content_type=self.content_type, pub_date=data['pub_date']) post.bind_categories(data['categories']) post.bind_tags(data['tags']) self._set_common_attributes(post) self.post = post return post def save_changes(self): """Save the changes back to the database. This also adds a redirect if the slug changes. """ if not self.data['pub_date']: # If user deleted publication timestamp, make a new one. self.data['pub_date'] = datetime.utcnow() old_slug = self.post.slug old_parser = self.post.parser forms.set_fields(self.post, self.data, 'title', 'author', 'parser') if (self.data['text'] != self.post.text or self.data['parser'] != old_parser): self.post.text = self.data['text'] add_redirect = self.post.is_published and old_slug != self.post.slug self.post.touch_times(self.data['pub_date']) self.post.bind_slug(self.data['slug']) self._set_common_attributes(self.post) if add_redirect: register_redirect(old_slug, self.post.slug) def _set_common_attributes(self, post): forms.set_fields(post, self.data, 'comments_enabled', 'pings_enabled', 'status') post.bind_categories(self.data['categories']) post.bind_tags(self.data['tags']) def taglist(self): """Return all available tags as a JSON-encoded list.""" tags = [t.name for t in Tag.query.all()] return dump_json(tags)