bunch of work; separate publications from programs, start to work on website

This commit is contained in:
bkfox 2015-09-23 17:27:01 +02:00
parent ef4c098d2e
commit 81a2e0533f
12 changed files with 518 additions and 178 deletions

View File

@ -32,72 +32,49 @@ class DiffusionInline (admin.TabularInline):
class TrackInline (SortableTabularInline): class TrackInline (SortableTabularInline):
fields = ['artist', 'title', 'tags', 'position'] fields = ['artist', 'name', 'tags', 'position']
form = TrackForm form = TrackForm
model = Track model = Track
sortable = 'position' sortable = 'position'
extra = 10 extra = 10
class MetadataAdmin (admin.ModelAdmin): class DescriptionAdmin (admin.ModelAdmin):
fieldsets = [ fields = [ 'name', 'tags', 'description' ]
( None, {
'fields': [ 'title', 'tags' ]
}),
( None, {
'fields': [ 'date', 'public' ],
}),
]
def save_model (self, request, obj, form, change): def tags (obj):
# FIXME: if request.data.author? return ', '.join(obj.tags.names())
if not obj.author:
obj.author = request.user
obj.save()
list_display = ['id', 'name', tags]
class PublicationAdmin (MetadataAdmin): list_filter = []
fieldsets = copy.deepcopy(MetadataAdmin.fieldsets) search_fields = ['name',]
list_display = ('id', 'title', 'date', 'public', 'parent')
list_filter = ['date', 'public', 'parent', 'author']
list_editable = ('public',)
search_fields = ['title', 'content']
fieldsets[0][1]['fields'].insert(1, 'subtitle')
fieldsets[0][1]['fields'] += [ 'img', 'content' ]
fieldsets[1][1]['fields'] += [ 'parent' ] #, 'meta' ],
@admin.register(Sound) @admin.register(Sound)
class SoundAdmin (MetadataAdmin): class SoundAdmin (DescriptionAdmin):
fields = None
fieldsets = [ fieldsets = [
(None, { 'fields': ['title', 'tags', 'path' ] } ), (None, { 'fields': DescriptionAdmin.fields + ['path' ] } ),
(None, { 'fields': ['duration', 'date', 'fragment' ] } ) (None, { 'fields': ['duration', 'date', 'fragment' ] } )
] ]
@admin.register(Stream) @admin.register(Stream)
class StreamAdmin (SortableModelAdmin): class StreamAdmin (SortableModelAdmin):
list_display = ('id', 'title', 'type', 'public', 'priority') list_display = ('id', 'name', 'type', 'priority')
list_editable = ('public',)
sortable = "priority" sortable = "priority"
@admin.register(Program) @admin.register(Program)
class ProgramAdmin (PublicationAdmin): class ProgramAdmin (DescriptionAdmin):
fieldsets = copy.deepcopy(PublicationAdmin.fieldsets) fields = DescriptionAdmin.fields + ['stream']
inlines = [ ScheduleInline ] inlines = [ ScheduleInline ]
fieldsets[1][1]['fields'] += ['email', 'url']
@admin.register(Episode) @admin.register(Episode)
class EpisodeAdmin (PublicationAdmin): class EpisodeAdmin (DescriptionAdmin):
fieldsets = copy.deepcopy(PublicationAdmin.fieldsets) list_filter = ['program'] + DescriptionAdmin.list_filter
list_filter = ['parent'] + PublicationAdmin.list_filter fields = DescriptionAdmin.fields + ['sounds']
fieldsets[0][1]['fields'] += ['sounds']
inlines = (TrackInline, DiffusionInline) inlines = (TrackInline, DiffusionInline)

View File

@ -33,12 +33,12 @@ class TrackArtistAutocomplete(OneFieldAutocomplete):
al.register(TrackArtistAutocomplete) al.register(TrackArtistAutocomplete)
class TrackTitleAutocomplete(OneFieldAutocomplete): class TrackNameAutocomplete(OneFieldAutocomplete):
search_fields = ['title'] search_fields = ['name']
model = Track model = Track
al.register(TrackTitleAutocomplete) al.register(TrackNameAutocomplete)
#class DiffusionAutocomplete(OneFieldAutocomplete): #class DiffusionAutocomplete(OneFieldAutocomplete):

View File

