def description_from_content(self): """ Returns the first block or sentence of the first content-like field. """ description = "" # Use the first RichTextField, or TextField if none found. for field_type in (RichTextField, models.TextField): if not description: for field in self._meta.fields: if isinstance(field, field_type) and \ field.name != "description": description = getattr(self, field.name) if description: break # Fall back to the title if description couldn't be determined. if not description: description = unicode(self) # Strip everything after the first block or sentence that has content. py_description = pq(description) tag_method_success = False for tag_name in ['p', 'ul']: if tag_method_success: break py_tags = py_description.find(tag_name) for tag in py_tags: py_tag = pq(tag) if py_tag.text().strip(): description = py_tag.outerHtml() description = truncatewords_html(description, 100) tag_method_success = True break if not tag_method_success: # If the previous method failed, try this method ends = ("<br />", "<br/>", "<br>", "\n", ". ", "! ", "? ") for end in ends: pos = description.lower().find(end) if pos > -1: description = TagCloser(description[:pos]).html break else: description = truncatewords_html(description, 100) return description
def render_news_placeholder(context, obj, name=False, truncate=False): """ Template tag to render a placeholder from an object, which has a placeholders many-to-many-field. """ result = '' if context.get('request') and hasattr(obj, 'placeholders'): if isinstance(name, int): # If the user doesn't want to use a placeholder name, but a cut, we # need to check if the user has used the name as a number truncate = name name = False if name: # If the name of the placeholder slot is given, get, render and # return it! try: result = safe(obj.placeholders.get(slot=name).render( context, None)) except ObjectDoesNotExist: pass else: # If no name is provided get the first placeholder with content for placeholder in obj.placeholders.all(): rendered = safe(placeholder.render(context, None)) if rendered: result = rendered break if truncate: return truncatewords_html(result, truncate) return result
def test_truncate_complex(self): self.assertEqual( truncatewords_html( '<i>Buenos días! ¿Cómo está?</i>', 3), '<i>Buenos días! ¿Cómo …</i>', )
def save(self, *args, **kwargs): """ Create the description from the content if none given. """ if self.publish_date is None: # publish_date will be blank when a blog post is created from the # quick blog form in the admin dashboard. self.publish_date = datetime.now() if not self.description: for field_type in (HtmlField, models.TextField): if not self.description: for field in self._meta.fields: if isinstance(field, field_type): self.description = getattr(self, field.name) if self.description: break if not self.description: self.description = self.title for end in ("</p>", "<br />", "\n", ". "): if end in self.description: self.description = self.description.split(end)[0] + end break else: self.description = truncatewords_html(self.description, 100) super(Displayable, self).save(*args, **kwargs)
def markdown( text, heading_baselevel=1, filter_tags=True, truncate=False, disable_tags="", plain_preview=False, preset=None, plain=False): def wrap(result): if plain or plain_preview: return result else: script = """ <script type='text/markdown' data-original-content>{}</script> """.format(json.dumps(html.escape(text))) return "<div>{}{}</div>".format(script, result) extensions = tuple(core_markdown.markdown_extensions) + ( toc.TocExtension(baselevel=heading_baselevel, marker='[INHALT]'), ) result = python_markdown.markdown(text, extensions=extensions) if preset == 'linkonly': result = bleach(result, disable_tags='all', except_for=('a',)) elif filter_tags: disabled_tags = tuple(disable_tags.split(",")) result = bleach(result, disabled_tags) if truncate: result = defaultfilters.truncatewords_html(result, truncate) if plain_preview: result = bleach(result, disable_tags="all") result = defaultfilters.truncatewords(result, plain_preview) result = django_html.conditional_escape(result) return safestring.mark_safe(wrap(result))
def clean(self, *args, **kwargs): import markdown import html2text from agora_site.agora_core.templatetags.string_tags import urlify_markdown from django.template.defaultfilters import truncatewords_html cleaned_data = super(ElectionAdminForm, self).clean() if not self.instance.has_perms('edit_details', self.request.user): raise ImmediateHttpResponse(response=http.HttpForbidden()) cleaned_data['pretty_name'] = clean_html(cleaned_data['pretty_name'], True) cleaned_data['description'] = clean_html(cleaned_data['description']) short_description = cleaned_data['short_description'] short_description = html2text.html2text(short_description[:140]).strip() short_description = markdown.markdown(urlify_markdown(short_description), safe_mode="escape", enable_attributes=False) cleaned_data['short_description'] = truncatewords_html(short_description, 25)[:140] from_date = cleaned_data.get("from_date", None) to_date = cleaned_data.get("to_date", None) if not from_date and not to_date: return cleaned_data if from_date < timezone.now(): raise django_forms.ValidationError(_('Invalid start date, must be ' 'in the future')) if from_date and to_date and ((to_date - from_date) < datetime.timedelta(hours=1)): raise django_forms.ValidationError(_('Voting time must be at least 1 hour')) return cleaned_data
def idea_list(): ideas = Idea.objects.filter(is_hidden=False, status__is_invalid=False).order_by('-id')[:IDEAS_IN_HOMEPAGE] html = '' for idea in ideas: description = truncatewords_html(idea.description, 20) html += '<div class="idea"><p class="title"><a href="%s">%s</a></p><p class="description">%s</p></div>' % (idea.get_absolute_url(), idea.title, description) return html
def description_from_content(self): """ Returns the first block or sentence of the first content-like field. """ description = "" if not self.gen_description and self.description: return self.description # Use the first RichTextField, or TextField if none found. for field_type in (RichTextField, models.TextField): if not description: for field in self._meta.fields: if isinstance(field, field_type) and field.name != "description": description = getattr(self, field.name) if description: break # Fall back to the title if description couldn't be determined. if not description: description = unicode(self) # Strip everything after the first block or sentence. ends = ("</p>", "<br />", "<br/>", "<br>", "</ul>", "\n", ". ", "! ", "? ") for end in ends: pos = description.lower().find(end) if pos > -1: description = TagCloser(description[:pos]).html break else: description = truncatewords_html(description, 100) return description
def get_feed_articles(self): feed_data = feedparser.parse(self.url) for entry in feed_data.entries: try: article = Article.objects.get(url=entry.link) except: article = Article() article.title = entry.title article.url = entry.link article.description = entry.description article.description_truncated = truncatewords_html( entry.description, 150) # Set publication date try: published = entry.published_parsed except AttributeError: try: published = entry.updated_parsed except AttributeError: published = entry.created_parsed publication_date = datetime.datetime.fromtimestamp( mktime(published)) date_string = publication_date.strftime('%Y-%m-%d %H:%M:%S') article.publication_date = date_string article.feed = self article.save()
def excerpt(self): """Return a post excerpt.""" if self.tease_rendered: return self.tease_rendered return truncatewords_html(self.body_rendered, settings.BLOG_EXCERPTLENGTH)
def dehydrate(self, bundle): bundle.data['facebook_link'] = bundle.obj.get_link bundle.data['member'] = bundle.obj.feed.persona.owner.name bundle.data['party'] = bundle.obj.feed.persona.owner.current_party.name bundle.data['published_str'] = humanize.naturaltime(bundle.obj.published) bundle.data['content_snippet'] = truncatewords_html(linebreaks(append_separators(urlize(bundle.obj.content))), MAX_LENGTH_FOR_STATUS_CONTENT) if bundle.obj.has_attachment: bundle.data['has_attachment'] = True bundle.data['attachment'] = { 'type': bundle.obj.attachment.type, 'is_photo': bundle.obj.attachment.type == 'photo', 'is_video': bundle.obj.attachment.type == 'video', 'is_youtube_video': bundle.obj.attachment.is_youtube_video, 'is_link': bundle.obj.attachment.type == 'link', 'is_event': bundle.obj.attachment.type == 'event', 'is_music': bundle.obj.attachment.type == 'music', 'is_note': bundle.obj.attachment.type == 'note', 'is_nonetype': not bundle.obj.attachment.type, 'link': bundle.obj.attachment.link, 'picture': bundle.obj.attachment.picture, 'name': bundle.obj.attachment.name, 'caption': bundle.obj.attachment.caption, 'description': bundle.obj.attachment.description, 'source': bundle.obj.attachment.source, 'source_clean': bundle.obj.attachment.source_clean } return bundle
def description_from_content(self): """ Returns the first block or sentence of the first content-like field. """ description = "" # Use the first RichTextField, or TextField if none found. for field_type in (RichTextField, models.TextField): if not description: for field in self._meta.fields: if (isinstance(field, field_type) and field.name != "description"): description = getattr(self, field.name) if description: from mezzanine.core.templatetags.mezzanine_tags \ import richtext_filters description = richtext_filters(description) break # Fall back to the title if description couldn't be determined. if not description: description = str(self) # Strip everything after the first block or sentence. ends = ("</p>", "<br />", "<br/>", "<br>", "</ul>", "\n", ". ", "! ", "? ") for end in ends: pos = description.lower().find(end) if pos > -1: description = TagCloser(description[:pos]).html break else: description = truncatewords_html(description, 100) return description
def description_from_content(self): """ Returns the first paragraph of the first content-like field. """ description = "" # Get the value of the first HTMLField, or TextField if none found. for field_type in (HtmlField, models.TextField): if not description: for field in self._meta.fields: if isinstance(field, field_type) and \ field.name != "description": description = getattr(self, field.name) if description: break # Fall back to the title if description couldn't be determined. if not description: description = self.title # Strip everything after the first paragraph or sentence. for end in ("</p>", "<br />", "\n", ". "): if end in description: description = description.split(end)[0] + end break else: description = truncatewords_html(description, 100) return description
def _convert_to_dict(post): return { 'Title': post.Title, 'Shortcut': post.Shortcut, 'Repr' : truncatewords_html(striptags(post.Content), 20), 'CreationDateTime': date(post.CreationDateTime, "j F Y") }
def description_from_content(self): """ Returns the first paragraph of the first content-like field. """ description = "" # Get the value of the first HTMLField, or TextField if none found. for field_type in (HtmlField, models.TextField): if not description: for field in self._meta.fields: if isinstance(field, field_type) and \ field.name != "description": description = getattr(self, field.name) if description: break # Fall back to the title if description couldn't be determined. if not description: description = self.title # Strip everything after the first paragraph or sentence. for end in ("</p>", "<br />", "\n", ". "): if end in description: description = description.split(end)[0] + end break else: description = truncatewords_html(description, 100) return description
def excerpt(self): """ Return the excerpt of a post, respecting the auto excerpt settings, with a link to continue reading if appropriate. """ # Create the link to continue reading the full post. continue_link = """ <p class="continue"> <a href="%s" title="Continue reading this post">%s</a> </p> """ % (self.get_absolute_url(), settings.BLOG_CONTINUE) excerpt = self.tease_rendered # If auto excerpts are enabled and the post does not have a tease, # truncate the body and set that to the tease. if settings.BLOG_AUTOEXCERPTS and not self.tease: excerpt = truncatewords_html(self.body_rendered, settings.BLOG_AUTOEXCERPTS) # If the auto excerpt is the same as the full body, set the # continue link to an empty string so that it is not displayed. if excerpt == self.body_rendered: continue_link = "" # If there is an excerpt, return it followed by the continue link. if excerpt: return "%s %s" % (excerpt, mark_safe(continue_link)) # If we're still here, there is no excerpt. return False
def description_from_content(self): """ Returns the first block or sentence of the first content-like field. """ description = "" # Use the first RichTextField, or TextField if none found. for field_type in (RichTextField, models.TextField): if not description: for field in self._meta.fields: if isinstance(field, field_type) and \ field.name != "description": description = getattr(self, field.name) if description: from mezzanine.core.templatetags.mezzanine_tags \ import richtext_filters description = richtext_filters(description) break # Fall back to the title if description couldn't be determined. if not description: description = str(self) # Strip everything after the first block or sentence. ends = ("</p>", "<br />", "<br/>", "<br>", "</ul>", "\n", ". ", "! ", "? ") for end in ends: pos = description.lower().find(end) if pos > -1: description = TagCloser(description[:pos]).html break else: description = truncatewords_html(description, 100) return description
def markdown(text, heading_baselevel=1, filter_tags=True, truncate=False, disable_tags="", plain_preview=False, preset=None, plain=False): def wrap(result): if plain or plain_preview: return result else: script = """ <script type='text/markdown' data-original-content>{}</script> """.format(json.dumps(html.escape(text))) return "<div>{}{}</div>".format(script, result) extensions = tuple(core_markdown.markdown_extensions) + (toc.TocExtension( baselevel=heading_baselevel, marker='[INHALT]'), ) result = python_markdown.markdown(text, extensions=extensions) if preset == 'linkonly': result = bleach(result, disable_tags='all', except_for=('a', )) elif filter_tags: disabled_tags = tuple(disable_tags.split(",")) result = bleach(result, disabled_tags) if truncate: result = defaultfilters.truncatewords_html(result, truncate) if plain_preview: result = bleach(result, disable_tags="all") result = defaultfilters.truncatewords(result, plain_preview) result = django_html.conditional_escape(result) return safestring.mark_safe(wrap(result))
def get_feed_articles(self): feed_data = feedparser.parse(self.url) for entry in feed_data.entries: try: article = Article.objects.get(url=entry.link) except: article = Article() article.title = entry.title article.url = entry.link article.description = entry.description article.description_truncated = truncatewords_html(entry.description, 150) # Set publication date try: published = entry.published_parsed except AttributeError: try: published = entry.updated_parsed except AttributeError: published = entry.created_parsed publication_date = datetime.datetime.fromtimestamp(mktime(published)) date_string = publication_date.strftime('%Y-%m-%d %H:%M:%S') article.publication_date = date_string article.feed = self article.save()
def html(value, truncate_at): #sanitize on output too? trunc_value = truncatewords_html(value, truncate_at) if len(trunc_value) < len(value): value = '<div class="truncated">%(trunc_value)s<a class="more" href="#">more</a></div><div class="untruncated">%(value)s<a class="less" href="#">less</a></div>' % ( dict(value=value, trunc_value=trunc_value)) return value, True
def obj_to_dict(obj): """ A helper that changes various types of content into a unified format, that will help us show them in templates. Works as a simple serializer. *deprecated* - it's much better to use activities app. """ content_type = ContentType.objects.get_for_model(obj) context = { "type": content_type.model, "name": capfirst(_(content_type.model)), "slug": obj.slug, "ct": content_type.pk, "pk": obj.pk, "url": obj.get_absolute_url(), "title": obj.__unicode__(), "image": obj.image_url, "thumbnail": obj.thumbnail, "retina_thumbnail": False, "location": obj.location.__unicode__(), "meta": {}, "date_created": obj.date_created.isoformat(), "creator": { "id": obj.creator.pk, "url": obj.creator.profile.get_absolute_url(), "img": obj.creator.profile.avatar.url, "name": obj.creator.get_full_name(), }, } if hasattr(obj, "category") and obj.category is not None and obj.category.pk: context.update({"category": {"pk": obj.category.pk, "name": obj.category.__unicode__()}}) if hasattr(obj, "retina_thumbnail") and not obj.has_default_image: context["retina_thumbnail"] = obj.retina_thumbnail if hasattr(obj, "has_default_image"): context["default_image"] = obj.has_default_image if content_type.model == "idea": context.update({"description": obj.description, "meta": {"votes": obj.get_votes()}}) elif content_type.model == "poll": context.update({"description": obj.question}) elif content_type.model == "news": context.update({"description": obj.content}) elif content_type.model == "discussion": context.update({"description": obj.intro, "meta": {"answers": obj.entry_set.count()}}) elif content_type.model == "socialproject": context["description"] = obj.get_description() context["name"] = _("Project") else: raise Exception(_("Wrong model instance")) context["description"] = truncatewords_html(context["description"], 15) return context
def _item_short_description(self, item): excerpt = item.excerpt_en if get_language( ) is 'en' else item.excerpt_fr body = item.body_en if get_language() is 'en' else item.body_fr if excerpt and excerpt.strip() != '': return excerpt else: return truncatewords_html(body, 70)
def render(self, context): if not self.words == 50: self.words = self.words.render(context) page = self.page.resolve(context) context["excerpt_url"] = page.url context["excerpt_title"] = page.title rendered = get_bracketed_content(context, page, "Excerpt") return truncatewords_html(rendered, self.words)
def post_excerpt(context, post): if post.excerpt: return post.excerpt from feincms.content.richtext.models import RichTextContent text_content = filter(lambda x: isinstance(x, RichTextContent), post.content.main) if text_content: return truncatewords_html(text_content[0].text, 40) return ""
def make_post(post, turncate=False): if turncate: turncate = int(turncate) if wordcount(post.body_html) >= turncate: post.body_html = truncatewords_html(post.body_html, turncate) else: turncate = False return {"post": post, "turncate": turncate}
def test_truncatewords_html(self): self.assertEqual( truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 0), '') self.assertEqual( truncatewords_html( '<p>one <a href="#">two - ' 'three <br>four</a> five</p>', 2), '<p>one <a href="#">two ...</a></p>') self.assertEqual( truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 4), '<p>one <a href="#">two - three <br>four ...</a></p>') self.assertEqual( truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 5), '<p>one <a href="#">two - three <br>four</a> five</p>') self.assertEqual( truncatewords_html( '<p>one <a href="#">two - three <br>four</a> five</p>', 100), '<p>one <a href="#">two - three <br>four</a> five</p>') self.assertEqual(truncatewords_html('\xc5ngstr\xf6m was here', 1), '\xc5ngstr\xf6m ...') self.assertEqual( truncatewords_html( '<i>Buenos días! ' '¿Cómo está?</i>', 3), '<i>Buenos días! ¿Cómo ...</i>')
def firstpara(article): '''Truncate an article by excluding everything after the first paragraph.''' try: index = article.index('</p>') return article[:index + 4] except ValueError: # Fall-back to default truncatewords_html tag if we can't identify a # paragraph. return truncatewords_html(article, 80)
def item_description(self, item): if hasattr(item, 'description'): description = item.description else: if hasattr(item, 'details'): description = item.details else: description = item.title return truncatewords_html(description, 100)
def idea_list(): ideas = Idea.objects.filter( is_hidden=False, status__is_invalid=False).order_by('-id')[:IDEAS_IN_HOMEPAGE] html = '' for idea in ideas: description = truncatewords_html(idea.description, 20) html += '<div class="idea"><p class="title"><a href="%s">%s</a></p><p class="description">%s</p></div>' % ( idea.get_absolute_url(), idea.title, description) return html
def formatted(context, post=None, truncate=None): if not post: post = context['post'] ctx = {'preview': True} if truncate else {} [ctx.update(c) for c in context.dicts] res = bbcode64(post, ctx) if truncate: return truncatewords_html(res, truncate) else: return res
def truncate_descriptions_task(): """ truncates descriptions for existing articles """ articles = Article.objects.all() for article in articles: logger.info("Truncating Description for " + article.title) article.description_truncated = truncatewords_html(article.description, 150) article.save()
def tease_rendered(self): cache_key = "blog.post.pk:{0}.tease.updated:{1}".format( self.pk, self.updated_at.isoformat() ) return cache.get_or_set_callback( cache_key, lambda: formatter((self.tease or truncatewords_html(self.body, 150)), self.markup), timeout=5 * 3600, )
def filter_markdown(value, words=None): html = markdown.markdown(value) html = re.sub(r'<(?!\/?a(?=>|\s.*>))\/?.*?>', '', html) html = mark_safe(linebreaksbr(urlize(html))) if words: return truncatewords_html(html, words) return html
def truncate_descriptions_task(): """ truncates descriptions for existing articles """ articles = Article.objects.all() for article in articles: logger.info("Truncating Description for " + article.title) article.description_truncated = truncatewords_html(article.description, 150) article.save()
def filter_markdown(value, words=None): html = markdown.markdown(value) html = re.sub(r'<(?!\/?a(?=>|\s.*>))\/?.*?>', '', html) html = mark_safe(linebreaksbr(urlize(html))) if words: return truncatewords_html(html, words) return html
def format_history_text(text): """Run history text through some cleaning and add ellipsis if it's too long.""" full = mark_safe(text) if text.startswith("This was part of a ballot set with:"): full = urlize_ietf_docs(full) full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(full))))) snippet = truncatewords_html(full, 25) if snippet != full: return mark_safe(u'<div class="snippet">%s<span class="show-all">[show all]</span></div><div style="display:none" class="full">%s</div>' % (snippet, full)) return full
def post_tease(request, post_id): try: post = Post.objects.get(pk=post_id) except Post.DoesNotExist: raise Http404 arrow = '<p class="more span-15"><a href="%s">READ ON »</a></p>' % post.get_absolute_url() if not post.tease: return HttpResponse(truncatewords_html(post.body, 300) + arrow) return HttpResponse(post.tease + arrow)
def post_tease(request, post_id): try: post = Post.objects.get(pk=post_id) except Post.DoesNotExist: raise Http404 arrow = '<p class="more span-15"><a href="%s">READ ON »</a></p>' % post.get_absolute_url() if not post.tease: return HttpResponse(truncatewords_html(post.body, 300) + arrow) return HttpResponse(post.tease + arrow)
def get_results(self, keywords): results = [] for event in Event.on_site.upcoming(): title_score = event.name.lower().count(keywords) * 5 # Name has five times the relevance of description desc_score = event.description.lower().count(keywords) total_score = title_score + desc_score snippet = event.description if total_score > 0: import textile snippet = truncatewords_html(textile.textile(snippet.encode('ascii','xmlcharrefreplace')), 25) results.append((event, event.name, snippet, total_score)) return results
def get_results(self, keywords): results = [] for item in EventsItem.on_site.published(): title_score = item.title.lower().count(keywords) * 5 # `title` has five times the relevance of body body_score = item.body.lower().count(keywords) total_score = title_score + body_score snippet = item.snippet or item.body if total_score > 0: import textile snippet = truncatewords_html(textile.textile(snippet.encode('ascii','xmlcharrefreplace')), 25) results.append((item, item.title, snippet, total_score)) return results
def format_snippet(text, trunc_words=25): # urlize if there aren't already links present if not 'href=' in text: text = urlize(text) full = keep_spacing( collapsebr(linebreaksbr(mark_safe(sanitize_html(text))))) snippet = truncatewords_html(full, trunc_words) if snippet != full: return mark_safe( u'<div class="snippet">%s<button class="btn btn-xs btn-default show-all"><span class="fa fa-caret-down"></span></button></div><div class="hidden full">%s</div>' % (snippet, full)) return full
def admin_summery(self): """ Returns the first paragraph or the firest 100 characters of the content. """ content_without_images = re.sub("<p><img.*?></p>", "", self.content) for end in ("</p>", "<br />", "\n", ". "): if end in content_without_images: summery = content_without_images.split(end)[0] + end break else: summery = truncatewords_html(content_without_images, 100) return summery
def admin_summery(self): """ Returns the first paragraph or the firest 100 characters of the content. """ content_without_images = re.sub("<p><img.*?></p>", '', self.content) for end in ("</p>", "<br />", "\n", ". "): if end in content_without_images: summery = content_without_images.split(end)[0] + end break else: summery = truncatewords_html(content_without_images, 100) return summery
def get_results(self, keywords): results = [] for item in NewsItem.on_site.published(): title_score = item.title.lower().count( keywords) * 5 # `title` has five times the relevance of body body_score = item.body.lower().count(keywords) total_score = title_score + body_score snippet = item.snippet or item.body if total_score > 0: import textile snippet = truncatewords_html( textile.textile( snippet.encode('ascii', 'xmlcharrefreplace')), 25) results.append((item, item.title, snippet, total_score)) return results
def save(self, *args, **kwargs): """ Create the description from the content if none given. """ if self.publish_date is None: # publish_date will be blank when a blog post is created from the # quick blog form in the admin dashboard. self.publish_date = datetime.now() if not self.description: for s in ("</p>", "\n", ". "): if s in self.content: self.description = self.content.split(s)[0] + s break else: self.description = truncatewords_html(self.content, 100) super(Displayable, self).save(*args, **kwargs)
def render(self, context): message = self.message.resolve(context) if self.translated: message_str = message.body_translated else: message_str = message.body try: plan = context["user"].get_profile().subscription if not plan or plan.membership_plan.free: message_str = truncatewords_html(message_str, FREE_MEMBER_TRUNCATE_MESSAGE_WORDS) except (AttributeError, ObjectDoesNotExist): pass return linebreaksbr(message_str)
def format_message(text, limit=2500, strip_tags=False): """ Opérations sur le texte des messages privés 1. Retirer tous les tags ou n'en garder que les principaux 2. Transformer tous les sauts de lignes en balises <br> 3. Couper en deux les mots trop longs 4. Limiter le texte à un nombre de mots proche de la limite en caractères """ body = striptags(text) if strip_tags is True else tags_keep( text, "strong em blockquote b p u i h2 h3 pre br") body = linebreaks_convert(body) body = truncate_longwords_html(body) body = truncatewords_html( body, limit // 6.06) # 6.06 estimation de caractères par mot en fr (espaces inclus) return body
def rendersummary(context, *args): """ Renders the arguments as a template themselves. This allows for treating text obtained from the model as template code. {% render page.content %} """ if len(args) == 1: return Template(args[0], 'rendersummary').render(context) bits = [] for arg in args: bits.append(Template(arg, 'rendersummary').render(context)) summary = mark_safe(u''.join(bits)) for end in ("</p>", "<br />", "<br/>", "</br>", "\n", ". "): if end in summary: summary = summary.split(end)[0] + end summary = truncatewords_html(summary, 100) return summary
def render(self, name, value, attrs=None): # Formats decimal value with period instead dot if moneyformat does it if isinstance(value, Decimal): value = moneyformat(value, self.decimal_places) if self.display is None: if self.object: method_name = 'get_%s_value' % name r = getattr(self.object, name) if hasattr(self.object, method_name): r = getattr(self.object, method_name)(r) else: r = value else: r = self.display try: display = getattr(self.object, 'get_%s_display' % name)() except AttributeError: if type(r) == datetime.date: value = display = format(r, settings.DATE_FORMAT) elif type(r) == datetime.datetime: value = display = format(r, settings.DATETIME_FORMAT) elif self.choices: display = dict(self.choices)[value] else: s = force_unicode(r, strings_only=False) display = truncatewords_html(linebreaksbr(s), 50) if isinstance(value, models.Model): value = value.pk # Avoid "None" value on front end display = display != 'None' and display or '' # Avoid None value value = value is not None and value or '' return mark_safe( '<span class="value read-only-widget">%s</span> <input type="hidden" name="%s" value="%s" id="%s">' % ( display, self.show_input and name or '', value, attrs.get('id', 'id_' + name), ))
def load_news(): """ Restores the news from the old Stigull database Usage: load_news() Pre: None Post: The batch of old news have been inserted into the new database """ users = scripts.load_objects("auth.user.txt") news = scripts.load_objects("news.txt") changes = scripts.load_objects("change.txt") comments = scripts.load_objects("comments.txt") print users, news, changes, comments for pk, entry_dict in news.itervalues(): #Zero or more news from news have been traversed #Each entry has the following fields # title, titleEn, body, bodyEn, datetimeCreated, author, changes, comments #For each entry a new Entry has been created with two 'Content' objects user = User.objects.get(username = users[news['author']].username) body_html = markdown(entry_dict['body']) body_en_html = markdown(entry_dict['bodyEn']) excerpt = truncatewords_html(body_html, 30) entry = Entry(publish_date = entry_dict['datetimeCreated'], author = user, enable_comments = True, status = Entry.LIVE_STATUS, slug = slugify(entry_dict['title']), excerpt = excerpt ) content_is = Content(entry = entry, language = 'is', title = entry_dict['title'], body = entry_dict['body'], body_html = body_html) content_en = Content(entry = entry, language = 'en', title = entry_dict['titleEn'], body = entry_dict['bodyEn'], body_html = body_en_html)
def import_wp(language): from django.template.defaultfilters import truncatewords_html from cms.api import add_plugin from wordpress.models import Post as WPost from djangocms_blog.models import Post, BlogCategory from django.contrib.auth.models import User for post in WPost.objects.published(): print post.title author = None users = User.objects.filter(username=post.author.login) if users.exists(): author = users[0] if not author: users = User.objects.filter(email=post.author.email) if users.exists(): author = users[0] if not author: author = User.objects.get(pk=1) new_post = Post() new_post.set_current_language(language) new_post.title = post.title new_post.slug = post.slug new_post.abstract = truncatewords_html(post.content, 20) new_post.date_created = post.post_date new_post.date_published = post.post_date new_post.date_modified = post.modified new_post.save() add_plugin(new_post.content, 'TextPlugin', language, body=post.content) if author: new_post.author = author for cat in post.categories(): try: category = BlogCategory.objects.language(language).get( translations__name=cat.name) except BlogCategory.DoesNotExist: category = BlogCategory() category.set_current_language(language) category.name = cat.name category.save() new_post.categories.add(category.pk) if post.tags(): for tag in post.tags(): new_post.tags.add(tag.name) new_post.save()
def create_post(post_data, parts): try: first_part = parts[0] except IndexError: first_part = post_data['title'] post_with_slug = Post.objects.filter(slug=post_data['slug']) if post_with_slug.exists(): raise ValueError('Slug is not unique') post = Post( title=post_data['title'], slug=post_data['slug'], lead_in=truncatewords_html(first_part, 55), publication_start=post_data['publication_start'], author=post_data['user'], language=post_data['language'], ) post.save() return post
def save(self, *args, **kwargs): if not self.description: # Extract the first few words of the content and remove the html tags. self.description = striptags(truncatewords_html(self.content, 15))[:257] if hasattr(self, '_renderer'): delattr(self, '_renderer') if not self.author: self.author = self.last_edited_by super().save(*args, **kwargs) # Sync last update of pages showing this item. related_pages = Page.objects.filter( id__in=self.pageitemlayout_set.values_list('page_id', flat=True)) related_pages.update(last_updated=timezone.now()) # Invalidate cache. for page in related_pages: delete_cache_for_page(page)
def get_messages(**options): for message_data in fetch_messages(**options): channel = options['channel'] email_message = email.message_from_bytes(message_data) subject = decoded_header(email_message.get('Subject')) from_header = email_message.get('From') to_header = email_message.get('To') from_name = email.utils.getaddresses([from_header])[0][0] msgid = email_message.get('Message-ID').strip() should_notify = True try: if not options.get('text', ''): should_notify = not MailMessage.objects.get(pk=msgid) except MailMessage.DoesNotExist: pass if should_notify: # Create a nicely-formatted version of the message body, mimetype = get_body(email_message) reply = quotations.extract_from(body, mimetype) text, sig = signature.extract(reply, sender=from_header) if mimetype == "text/html": text = HTMLSlacker(text).get_output() msg = "_{}_ to _{}_\n*{}*\n\n{}".format(from_name, to_header, subject, text) msg = truncatewords_html(msg, 400) opts = {'channel': channel, 'text': msg} # Attempt to thread any email conversation as a Slack thread references = email_message.get('References', '').split() thread = MailMessage.objects.filter(msgid__in=references) sc = SlackClient(os.environ['SLACK_TOKEN']) # Send the message response = sc.api_call("chat.postMessage", **opts) if thread: # Also add it as a thread opts['thread_ts'] = thread.first().slackthread_ts response = sc.api_call("chat.postMessage", **opts) if response['ok']: ts = response['ts'] msg, created = MailMessage.objects.get_or_create( subject=subject, msgid=msgid) msg.slackthread_ts = ts msg.save()
def clean(self, *args, **kwargs): import markdown import html2text from agora_site.agora_core.templatetags.string_tags import urlify_markdown from django.template.defaultfilters import truncatewords_html cleaned_data = super(ElectionAdminForm, self).clean() if not self.instance.has_perms('edit_details', self.request.user): raise ImmediateHttpResponse(response=http.HttpForbidden()) cleaned_data['pretty_name'] = clean_html(cleaned_data['pretty_name'], True) cleaned_data['description'] = clean_html(cleaned_data['description']) short_description = cleaned_data['short_description'] short_description = html2text.html2text( short_description[:140]).strip() short_description = markdown.markdown( urlify_markdown(short_description), safe_mode="escape", enable_attributes=False) cleaned_data['short_description'] = truncatewords_html( short_description, 25)[:140] from_date = cleaned_data.get("from_date", None) to_date = cleaned_data.get("to_date", None) if not from_date and not to_date: return cleaned_data if from_date < timezone.now(): raise django_forms.ValidationError( _('Invalid start date, must be ' 'in the future')) if from_date and to_date and ( (to_date - from_date) < datetime.timedelta(hours=1)): raise django_forms.ValidationError( _('Voting time must be at least 1 hour')) return cleaned_data
def render_news_placeholder(context, obj, name=False, truncate=False): # pragma: nocover # NOQA """ DEPRECATED: Template tag to render a placeholder from an NewsEntry object We don't need this any more because we don't have a placeholders M2M field on the model any more. Just use the default ``render_placeholder`` tag. """ warnings.warn( "render_news_placeholder is deprecated. Use render_placeholder" " instead", DeprecationWarning, stacklevel=2) result = '' if context.get('request'): if isinstance(name, int): # If the user doesn't want to use a placeholder name, but a cut, we # need to check if the user has used the name as a number truncate = name name = False if name: # If the name of the placeholder slot is given, get, render and # return it! try: result = safe(getattr(obj, name).render(context, None)) except AttributeError: pass else: # If no name is provided get the first placeholder with content for name in ['excerpt', 'content']: rendered = '' try: rendered = safe(getattr(obj, name).render(context, None)) except AttributeError: pass if rendered: result = rendered break if truncate: return truncatewords_html(result, truncate) return result
def parse_entry(self, entry, feed_instance, latest): url = feed_instance.website_rss published_parsed = entry.get('published_parsed') # Maybe it's an atom feed? if not published_parsed: published_parsed = entry.get('updated_parsed') if not published_parsed: logger.error("feed: '%s' has no published or updated date", url) return published = datetime.fromtimestamp( time.mktime(published_parsed)).replace(tzinfo=utc) if latest and latest.publishdate >= published: logger.debug("feed: '%s' has no more new entries", url) raise ItemOlderThenLatest() if not entry.link: logger.error("feed '%s' entry has no link, skipping", url) return logger.debug("import feed entry '%s'", entry.title) item = FeedItem(title=entry.title, publishdate=published, url=entry.link) item.feed = feed_instance if entry.get('description'): summary = bleach.clean(entry.description, strip=True) if len(summary) > FEEDITEM_SUMMARY_LIMIT: summary = truncatewords_html(summary, 100) item.summary = summary if entry.get('author'): item.author = entry.get('author') return item
def render(self, context): sitemap_node = None self.path = self.path.render(context).strip('"') sitemap_node = context["site"].find_node(Folder(self.path)) if not sitemap_node: sitemap_node = context["site"] def later(page1, page2): return (page1, page2)[page2.created > page1.created] page = reduce(later, sitemap_node.walk_pages()) rendered = None rendered = render_to_string(str(page), context) excerpt_start = marker_start % "Excerpt" excerpt_end = marker_end % "Excerpt" start = rendered.find(excerpt_start) if not start == -1: context["latest_excerpt_url"] = page.url context["latest_excerpt_title"] = page.title start = start + len(excerpt_start) end = rendered.find(excerpt_end, start) return truncatewords_html(rendered[start:end], self.words) else: return ""
def dehydrate(self, bundle): bundle.data['facebook_link'] = bundle.obj.get_link bundle.data['member'] = bundle.obj.feed.persona.owner.name bundle.data['party'] = bundle.obj.feed.persona.owner.current_party.name bundle.data['published_str'] = humanize.naturaltime(bundle.obj.published) if 'content__contains' in bundle.request.GET: # add a full snippet with highlighted search field htmlized_content = linebreaks(append_separators(urlize(bundle.obj.content))) search_pattern = re.compile(bundle.request.GET['content__contains']) bundle.data['content_snippet'] = re.sub(search_pattern, add_html_tag, htmlized_content) # print bundle.data['content_snippet'] else: # add a shortened snippet bundle.data['content_snippet'] = truncatewords_html( linebreaks(append_separators(urlize(bundle.obj.content))), MAX_LENGTH_FOR_STATUS_CONTENT) if bundle.obj.has_attachment: bundle.data['has_attachment'] = True bundle.data['attachment'] = { 'type': bundle.obj.attachment.type, 'is_photo': bundle.obj.attachment.type == 'photo', 'is_video': bundle.obj.attachment.type == 'video', 'is_youtube_video': bundle.obj.attachment.is_youtube_video, 'is_link': bundle.obj.attachment.type == 'link', 'is_event': bundle.obj.attachment.type == 'event', 'is_music': bundle.obj.attachment.type == 'music', 'is_note': bundle.obj.attachment.type == 'note', 'is_nonetype': not bundle.obj.attachment.type, 'link': bundle.obj.attachment.link, 'picture': bundle.obj.attachment.picture, 'name': bundle.obj.attachment.name, 'caption': bundle.obj.attachment.caption, 'description': bundle.obj.attachment.description, 'source': bundle.obj.attachment.source, 'source_clean': bundle.obj.attachment.source_clean } return bundle
def get_feed_articles(self): feed_data = feedparser.parse(self.url) for entry in feed_data.entries: try: article = Article.objects.get(url=entry.link) except: article = Article() article.title = entry.title article.url = entry.link article.description = entry.description article.description_truncated = truncatewords_html(entry.description, 150) # Set publication date d = datetime(*(entry.published_parsed[0:6])) dateString = d.strftime('%Y-%m-%d %H:%M:%S') article.publication_date = dateString article.feed = self article.save()