Feed parsing and formatting
This commit is contained in:
parent
9d3b278e4f
commit
48501957a1
5 changed files with 34 additions and 30 deletions
|
@ -12,7 +12,7 @@ def parse(obj, raw, stream):
|
||||||
|
|
||||||
# Date stamp handling
|
# Date stamp handling
|
||||||
ts = raw['published'] / 1000
|
ts = raw['published'] / 1000
|
||||||
obj.published = datetime.utcfromtimestamp(ts)
|
obj.published = datetime.fromtimestamp(ts)
|
||||||
|
|
||||||
# Authorship and title
|
# Authorship and title
|
||||||
obj.title = raw['title']
|
obj.title = raw['title']
|
||||||
|
@ -32,6 +32,8 @@ def parse(obj, raw, stream):
|
||||||
obj.visual = raw['enclosure'][0]['href']
|
obj.visual = raw['enclosure'][0]['href']
|
||||||
elif 'visual' in raw and 'url' in raw['visual']:
|
elif 'visual' in raw and 'url' in raw['visual']:
|
||||||
obj.visual = raw['visual']['url']
|
obj.visual = raw['visual']['url']
|
||||||
|
if obj.visual.lower().strip() == 'none':
|
||||||
|
obj.visual = ''
|
||||||
|
|
||||||
# Collect text in nested JSON content
|
# Collect text in nested JSON content
|
||||||
if 'content' in obj.raw:
|
if 'content' in obj.raw:
|
||||||
|
|
|
@ -12,6 +12,7 @@ from django.core.mail import send_mail
|
||||||
from wagtail.contrib.settings.models import BaseSetting, register_setting
|
from wagtail.contrib.settings.models import BaseSetting, register_setting
|
||||||
|
|
||||||
from .models import Entry, Stream
|
from .models import Entry, Stream
|
||||||
|
import feedler.feedparser as feedparser
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger('feedler')
|
logger = logging.getLogger('feedler')
|
||||||
|
@ -60,5 +61,5 @@ def handle_save_settings(sender, instance, *args, **kwargs):
|
||||||
except Entry.DoesNotExist:
|
except Entry.DoesNotExist:
|
||||||
logger.info("Adding entry '%s'" % eid)
|
logger.info("Adding entry '%s'" % eid)
|
||||||
entry = Entry()
|
entry = Entry()
|
||||||
entry.parse(raw_entry, stream)
|
entry = feedparser.parse(entry, raw_entry, stream)
|
||||||
entry.save()
|
entry.save()
|
||||||
|
|
|
@ -6,8 +6,6 @@ from wagtail.wagtailcore.models import Page, Orderable
|
||||||
from wagtail.wagtailadmin.edit_handlers import FieldPanel
|
from wagtail.wagtailadmin.edit_handlers import FieldPanel
|
||||||
from wagtail.wagtailcore.fields import RichTextField
|
from wagtail.wagtailcore.fields import RichTextField
|
||||||
|
|
||||||
import feedler.feedparser as feedparser
|
|
||||||
|
|
||||||
class Stream(models.Model):
|
class Stream(models.Model):
|
||||||
title = models.CharField(max_length=255)
|
title = models.CharField(max_length=255)
|
||||||
ident = models.CharField(max_length=255)
|
ident = models.CharField(max_length=255)
|
||||||
|
@ -38,10 +36,6 @@ class Entry(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name_plural = 'Entries'
|
verbose_name_plural = 'Entries'
|
||||||
|
|
||||||
def parse(self, raw, stream):
|
|
||||||
# TODO: Exception handling
|
|
||||||
feedparser.parse(self, raw, stream)
|
|
||||||
|
|
||||||
class FeedPage(Page):
|
class FeedPage(Page):
|
||||||
intro = RichTextField(default='', blank=True)
|
intro = RichTextField(default='', blank=True)
|
||||||
stream = models.ForeignKey(Stream, on_delete=models.PROTECT,
|
stream = models.ForeignKey(Stream, on_delete=models.PROTECT,
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
<section id="article-index" class="article-index-page">
|
<section id="article-index" class="article-index-page">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>{{ page.title }}</h2>
|
<h2>{{ page.title }}</h2>
|
||||||
<p class="lead">{{ page.intro|richtext }}</p>
|
{% if page.intro %}
|
||||||
|
<p class="lead">{{ page.intro|richtext }}</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -23,15 +25,17 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for entry in feedentries %}
|
{% for entry in feedentries %}
|
||||||
<div class="col-md-4 col-sm-6 col-xs-12">
|
<div class="col-md-4 col-sm-6 col-xs-12">
|
||||||
|
{% if entry.visual %}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
{% if entry.visual %}
|
<img src="{{ entry.visual }}">
|
||||||
<img src="{{ entry.visual }}" width="360">
|
{% else %}
|
||||||
{% endif %}
|
<div class="panel panel-fulltext">
|
||||||
|
{% endif %}
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<h3><span>{{ entry.title }}</span></h3>
|
<h3><span>{{ entry.title|striptags|truncatewords_html:10 }}</span></h3>
|
||||||
<p>
|
<p>
|
||||||
{{ entry.content|striptags|truncatewords_html:40 }}
|
<em><small><span>{{ entry.author }}</span></small></em><br><br>
|
||||||
<br><em><small><span>{{ entry.author }}</span></small></em>
|
{{ entry.content|striptags|truncatewords_html:25 }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ entry.link }}" target="_blank" class="fill"></a>
|
<a href="{{ entry.link }}" target="_blank" class="fill"></a>
|
||||||
|
|
|
@ -2,21 +2,13 @@
|
||||||
// News overview
|
// News overview
|
||||||
#news {
|
#news {
|
||||||
|
|
||||||
.panel-default {
|
.panel-default, .panel-fulltext {
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
padding-top: 75%; /* 1:1 Aspect Ratio */
|
padding-top: 75%; /* 1:1 Aspect Ratio */
|
||||||
position: relative; /* If you want text inside of it */
|
position: relative; /* If you want text inside of it */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: lighten($brand-primary, 10%);
|
background: lighten($brand-primary, 10%);
|
||||||
|
|
||||||
img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-body {
|
.panel-body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -24,10 +16,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transform: translateY(60%);
|
|
||||||
background-color: rgba($brand-primary, .8);
|
background-color: rgba($brand-primary, .8);
|
||||||
transition: transform .65s;
|
|
||||||
|
|
||||||
h3, p {
|
h3, p {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
@ -58,9 +47,6 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover .panel-body {
|
|
||||||
transform: rotateY(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// expand link over the thumbnail
|
// expand link over the thumbnail
|
||||||
a.fill {
|
a.fill {
|
||||||
|
@ -72,6 +58,23 @@
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel-default {
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.panel-body {
|
||||||
|
transform: translateY(60%);
|
||||||
|
transition: transform .65s;
|
||||||
|
}
|
||||||
|
&:hover .panel-body {
|
||||||
|
transform: rotateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// News detail article
|
// News detail article
|
||||||
|
|
Loading…
Reference in a new issue