Feed working

This commit is contained in:
Fergal Moran
2016-07-06 00:11:39 +01:00
parent ef67cba94f
commit 064b19affa
15 changed files with 262 additions and 6 deletions

View File

@@ -98,6 +98,17 @@ class LikeSerializer(serializers.ModelSerializer):
display_name = serializers.ReadOnlyField(source='get_nice_name')
class FavouriteSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = (
'display_name',
'slug',
)
display_name = serializers.ReadOnlyField(source='get_nice_name')
class GenreSerializer(serializers.ModelSerializer):
class Meta:
model = Genre
@@ -162,6 +173,7 @@ class MixSerializer(serializers.ModelSerializer):
'plays',
'downloads',
'is_liked',
'is_favourited',
]
@@ -174,10 +186,11 @@ class MixSerializer(serializers.ModelSerializer):
genres = GenreSerializer(many=True, required=False, read_only=True)
likes = LikeSerializer(many=True, required=False, read_only=True) # slug_field='slug', many=True, read_only=True)
favourites = serializers.SlugRelatedField(slug_field='slug', many=True, read_only=True)
favourites = FavouriteSerializer(many=True, required=False, read_only=True) # slug_field='slug', many=True, read_only=True)
plays = InlineActivityPlaySerializer(many=True, read_only=True, source='activity_plays')
downloads = InlineActivityDownloadSerializer(read_only=True, source='activity_downloads')
is_liked = serializers.SerializerMethodField(read_only=True)
is_favourited = serializers.SerializerMethodField(read_only=True)
def update(self, instance, validated_data):
# all nested representations need to be serialized separately here
@@ -202,6 +215,25 @@ class MixSerializer(serializers.ModelSerializer):
except UserProfile.DoesNotExist:
pass
favourites = self.initial_data['favourites']
unfavourited = instance.favourites.exclude(user__userprofile__slug__in=[f['slug'] for f in favourites])
for uf in unfavourited:
# check that the user removing the like is an instance of the current user
# for now, only the current user can like stuff
if uf == self.context['request'].user.userprofile:
instance.update_favourite(uf, False)
for favourite in favourites:
# check that the user adding the like is an instance of the current user
# for now, only the current user can like stuff
try:
user = UserProfile.objects.get(slug=favourite['slug'])
if user is not None and user == self.context['request'].user.userprofile:
instance.update_favourite(user, True)
except UserProfile.DoesNotExist:
pass
genres = self.initial_data['genres']
instance.genres.clear()
for genre in genres:
@@ -224,6 +256,8 @@ class MixSerializer(serializers.ModelSerializer):
return super(MixSerializer, self).update(instance, validated_data)
except MixUpdateException as ex:
raise ex
except Exception as ex:
raise ex
def is_valid(self, raise_exception=False):
return super(MixSerializer, self).is_valid(raise_exception)

View File