@ -10,10 +10,10 @@ from programs.models import *
class TrackForm (forms.ModelForm): class TrackForm (forms.ModelForm):
class Meta: class Meta:
model = Track model = Track
fields = ['artist', 'title', 'tags', 'position'] fields = ['artist', 'name', 'tags', 'position']
widgets = { widgets = {
'artist': al.TextWidget('TrackArtistAutocomplete'), 'artist': al.TextWidget('TrackArtistAutocomplete'),
'title': al.TextWidget('TrackTitleAutocomplete'), 'name': al.TextWidget('TrackNameAutocomplete'),
'tags': TaggitWidget('TagAutocomplete'), 'tags': TaggitWidget('TagAutocomplete'),
} }

View File

@ -24,7 +24,7 @@ class Actions:
@staticmethod @staticmethod
def update (date): def update (date):
items = [] items = []
for schedule in Schedule.objects.filter(parent__active = True): for schedule in Schedule.objects.filter(program__active = True):
items += schedule.diffusions_of_month(date, exclude_saved = True) items += schedule.diffusions_of_month(date, exclude_saved = True)
print('> {} new diffusions for schedule #{} ({})'.format( print('> {} new diffusions for schedule #{} ({})'.format(
len(items), schedule.id, str(schedule) len(items), schedule.id, str(schedule)
@ -47,7 +47,7 @@ class Actions:
date__gt = date) date__gt = date)
items = [] items = []
for diffusion in qs: for diffusion in qs:
schedules = Schedule.objects.filter(parent = diffusion.program) schedules = Schedule.objects.filter(program = diffusion.program)
for schedule in schedules: for schedule in schedules:
if schedule.match(diffusion.date): if schedule.match(diffusion.date):
break break

View File

@ -1,10 +1,7 @@
import os import os
from django.db import models from django.db import models
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
from django.utils import timezone as tz from django.utils import timezone as tz
from django.utils.html import strip_tags from django.utils.html import strip_tags
@ -27,27 +24,15 @@ def date_or_default (date, date_only = False):
return date return date
class Metadata (models.Model): class Description (models.Model):
""" name = models.CharField (
meta is used to extend a model for future needs _('name'),
"""
author = models.ForeignKey (
User,
verbose_name = _('author'),
blank = True, null = True,
)
title = models.CharField(
_('title'),
max_length = 128, max_length = 128,
) )
date = models.DateTimeField( description = models.TextField (
_('date'), _('description'),
default = tz.datetime.now, max_length = 1024,
) blank = True, null = True
public = models.BooleanField(
_('public'),
default = True,
help_text = _('publication is public'),
) )
tags = TaggableManager( tags = TaggableManager(
_('tags'), _('tags'),
@ -55,68 +40,18 @@ class Metadata (models.Model):
) )
def get_slug_name (self): def get_slug_name (self):
return slugify(self.title) return slugify(self.name)
class Meta:
abstract = True
class Publication (Metadata):
subtitle = models.CharField(
_('subtitle'),
max_length = 128,
blank = True,
)
img = models.ImageField(
_('image'),
upload_to = "images",
blank = True,
)
content = models.TextField(
_('content'),
blank = True,
)
commentable = models.BooleanField(
_('enable comments'),
default = True,
help_text = _('comments are enabled on this publication'),
)
@staticmethod
def _exclude_args (allow_unpublished = False, prefix = ''):
if allow_unpublished:
return {}
res = {}
res[prefix + 'public'] = False
res[prefix + 'date__gt'] = tz.now()
return res
@classmethod
def get_available (cl, first = False, **kwargs):
"""
Return the result of filter(kargs) if the resulting publications
is published and public
Otherwise, return None
"""
kwargs['public'] = True
kwargs['date__lte'] = tz.now()
e = cl.objects.filter(**kwargs)
if first:
return (e and e[0]) or None
return e or None
def __str__ (self): def __str__ (self):
return self.title + ' (' + str(self.id) + ')' if self.pk:
return '#{} {}'.format(self.pk, self.name)
return '{}'.format(self.name)
class Meta: class Meta:
abstract = True abstract = True
class Track (models.Model): class Track (Description):
# There are no nice solution for M2M relations ship (even without # There are no nice solution for M2M relations ship (even without
# through) in django-admin. So we unfortunately need to make one- # through) in django-admin. So we unfortunately need to make one-
# to-one relations and add a position argument # to-one relations and add a position argument
@ -127,13 +62,8 @@ class Track (models.Model):
_('artist'), _('artist'),
max_length = 128, max_length = 128,
) )
title = models.CharField( # position can be used to specify a position in seconds for non-
_('title'), # stop programs or a position in the playlist
max_length = 128,
)
tags = TaggableManager( blank = True )
# position can be used to specify a position in seconds for non-stop
# programs or a position in the playlist
position = models.SmallIntegerField( position = models.SmallIntegerField(
default = 0, default = 0,
help_text=_('position in the playlist'), help_text=_('position in the playlist'),
@ -147,7 +77,7 @@ class Track (models.Model):
verbose_name_plural = _('Tracks') verbose_name_plural = _('Tracks')
class Sound (Metadata): class Sound (Description):
""" """
A Sound is the representation of a sound, that can be: A Sound is the representation of a sound, that can be:
- An episode podcast/complete record - An episode podcast/complete record
@ -158,7 +88,7 @@ class Sound (Metadata):
public, then we can podcast it. If a Sound is a fragment, then it is not public, then we can podcast it. If a Sound is a fragment, then it is not
usable for diffusion. usable for diffusion.
Each sound file can be associated to a filesystem's file or an embedded Each sound can be associated to a filesystem's file or an embedded
code (for external podcasts). code (for external podcasts).
""" """
path = models.FilePathField( path = models.FilePathField(
@ -177,10 +107,15 @@ class Sound (Metadata):
_('duration'), _('duration'),
blank = True, null = True, blank = True, null = True,
) )
public = models.BooleanField(
_('public'),
default = False,
help_text = _("the element is public"),
)
fragment = models.BooleanField( fragment = models.BooleanField(
_('incomplete sound'), _('incomplete sound'),
default = False, default = False,
help_text = _("the file has been cut"), help_text = _("the file is a cut"),
) )
removed = models.BooleanField( removed = models.BooleanField(
default = False, default = False,
@ -198,6 +133,7 @@ class Sound (Metadata):
def save (self, *args, **kwargs): def save (self, *args, **kwargs):
if not self.pk: if not self.pk:
self.date = self.get_mtime() self.date = self.get_mtime()
super(Sound, self).save(*args, **kwargs) super(Sound, self).save(*args, **kwargs)
def __str__ (self): def __str__ (self):
@ -228,7 +164,7 @@ class Schedule (models.Model):
for key, value in Frequency.items(): for key, value in Frequency.items():
ugettext_lazy(key) ugettext_lazy(key)
parent = models.ForeignKey( program = models.ForeignKey(
'Program', 'Program',
blank = True, null = True, blank = True, null = True,
) )
@ -243,7 +179,7 @@ class Schedule (models.Model):
rerun = models.ForeignKey( rerun = models.ForeignKey(
'self', 'self',
blank = True, null = True, blank = True, null = True,
help_text = "Schedule of a rerun", help_text = "Schedule of a rerun of this one",
) )
def match (self, date = None, check_time = True): def match (self, date = None, check_time = True):
@ -373,7 +309,7 @@ class Diffusion (models.Model):
'default': 0x00, # simple diffusion (done/planed) 'default': 0x00, # simple diffusion (done/planed)
'unconfirmed': 0x01, # scheduled by the generator but not confirmed for diffusion 'unconfirmed': 0x01, # scheduled by the generator but not confirmed for diffusion
'cancel': 0x02, # cancellation happened; used to inform users 'cancel': 0x02, # cancellation happened; used to inform users
'restart': 0x03, # manual restart; used to remix/give up antenna # 'restart': 0x03, # manual restart; used to remix/give up antenna
'stop': 0x04, # diffusion has been forced to stop 'stop': 0x04, # diffusion has been forced to stop
} }
for key, value in Type.items(): for key, value in Type.items():
@ -424,12 +360,17 @@ class Stream (models.Model):
for key, value in Type.items(): for key, value in Type.items():
ugettext_lazy(key) ugettext_lazy(key)
title = models.CharField( name = models.CharField(
_('title'), _('name'),
max_length = 32, max_length = 32,
blank = True, blank = True,
null = True, null = True,
) )
public = models.BooleanField(
_('public'),
default = True,
help_text = _('program list is public'),
)
type = models.SmallIntegerField( type = models.SmallIntegerField(
verbose_name = _('type'), verbose_name = _('type'),
choices = [ (y, x) for x,y in Type.items() ], choices = [ (y, x) for x,y in Type.items() ],
@ -439,11 +380,6 @@ class Stream (models.Model):
default = 0, default = 0,
help_text = _('priority of the stream') help_text = _('priority of the stream')
) )
public = models.BooleanField(
_('public'),
default = True,
help_text = _('program list is public'),
)
# get info for: # get info for:
# - random lists # - random lists
@ -453,23 +389,14 @@ class Stream (models.Model):
# - stream/pgm # - stream/pgm
def __str__ (self): def __str__ (self):
return '#{} {}'.format(self.priority, self.title) return '#{} {}'.format(self.priority, self.name)
class Program (Publication): class Program (Description):
parent = models.ForeignKey( stream = models.ForeignKey(
Stream, Stream,
verbose_name = _('stream'), verbose_name = _('stream'),
) )
email = models.EmailField(
_('email'),
max_length = 128,
null = True, blank = True,
)
url = models.URLField(
_('website'),
blank = True, null = True,
)
active = models.BooleanField( active = models.BooleanField(
_('inactive'), _('inactive'),
default = True, default = True,
@ -491,8 +418,8 @@ class Program (Publication):
return schedule return schedule
class Episode (Publication): class Episode (Description):
parent = models.ForeignKey( program = models.ForeignKey(
Program, Program,
verbose_name = _('parent'), verbose_name = _('parent'),
help_text = _('parent program'), help_text = _('parent program'),

View File

@ -1,15 +1,42 @@
import copy import copy
from django.contrib import admin from django.contrib import admin
from django.utils.translation import ugettext as _, ugettext_lazy
from django.contrib.contenttypes.admin import GenericStackedInline
from programs.admin import PublicationAdmin import programs.models as programs
from website.models import * from website.models import *
@admin.register(Article)
class ArticleAdmin (PublicationAdmin):
fieldsets = copy.deepcopy(PublicationAdmin.fieldsets)
fieldsets[1][1]['fields'] += ['static_page'] def add_inline (base_model, post_model, prepend = False):
class InlineModel (GenericStackedInline):
model = post_model
extra = 1
max_num = 1
ct_field = 'object_type'
verbose_name = _('Post')
registry = admin.site._registry
if not base_model in registry:
raise TypeError(str(base_model) + " not in admin registry")
inlines = list(registry[base_model].inlines) or []
if prepend:
inlines.insert(0, InlineModel)
else:
inlines.append(InlineModel)
registry[base_model].inlines = inlines
add_inline(Program, ObjectDescription)
add_inline(Episode, ObjectDescription)
#class ArticleAdmin (DescriptionAdmin):
# fieldsets = copy.deepcopy(DescriptionAdmin.fieldsets)
#
# fieldsets[1][1]['fields'] += ['static_page']

View File

@ -1,15 +1,120 @@
from django.db import models from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
from django.utils import timezone
from programs.models import Publication from django.db.models.signals import post_save
from django.dispatch import receiver
from programs.models import *
class Article (Publication): class Thread (models.Model):
parent = models.ForeignKey( post_type = models.ForeignKey(ContentType)
'self', post_id = models.PositiveIntegerField()
verbose_name = _('parent'), post = GenericForeignKey('post_type', 'post_id')
@classmethod
def get (cl, model, **kwargs):
post_type = ContentType.objects.get_for_model(model)
return cl.objects.get(post_type__pk = post_type.id,
**kwargs)
@classmethod
def filter (cl, model, **kwargs):
post_type = ContentType.objects.get_for_model(model)
return cl.objects.filter(post_type__pk = post_type.id,
**kwargs)
@classmethod
def exclude (cl, model, **kwargs):
post_type = ContentType.objects.get_for_model(model)
return cl.objects.exclude(post_type__pk = post_type.id,
**kwargs)
def __str__ (self):
return str(self.post)
class Post (models.Model):
thread = models.ForeignKey(
Thread,
on_delete=models.SET_NULL,
blank = True, null = True, blank = True, null = True,
help_text = _('parent article'), help_text = _('the publication is posted on this thread'),
)
author = models.ForeignKey(
User,
verbose_name = _('author'),
blank = True, null = True,
)
date = models.DateTimeField(
_('date'),
default = timezone.datetime.now
)
public = models.BooleanField(
verbose_name = _('public'),
default = True
)
image = models.ImageField(
blank = True, null = True
)
def as_dict (self):
d = {}
d.update(self.__dict__)
d.update({
'title': self.get_title(),
'image': self.get_image(),
'date': self.get_date(),
'content': self.get_content()
})
def get_detail_url (self):
pass
def get_image (self):
return self.image
def get_date (self):
return self.date
def get_title (self):
pass
def get_content (self):
pass
class Meta:
abstract = True
@receiver(post_save)
def on_new_post (sender, instance, created, *args, **kwargs):
"""
Signal handler to create a thread that is attached to the newly post
"""
if not issubclass(sender, Post) or not created:
return
thread = Thread(post = instance)
thread.save()
class ObjectDescription (Post):
object_type = models.ForeignKey(ContentType, blank = True, null = True)
object_id = models.PositiveIntegerField(blank = True, null = True)
object = GenericForeignKey('object_type', 'object_id')
class Article (Post):
title = models.CharField(
_('title'),
max_length = 128,
) )
static_page = models.BooleanField( static_page = models.BooleanField(
_('static page'), _('static page'),
@ -19,17 +124,25 @@ class Article (Publication):
_('article is focus'), _('article is focus'),
default = False, default = False,
) )
referring_tag = models.CharField(
_('referring tag'),
max_length = 32,
blank = True, null = True,
help_text = _('tag used by other to refers to this article'),
)
class Meta: class Meta:
verbose_name = _('Article') verbose_name = _('Article')
verbose_name_plural = _('Articles') verbose_name_plural = _('Articles')
#class MenuItem ():
# Menu = {
# 'top': 0x00,
# 'sidebar': 0x01,
# 'bottom': 0x02,
# }
# for key, value in Type.items():
# ugettext_lazy(key)
#
# parent = models.ForeignKey(
# 'self',
# blank = True, null = True
# )
# menu = models.SmallIntegerField(
# )

139
website/routes.py Normal file
View File

@ -0,0 +1,139 @@
from django.conf.urls import url
from django.utils import timezone
from website.models import *
class Routes:
registry = []
def register (self, route):
if not route in self.registry:
self.registry.append(route)
def unregister (self, route):
self.registry.remove(route)
def get_urlpatterns (self):
patterns = []
for route in self.registry:
patterns += route.get_urlpatterns() or []
return patterns
class Route:
"""
Base class for routing. Given a model, we generate url specific for each
route type. The generated url takes this form:
base_name + '/' + route_name + '/' + '/'.join(route_url_args)
Where base_name by default is the given model's verbose_name (uses plural if
Route is for a list).
The given view is considered as a django class view, and has view_
"""
model = None # model routed here
view = None # view class to call
view_kwargs = None # arguments passed to view at creation of the urls
class Meta:
name = None # route name
is_list = False # route is for a list
url_args = [] # arguments passed from the url [ (name : regex),... ]
def __init__ (self, model, view, view_kwargs = None,
base_name = None):
self.model = model
self.view = view
self.view_kwargs = view_kwargs
self.embed = False
_meta = {}
_meta.update(Route.Meta.__dict__)
_meta.update(self.Meta.__dict__)
self._meta = _meta
if not base_name:
base_name = model._meta.verbose_name_plural if _meta['is_list'] \
else model._meta.verbose_name
base_name = base_name.title().lower()
self.base_name = base_name
def get_queryset (self, request, **kwargs):
"""
Called by the view to get the queryset when it is needed
"""
def get_urlpatterns (self):
view_kwargs = self.view_kwargs or {}
pattern = '^{}/{}'.format(self.base_name, self.Meta.name)
if self.view.Meta.formats:
pattern += '(/(?P<format>{}))?'.format('|'.join(self.view.Meta.formats))
if self._meta['url_args']:
url_args = '/'.join([ '(?P<{}>{})'.format(arg, expr) \
for arg, expr in self._meta['url_args']
])
pattern += '/' + url_args
pattern += '/?$'
return [ url(
pattern,
self.view and self.view.as_view(
route = self,
model = self.model,
**view_kwargs
),
name = '{}'
) ]
class SearchRoute (Route):
class Meta:
name = 'search'
is_list = True
def get_queryset (self, request, **kwargs):
q = request.GET.get('q') or ''
qs = self.model.objects
for search_field in model.search_fields or []:
r = self.model.objects.filter(**{ search_field + '__icontains': q })
if qs: qs = qs | r
else: qs = r
qs.distinct()
return qs
class ThreadRoute (Route):
class Meta:
name = 'thread'
is_list = True
url_args = [
('pk', '[0-9]+')
]
def get_queryset (self, request, **kwargs):
return self.model.objects.filter(thread__id = int(kwargs['pk']))
class DateRoute (Route):
class Meta:
name = 'date'
is_list = True
url_args = [
('year', '[0-9]{4}'),
('month', '[0-9]{2}'),
('day', '[0-9]{1,2}'),
]
def get_queryset (self, request, **kwargs):
return self.model.objects.filter(
date__year = int(kwargs['year']),
date__month = int(kwargs['month']),
date__day = int(kwargs['day']),
)

View File

@ -0,0 +1,59 @@
{# Parameters are: #}
{# * pub: publication itself; pub.meta must have been eval() #}
{# * threads: list of parent, from top to bottom, including itself #}
{# #}
{# * views: a view object used to know which view to use for links #}
{# #}
{# {% extends embed|yesno:"website/single.html,website/base.html" %} #}
{% load i18n %}
{% load thumbnail %}
{# {% load website_views %} #}
<div class="post_list {{ classes }}">
{% for post in object_list %}
<a class="post_item"
href="post.get_detail_url">
{% if 'date' in list.fields or 'time' in list.fields %}
{% with post_date=post.get_date %}
<time datetime="{{ post_date }}" class="post_datetime">
{% if 'date' in list.fields %}
<span class="post_date">
{{ post_date|date:'D. d F' }},
</span>
{% endif %}
{% if 'time' in list.fields %}
<span class="post_time">
{{ post_date|date:'H:i' }},
</span>
{% endif %}
</time>
{% endwith %}
{% endif %}
{% if 'image' in list.fields %}
{% with post_image=post.get_image %}
<img src="{% thumbnail post_image "64x64" crop %}" class="post_image">
{% endwith %}
{% endif %}
{% if 'title' in list.fields %}
{% with post_title=post.get_title %}
<h4 class="post_title">post_title</h4>
{% endwith %}
{% endif %}
{% if 'content' in list.fields %}
{% with post_content=post.get_content %}
<div class="post_content">
{{ post_content|safe|striptags|truncatechars:"64" }}
</div>
{% endwith %}
{% endif %}
</a>
{% endfor %}
</div>

24
website/urls.py Normal file
View File

@ -0,0 +1,24 @@
from django.conf.urls import url, include
from website.models import *
from website.views import *
from website.routes import *
routes = Routes()
routes.register( SearchRoute(Article, PostListView) )
#routes.register( SearchRoute(ProgramPost, PostListView, base_name = 'programs') )
#routes.register( SearchRoute(EpisodePost, PostListView, base_name = 'episodes') )
routes.register( ThreadRoute(Article, PostListView) )
#routes.register( ThreadRoute(ProgramPost, PostListView, base_name = 'programs') )
#routes.register( ThreadRoute(EpisodePost, PostListView, base_name = 'episodes') )
routes.register( DateRoute(Article, PostListView) )
#routes.register( DateRoute(ProgramPost, PostListView, base_name = 'programs') )
#routes.register( DateRoute(EpisodePost, PostListView, base_name = 'episodes') )
urlpatterns = routes.get_urlpatterns()

View File

@ -36,7 +36,7 @@ class ListQueries:
if not q: if not q:
q = timezone.datetime.today() q = timezone.datetime.today()
if type(q) is str: if type(q) is str:
q = timezone.datetime.strptime(q, '%Y/%m/%d').date() q = timezone.datetime.strptime(q, '%Y%m%d').date()
return qs.filter(date__startswith = q) return qs.filter(date__startswith = q)

View File

@ -1,3 +1,77 @@
from django.shortcuts import render from django.shortcuts import render
from django.utils import timezone
from django.views.generic import ListView
from django.views.generic import DetailView
from django.core import serializers
from django.utils.translation import ugettext as _, ugettext_lazy
from website.models import *
class PostListView (ListView):
class Query:
"""
Request availables parameters
"""
exclude = None
order = 'desc'
reverse = False
format = 'normal'
def __init__ (self, query):
my_class = self.__class__
if type(query) is my_class:
self.__dict__.update(query.__dict__)
return
if type(query) is not dict:
query = query.__dict__
self.__dict__ = { k: v for k,v in query.items() }
template_name = 'website/list.html'
allow_empty = True
query = None
format = None
fields = [ 'date', 'time', 'image', 'title', 'content' ]
route = None
model = None
class Meta:
# FIXME
formats = ['normal', 'embed', 'json', 'yaml', 'xml']
def __init__ (self, *args, **kwargs):
super(PostListView, self).__init__(*args, **kwargs)
if self.query:
self.query = Query(self.query)
def get_queryset (self):
qs = self.route.get_queryset(self.request, **self.kwargs)
qs = qs.filter(public = True)
query = self.query or PostListView.Query(self.request.GET)
if query.exclude:
qs = qs.exclude(id = int(exclude))
if query.order == 'asc':
qs.order_by('date', 'id')
else:
qs.order_by('-date', '-id')
return qs
def get_context_data (self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs)
context.update({
'list': self
})
return context
# Create your views here.