Added manga.publishers to frontend
This commit is contained in:
parent
4efc63ef47
commit
76eec051d3
|
@ -6,6 +6,7 @@ from .models import Publisher, Series, Volume
|
|||
|
||||
class PublisherAdmin(reversion.VersionAdmin):
|
||||
list_display = ['name', 'series_count']
|
||||
prepopulated_fields = {"slug": ("name",)}
|
||||
|
||||
def series_count(self, obj):
|
||||
return obj.series.count()
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'Publisher.slug'
|
||||
db.add_column(u'manga_publisher', 'slug',
|
||||
self.gf('django.db.models.fields.SlugField')(max_length=50, null=True, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'Publisher.slug'
|
||||
db.delete_column(u'manga_publisher', 'slug')
|
||||
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '75'})
|
||||
},
|
||||
u'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'filer.file': {
|
||||
'Meta': {'object_name': 'File'},
|
||||
'_file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'folder': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'all_files'", 'null': 'True', 'to': "orm['filer.Folder']"}),
|
||||
'has_all_mandatory_data': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
|
||||
'original_filename': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'owned_files'", 'null': 'True', 'to': u"orm['auth.User']"}),
|
||||
'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_filer.file_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}),
|
||||
'sha1': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}),
|
||||
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
'filer.folder': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('parent', 'name'),)", 'object_name': 'Folder'},
|
||||
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
|
||||
'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
|
||||
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'owner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'filer_owned_folders'", 'null': 'True', 'to': u"orm['auth.User']"}),
|
||||
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['filer.Folder']"}),
|
||||
'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
|
||||
'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
|
||||
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
'filer.image': {
|
||||
'Meta': {'object_name': 'Image', '_ormbases': ['filer.File']},
|
||||
'_height': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'_width': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'author': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'date_taken': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'default_alt_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'default_caption': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
u'file_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['filer.File']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'must_always_publish_author_credit': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'must_always_publish_copyright': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'subject_location': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '64', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'manga.publisher': {
|
||||
'Meta': {'ordering': "['name']", 'object_name': 'Publisher'},
|
||||
'for_review': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'for_review_comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'manga.series': {
|
||||
'Meta': {'ordering': "['name']", 'object_name': 'Series'},
|
||||
'cover': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Image']", 'null': 'True', 'blank': 'True'}),
|
||||
'finished': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'for_review': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'for_review_comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||
'summary': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
u'manga.userhavevolume': {
|
||||
'Meta': {'object_name': 'UserHaveVolume'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'have_volumes'", 'to': u"orm['auth.User']"}),
|
||||
'volume': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'owned_by'", 'to': u"orm['manga.Volume']"})
|
||||
},
|
||||
u'manga.userwishlistvolume': {
|
||||
'Meta': {'object_name': 'UserWishlistVolume'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wishlisted_volumes'", 'to': u"orm['auth.User']"}),
|
||||
'volume': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wishlisted_by'", 'to': u"orm['manga.Volume']"})
|
||||
},
|
||||
u'manga.volume': {
|
||||
'Meta': {'ordering': "['series__name', 'number']", 'object_name': 'Volume'},
|
||||
'cover': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['filer.Image']", 'null': 'True', 'blank': 'True'}),
|
||||
'for_review': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'for_review_comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
|
||||
'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True', 'blank': 'True'}),
|
||||
'number': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'publisher': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'volumes'", 'to': u"orm['manga.Publisher']"}),
|
||||
'series': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'volumes'", 'to': u"orm['manga.Series']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['manga']
|
|
@ -8,14 +8,28 @@ from shelfzilla.models import ReviewModel
|
|||
|
||||
class Publisher(ReviewModel):
|
||||
name = models.CharField(_('Name'), max_length=40)
|
||||
slug = models.SlugField(_('Slug'), blank=True, null=True)
|
||||
url = models.URLField(_('URL'), blank=True, null=True)
|
||||
|
||||
# Cache
|
||||
_series = None
|
||||
_volumes = None
|
||||
|
||||
def __unicode__(self):
|
||||
return u'{}'.format(self.name)
|
||||
|
||||
@property
|
||||
def series(self):
|
||||
return self.volumes.distinct('series')
|
||||
result = []
|
||||
if not self._series:
|
||||
queryset = self.volumes.order_by('series__id')\
|
||||
.distinct('series').values_list('series')
|
||||
|
||||
if queryset:
|
||||
result = Series.objects.filter(pk__in=queryset)
|
||||
|
||||
self._series = result
|
||||
return self._series
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
from django.conf.urls import patterns, url
|
||||
|
||||
from ..views.publishers import PublishersListView, PublishersDetailView
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', PublishersListView.as_view(), name='publishers.list'),
|
||||
url(
|
||||
r'^(?P<sid>\d+)/$',
|
||||
PublishersDetailView.as_view(),
|
||||
name='publishers.detail'),
|
||||
url(
|
||||
r'^(?P<sid>\d+)/(?P<slug>[\w-]+)/$',
|
||||
PublishersDetailView.as_view(),
|
||||
name='publishers.detail'),
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
from django.template import RequestContext
|
||||
from django.shortcuts import render_to_response, get_object_or_404
|
||||
|
||||
from shelfzilla.views import View
|
||||
from ..models import Publisher
|
||||
|
||||
|
||||
class PublishersView(View):
|
||||
section = 'publishers'
|
||||
|
||||
|
||||
class PublishersListView(PublishersView):
|
||||
template = 'manga/publishers/list.html'
|
||||
|
||||
def get(self, request):
|
||||
items = Publisher.objects.all()
|
||||
context = {
|
||||
'items': items
|
||||
}
|
||||
ctx = RequestContext(request, self.get_context(context))
|
||||
return render_to_response(self.template, context_instance=ctx)
|
||||
|
||||
|
||||
class PublishersDetailView(PublishersView):
|
||||
template = 'manga/publishers/detail.html'
|
||||
|
||||
def get(self, request, sid, slug=None):
|
||||
if slug:
|
||||
item = get_object_or_404(Publisher, pk=sid, slug=slug)
|
||||
else:
|
||||
item = get_object_or_404(Publisher, pk=sid)
|
||||
|
||||
context = {
|
||||
'item': item
|
||||
}
|
||||
|
||||
ctx = RequestContext(request, self.get_context(context))
|
||||
return render_to_response(self.template, context_instance=ctx)
|
|
@ -28,7 +28,7 @@
|
|||
<a data-pjax href="{% url "series.list" %}">{% trans "Series" %}</a>
|
||||
</li>
|
||||
<li {% if navigation.section == "publishers" %}class="active"{% endif %}>
|
||||
<a data-pjax href="#">{% trans "Publishers" %}</a>
|
||||
<a data-pjax href="{% url 'publishers.list' %}">{% trans "Publishers" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
{% extends extends_template %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{{ block.super }} | {{ item.name }}{% endblock %}
|
||||
|
||||
{% block main_content %}
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-primary">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Series" %}</strong>: {{ item.series.count }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Volumes" %}</strong>: {{ item.volumes.count }}
|
||||
</li>
|
||||
{% if item.url %}
|
||||
<li class="list-group-item text-center">
|
||||
<a href="{{ item.url }}"><i class="glyphicon glyphicon-home"></i> {% trans "Homepage" %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title panel-title-alt text-center">{{ item.name }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="series-list panel">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<th>{% trans "Name" %}</th>
|
||||
<th>{% trans "Volumes" %}</th>
|
||||
<th>{% trans "Finished" %}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for series in item.series %}
|
||||
<td>
|
||||
{% if series.slug %}
|
||||
<a href="{% url 'series.detail' series.pk series.slug %}">{{ series.name }}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'series.detail' series.pk %}">{{ series.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ series.volumes.count }}</td>
|
||||
<td>{{ series.finished|yesno|capfirst }}</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,38 @@
|
|||
{% extends extends_template %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_title %}{{ block.super }} | {% trans "Publishers" %}{% endblock %}
|
||||
|
||||
{% block main_content %}
|
||||
{% regroup items by first_letter as letter_list %}
|
||||
<div class="container">
|
||||
<div class="pull-right">
|
||||
<ul class="pagination">
|
||||
{% for letter in letter_list %}
|
||||
<li>
|
||||
<a href="#{{ letter.grouper }}">{{ letter.grouper }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
{% for letter in letter_list %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title" id="{{ letter.grouper }}">{{ letter.grouper }}</h3>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
{% for item in letter.list %}
|
||||
<li class="list-group-item">
|
||||
{% if item.slug %}
|
||||
<a href="{% url "publishers.detail" item.pk item.slug %}" data-pjax>{{ item.name }}</a>
|
||||
{% else %}
|
||||
<a href="{% url "publishers.detail" item.pk %}" data-pjax>{{ item.name }}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -13,6 +13,7 @@ urlpatterns = patterns(
|
|||
url(r'^', include('shelfzilla.apps.users.urls')),
|
||||
url(r'^series/', include('shelfzilla.apps.manga.urls.series')),
|
||||
url(r'^volumes/', include('shelfzilla.apps.manga.urls.volumes')),
|
||||
url(r'^publishers/', include('shelfzilla.apps.manga.urls.publishers')),
|
||||
url(r'^$', include('shelfzilla.apps.homepage.urls')),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
)
|
||||
|
|
Reference in New Issue