@@ -123,13 +123,12 @@ INSTALLED_APPS = (
'allauth.socialaccount.providers.twitter',
'pipeline',
'dbbackup',
'gunicorn',
'corsheaders',
'sorl.thumbnail',
'djcelery',
'spa',
'gunicorn',
'spa.signals',
'core',
'storages',
@@ -254,7 +253,9 @@ SOCIAL_AUTH_AUTHENTICATION_BACKENDS = (
'social.backends.yahoo.YahooOpenId'
)
"""
DBBACKUP_STORAGE = 'dbbackup.storage.dropbox_storage'
DBBACKUP_TOKENS_FILEPATH = '._dss_tokens'
DBBACKUP_DROPBOX_APP_KEY = localsettings.DSS_DB_BACKUP_KEY
DBBACKUP_DROPBOX_APP_SECRET = localsettings.DSS_DB_BACKUP_SECRET
DBBACKUP_DROPBOX_APP_SECRET = localsettings.DSS_DB_BACKUP_SECRET
"""

View File

@@ -14,6 +14,7 @@ urlpatterns = patterns(
(r'^_embed/', include('spa.embedding.urls')),
(r'^__redir/blog/', include('spa.blog.urls')),
(r'^__redir/social/', include('spa.social.urls')),
(r'^podcast/', include('spa.podcast.urls')),
url(r'', include('user_sessions.urls', 'user_sessions')),
url(r'^', include('api.urls')),
)

View File

@@ -22,7 +22,6 @@ google-api-python-client
django-celery
django-scheduler
django-recurrence
# django-dbbackup
azure

View File

@@ -0,0 +1,16 @@
import uuid
from django.core.management.base import NoArgsCommand
from spa.models import UserProfile
class Command(NoArgsCommand):
def handle_noargs(self, **options):
try:
users = UserProfile.objects.exclude(uid__isnull=False)
for user in users:
user.uid = uuid.uuid4()
user.save()
except Exception as ex:
print("Debug exception: %s" % ex)

View File

@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('spa', '0025_socialaccountlink_provider_data'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='uid',
field=models.UUIDField(editable=False, null=True),
),
]

View File

@@ -238,7 +238,7 @@ class Mix(BaseModel):
if user.user.is_authenticated():
if value:
if self.favourites.filter(user=user.user).count() == 0:
fav = ActivityFavourite(user=user) # , mix=self)
fav = ActivityFavourite(user=user, mix=self)
fav.save()
self.favourites.add(user)
self.save()

View File

@@ -7,6 +7,7 @@ from django.contrib.auth.models import User
from django.core.exceptions import SuspiciousOperation
from django.db import models
from django.db.models import Count
import uuid
from django_gravatar.helpers import has_gravatar, get_gravatar_url
from sorl import thumbnail
@@ -41,6 +42,8 @@ class UserProfile(BaseModel):
ACTIVITY_SHARE_NETWORK_TWITTER = 2
user = models.OneToOneField(User, unique=True, related_name='userprofile')
uid = models.UUIDField(primary_key=False, editable=False, null=True)
avatar_type = models.CharField(max_length=15, default='social')
avatar_image = models.ImageField(max_length=1024, blank=True, upload_to=avatar_name)
display_name = models.CharField(blank=True, max_length=35)

6
spa/podcast/urls.py Normal file
View File

@@ -0,0 +1,6 @@
from django.conf.urls import patterns, url
urlpatterns = patterns(
'',
url(r'^(?P<uid>[\w\d_.-]+)/favourites/?$', 'spa.podcast.views.favourites', name='podast_favourites_slug'),
)

35
spa/podcast/views.py Normal file
View File

@@ -0,0 +1,35 @@
from django.http import Http404
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from spa.models import UserProfile
def favourites(request, uid):
try:
user = UserProfile.objects.order_by('-id').get(uid=uid)
except UserProfile.DoesNotExist:
raise Http404("User does not exist")
fav_list = user.favourites.all()
return _render_podcast(request, user, fav_list)
def _render_podcast(request, user, list):
context = {
'title': 'DSS Favourites',
'description': 'All your favourites on Deep South Sounds',
'link': 'https://deepsouthsounds.com/',
'user': user.first_name,
'summary': 'Deep South Sounds is a collective of like minded house heads from Ireland&quot;s Deep South',
'last_build_date': list[0].upload_date,
'objects': list,
}
response = render_to_response(
'podcast/feed.xml',
context=context,
context_instance=RequestContext(request),
content_type='application/rss+xml'
)
return response

View File

View File

@@ -0,0 +1,33 @@
from django import template
import datetime
import time
from email import utils
register = template.Library()
@register.filter
def get_mix_url(obj):
return obj.get_full_url()
@register.filter
def get_mix_audio_url(obj):
return obj.get_download_url()
@register.filter
def seconds_to_hms(seconds):
try:
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
return "%d:%02d:%02d" % (h, m, s)
except Exception as ex:
return "00:00:09"
@register.filter
def date_to_rfc2822(date):
nowtuple = date.timetuple()
nowtimestamp = time.mktime(nowtuple)
return utils.formatdate(nowtimestamp)

BIN
static/img/podcast_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<channel>
{% load dss_extras %}
<title>{{ title }}</title>
<description>{{ description }}</description>
<link>{{ link }}</link>
<language>en-ie</language>
<copyright>Copyright 2016</copyright>
<lastBuildDate>{{ last_build_date|date_to_rfc2822 }}</lastBuildDate>
<pubDate>{{ last_build_date|date_to_rfc2822 }}</pubDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<webMaster>webmaster@deepsouthsounds.com</webMaster>
<itunes:author>{{ user }} @ deepsouthsounds</itunes:author>
<itunes:subtitle>{{ title }}</itunes:subtitle>
<itunes:summary>{{ summary }}</itunes:summary>
<itunes:owner>
<itunes:name>Fergal Moran</itunes:name>
<itunes:email>fergal@deepsouthsounds.com</itunes:email>
</itunes:owner>
<itunes:explicit>No</itunes:explicit>
<itunes:image href="https://dsscdn2.blob.core.windows.net/static/podcast_logo.png"/>
<itunes:category text="Technology">
<itunes:category text="Podcasting"/>
</itunes:category>
{% for item in objects %}
<item>
<title>{{ item.title }}</title>
<link>{{ item|get_mix_url }}</link>
<guid>{{ item|get_mix_url }}</guid>
<description>{{ item.description }}</description>
<enclosure url="{{ item|get_mix_audio_url }}" length="{{ item.duration }}" type="audio/mpeg"/>
<category>Podcasts</category>
<pubDate>{{ item.upload_date|date_to_rfc2822 }}</pubDate>
<itunes:author>{{ item.user.display_name }}</itunes:author>
<itunes:explicit>No</itunes:explicit>
<itunes:subtitle>{{ item.description }}</itunes:subtitle>
<itunes:summary>{{ item.description }}</itunes:summary>
<itunes:duration>{{ item.duration|seconds_to_hms }}</itunes:duration>
<itunes:keywords>deep south sounds, deep house, Cork, Fergal Moran, Ed Dunlea, {{ item.title }}, {{ item.user.display_name }}
</itunes:keywords>
</item>
{% endfor %}
</channel>
</rss>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<channel>
<title>{{ object.title }}</title>
<link>{{ object.link }}</link>
<description>{{ object.description|striptags }}</description>
{% if object.language %}<language>{{ object.language }}</language>{% endif %}
<copyright>&#x2117; &amp; &#xA9; {% now "Y" %} {{ object.organization }}. {{ object.copyright }}.</copyright>
<managingEditor>{% for author in object.author.all %}{% if forloop.first %}{% else %}{% if forloop.last %} and {% else %}, {% endif %}{% endif %}{{ author.email }}{% endfor %}</managingEditor>
{% if object.author.email or object.webmaster.email %}<webMaster>{% if object.webmaster.email %}{{ object.webmaster.email }}{% else %}{% endif %}</webMaster>{% endif %}
<lastBuildDate>{{ object.list.0.date|date:"r" }}</lastBuildDate>
{% if object.category_show %}<category{% if object.domain %} domain="{{ object.domain }}"{% endif %}>{{ object.category_show }}</category>{% endif %}
<generator>Django Web Framework</generator>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
{% if object.ttl %}<ttl>{{ object.ttl }}</ttl>{% endif %}
{% if object.image %}<image>
<url>{{ object.image.url }}</url>
<title>{{ object.title }}</title>
<link>{{ object.link }}</link>
</image>{% endif %}
<itunes:author>{{ object.organization }}</itunes:author>
<itunes:owner>
<itunes:name>{% for author in object.author.all %}{% if forloop.first %}{% else %}{% if forloop.last %} and {% else %}, {% endif %}{% endif %}{% if author.first_name or author.last_name %}{% if author.first_name and author.last_name %}{{ author.first_name }} {{ author.last_name }}{% endif %}{% if author.first_name and not author.last_name %}{{ author.first_name }}{% endif %}{% if author.last_name and not author.first_name %}{{ author.last_name }}{% endif %}{% else %}{{ author.username }}{% endif %}{% endfor %}</itunes:name>
<itunes:email>{% for author in object.author.all %}{{ author.email }}{% if forloop.last %}{% else %}, {% endif %}{% endfor %}</itunes:email>
</itunes:owner>
{% if object.subtitle %}<itunes:subtitle>{{ object.subtitle }}</itunes:subtitle>{% endif %}
<itunes:summary>{% if object.summary %}{{ object.summary|striptags }}{% else %}{{ object.description|striptags }}{% endif %}</itunes:summary>
{% if object.image %}<itunes:image href="{{ object.image.url }}" />{% endif %}
{% if object.category.all %}{% for category in object.category.all %}{% if category.name %}<itunes:category text="{{ category.parent.name }}">
<itunes:category text="{{ category.name }}" />
</itunes:category>
{% else %}<itunes:category text="{{ category.parent.name }}" />
{% endif %}{% endfor %}{% endif %}
{% if object.explicit %}<itunes:explicit>{{ object.explicit|lower }}</itunes:explicit>{% endif %}
{% if object.block %}<itunes:block>yes</itunes:block>{% endif %}
{% if object.redirect %}<itunes:new-feed-url>{{ object.redirect }}</itunes:new-feed-url>{% endif %}
{% for episode in object.episode_set.published %}<item>
<title>{{ episode.title }}</title>
<link>{{ episode.enclosure_set.all.0.file.url }}</link>
<description>{{ episode.description|striptags }}</description>
<author>{% for author in object.author.all %}{{ author.email }}{% if forloop.last %}{% else %}, {% endif %}{% endfor %}</author>
{% if episode.category %}<category{% if episode.domain %} url="{{ episode.domain }}"{% endif %}>{{ episode.category }}</category>{% endif %}
<enclosure url="{{ episode.enclosure_set.all.0.file.url }}" length="{{ episode.enclosure_set.all.0.file.size }}" type="{{ episode.enclosure_set.all.0.mime }}" />
<guid isPermalink="true">{{ episode.enclosure_set.all.0.file.url }}</guid>
<pubDate>{{ episode.date|date:"r" }} GMT</pubDate>
<itunes:author>{% for author in episode.author.all %}{% if forloop.first %}{% else %}{% if forloop.last %} and {% else %}, {% endif %}{% endif %}{% if author.first_name or author.last_name %}{% if author.first_name and author.last_name %}{{ author.first_name }} {{ author.last_name }}{% endif %}{% if author.first_name and not author.last_name %}{{ author.first_name }}{% endif %}{% if author.last_name and not author.first_name %}{{ author.last_name }}{% endif %}{% else %}{{ author.username }}{% endif %}{% endfor %}</itunes:author>
{% if episode.subtitle %}<itunes:subtitle>{{ episode.subtitle }}</itunes:subtitle>{% endif %}
<itunes:summary>{% if episode.summary %}{{ episode.summary|striptags }}{% else %}{{ episode.description|striptags }}{% endif %}</itunes:summary>
{% if episode.minutes and episode.seconds %}<itunes:duration>{{ episode.minutes }}:{{ episode.seconds }}</itunes:duration>{% endif %}
{% if episode.keywords %}<itunes:keywords>{{ episode.keywords }}</itunes:keywords>{% endif %}
{% if episode.explicit %}<itunes:explicit>{{ episode.explicit|lower }}</itunes:explicit>{% endif %}
{% if episode.block %}<itunes:block>yes</itunes:block>{% endif %}
</item>
{% endfor %}
</channel>
</rss>