From fad441d3acfc421d366bee964dfc923650c1bfd4 Mon Sep 17 00:00:00 2001 From: Gena Date: Sun, 14 Jun 2015 21:03:06 +0600 Subject: [PATCH] no message --- batiskaf/settings.py | 1 + batiskaf/templates/jinja2/base.jinja | 4 +- batiskaf/templates/jinja2/news/detail.jinja | 113 ++++++++++++++++++++ batiskaf/templates/jinja2/news/list.jinja | 55 ++++++++++ batiskaf/urls.py | 1 + news/__init__.py | 0 news/admin.py | 22 ++++ news/forms.py | 9 ++ news/migrations/0001_initial.py | 64 +++++++++++ news/migrations/0002_auto_20150614_1756.py | 24 +++++ news/migrations/0003_auto_20150614_2025.py | 24 +++++ news/migrations/__init__.py | 0 news/models.py | 58 ++++++++++ news/tests.py | 3 + news/urls.py | 9 ++ news/views.py | 48 +++++++++ static/less/_.css | 7 ++ static/less/_.less | 9 ++ store/admin.py | 2 +- store/migrations/0017_auto_20150614_1746.py | 27 +++++ store/models.py | 12 +++ 21 files changed, 488 insertions(+), 4 deletions(-) create mode 100644 batiskaf/templates/jinja2/news/detail.jinja create mode 100644 batiskaf/templates/jinja2/news/list.jinja create mode 100644 news/__init__.py create mode 100644 news/admin.py create mode 100644 news/forms.py create mode 100644 news/migrations/0001_initial.py create mode 100644 news/migrations/0002_auto_20150614_1756.py create mode 100644 news/migrations/0003_auto_20150614_2025.py create mode 100644 news/migrations/__init__.py create mode 100644 news/models.py create mode 100644 news/tests.py create mode 100644 news/urls.py create mode 100644 news/views.py create mode 100644 store/migrations/0017_auto_20150614_1746.py diff --git a/batiskaf/settings.py b/batiskaf/settings.py index d80712c..ebb09c4 100644 --- a/batiskaf/settings.py +++ b/batiskaf/settings.py @@ -62,6 +62,7 @@ INSTALLED_APPS = ( 'main', 'accounts', 'store', + 'news', ) MIDDLEWARE_CLASSES = ( diff --git a/batiskaf/templates/jinja2/base.jinja b/batiskaf/templates/jinja2/base.jinja index 3176ba0..1a83a73 100644 --- a/batiskaf/templates/jinja2/base.jinja +++ b/batiskaf/templates/jinja2/base.jinja @@ -343,9 +343,7 @@

- Карта сайта  |  Поисковые запросы  |  Расширенный - Поиск  |  Контакты  |  RSS  |  Privacy Policy + Карта сайта  |  Поисковые запросы  |  Поиск  |  Контакты  |  RSS


diff --git a/batiskaf/templates/jinja2/news/detail.jinja b/batiskaf/templates/jinja2/news/detail.jinja new file mode 100644 index 0000000..e880184 --- /dev/null +++ b/batiskaf/templates/jinja2/news/detail.jinja @@ -0,0 +1,113 @@ +{% extends 'base.jinja' %} +{% block content %} +

+ {{ object.title }} +


+
+ +

+ + {{ object.created.strftime('%d.%m.%Y') }} +      Комментарии ({{ object.comments.count() }}) + +

+ +

+ {% set im = object.image %} + +

+ {{ object.text|linebreaks|safe }} + +
+
+ + +
+
+ Поделиться ссылкой:
+ + +
+ +
+
+
+
+ + +

+ Комментарии:

+ + + {% if object.comments.all() %} + +
    + + + {% for comment in object.comments.all() %} + +
  • + +
    +

    {{ comment.name }} пишет: #

    +

    {{ comment.created.strftime('%d.%m.%Y %H:%M') }}

    +

    {{ comment.text|striptags }}

    + + +
    +
  • + + {% endfor %} +
+ {% else %} +
+ Пока нет ни одного комментария! Вы можете стать первым! +
+ {% endif %} + +
+
+ +

+ Оставить комментарий:

+ +
+
+ {{ form|bootstrap }} +
+ +
+
+
+
+ + +
+ +{% endblock %} + diff --git a/batiskaf/templates/jinja2/news/list.jinja b/batiskaf/templates/jinja2/news/list.jinja new file mode 100644 index 0000000..a702949 --- /dev/null +++ b/batiskaf/templates/jinja2/news/list.jinja @@ -0,0 +1,55 @@ +{% extends 'base.jinja' %} +{% block content %} + + + {% if tag %} +

Новости с тегом "{{ tag.title }}" +


{% endif %} + {% for object in object_list %} +
+

+ {{ object.title }} +

+ +

+ + {{ object.created.strftime('%d.%m.%Y') }} +      Комментировать + +

+

+ {% set im = object.image|thumbnail("400x400") %} + +

+ {{ object.text|truncate(520)|linebreaks|safe }} +

Продолжить читать → +

+
+ +
+ {% endfor %} + +{% endblock %} + diff --git a/batiskaf/urls.py b/batiskaf/urls.py index b1cddeb..bf9c759 100644 --- a/batiskaf/urls.py +++ b/batiskaf/urls.py @@ -11,6 +11,7 @@ urlpatterns = patterns( '', url(r'^$', 'main.views.index', name='index'), + url(r'^news/', include('news.urls')), url(r'^get_order_amount/$', 'store.views.get_order_amount'), url(r'^order/(?P.+)/print/$', order_print, name='store_order_print'), diff --git a/news/__init__.py b/news/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/news/admin.py b/news/admin.py new file mode 100644 index 0000000..664cf1b --- /dev/null +++ b/news/admin.py @@ -0,0 +1,22 @@ +from django.contrib import admin +from .models import * + + +@admin.register(News) +class NewsAdmin(admin.ModelAdmin): + list_display = ('title', 'is_public') + prepopulated_fields = {"slug": ("title",)} + list_editable = ('is_public',) + list_filter = ('is_public',) + + +@admin.register(NewsTag) +class TagsAdmin(admin.ModelAdmin): + list_display = ('title',) + prepopulated_fields = {"slug": ("title",)} + + +@admin.register(NewsComment) +class CommentsAdmin(admin.ModelAdmin): + list_display = ('name', 'email', 'text', 'news') + diff --git a/news/forms.py b/news/forms.py new file mode 100644 index 0000000..bcad284 --- /dev/null +++ b/news/forms.py @@ -0,0 +1,9 @@ +from django import forms +from .models import * + +class CommentForm(forms.ModelForm): + reply_to = forms.IntegerField(widget=forms.HiddenInput(), required=False) + + class Meta: + model = NewsComment + fields = ['name', 'email', 'text', 'reply_to'] diff --git a/news/migrations/0001_initial.py b/news/migrations/0001_initial.py new file mode 100644 index 0000000..1135ff7 --- /dev/null +++ b/news/migrations/0001_initial.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import news.models + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='News', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)), + ('created', models.DateTimeField(verbose_name='Дата и время', auto_now_add=True)), + ('title', models.CharField(verbose_name='Заголовок', max_length=512, unique=True)), + ('slug', models.SlugField(verbose_name='Ссылка', max_length=512, unique=True)), + ('text', models.TextField(verbose_name='Новость')), + ('is_public', models.BooleanField(verbose_name='Публиковать', default=True)), + ('image', models.ImageField(verbose_name='Картинка', upload_to=news.models.photo_filename)), + ], + options={ + 'verbose_name': 'новость', + 'verbose_name_plural': 'новости', + }, + ), + migrations.CreateModel( + name='NewsComment', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)), + ('created', models.DateTimeField(verbose_name='Дата и время', auto_now_add=True)), + ('name', models.CharField(verbose_name='Имя', max_length=45)), + ('email', models.EmailField(verbose_name='Email', max_length=254)), + ('text', models.TextField(verbose_name='Комментарий')), + ('news', models.ForeignKey(related_name='comments', to='news.News')), + ('reply_to', models.ForeignKey(to='news.NewsComment')), + ], + options={ + 'verbose_name': 'комментарий', + 'verbose_name_plural': 'комментарии', + }, + ), + migrations.CreateModel( + name='NewsTag', + fields=[ + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)), + ('title', models.CharField(verbose_name='Заголовок', max_length=512, unique=True)), + ('slug', models.SlugField(verbose_name='Ссылка', max_length=512, unique=True)), + ('news_list', models.ManyToManyField(to='news.News')), + ], + options={ + 'verbose_name': 'тег', + 'verbose_name_plural': 'теги', + }, + ), + migrations.AddField( + model_name='news', + name='tags_list', + field=models.ManyToManyField(to='news.NewsTag'), + ), + ] diff --git a/news/migrations/0002_auto_20150614_1756.py b/news/migrations/0002_auto_20150614_1756.py new file mode 100644 index 0000000..32ce1dc --- /dev/null +++ b/news/migrations/0002_auto_20150614_1756.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='news', + name='tags_list', + field=models.ManyToManyField(null=True, blank=True, to='news.NewsTag'), + ), + migrations.AlterField( + model_name='newstag', + name='news_list', + field=models.ManyToManyField(null=True, blank=True, to='news.News'), + ), + ] diff --git a/news/migrations/0003_auto_20150614_2025.py b/news/migrations/0003_auto_20150614_2025.py new file mode 100644 index 0000000..fe10b11 --- /dev/null +++ b/news/migrations/0003_auto_20150614_2025.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0002_auto_20150614_1756'), + ] + + operations = [ + migrations.AlterField( + model_name='newscomment', + name='email', + field=models.EmailField(verbose_name='Email (не будет опубликован)', max_length=254), + ), + migrations.AlterField( + model_name='newscomment', + name='reply_to', + field=models.ForeignKey(blank=True, null=True, to='news.NewsComment'), + ), + ] diff --git a/news/migrations/__init__.py b/news/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/news/models.py b/news/models.py new file mode 100644 index 0000000..b753648 --- /dev/null +++ b/news/models.py @@ -0,0 +1,58 @@ +from django.core.urlresolvers import reverse +from django.db import models +from django.utils import timezone + + +def photo_filename(instance, filename): + from slugify import slugify_filename + + return 'photo_uploads/' + slugify_filename(filename) + + +class News(models.Model): + created = models.DateTimeField('Дата и время', auto_now_add=True, editable=False) + title = models.CharField('Заголовок', max_length=512, null=False, blank=False, unique=True) + slug = models.SlugField('Ссылка', max_length=512, null=False, blank=False, unique=True) + text = models.TextField('Новость', null=False, blank=False) + is_public = models.BooleanField('Публиковать', default=True) + image = models.ImageField('Картинка', upload_to=photo_filename) + tags_list = models.ManyToManyField('NewsTag', null=True, blank=True) + + class Meta: + verbose_name = 'новость' + verbose_name_plural = 'новости' + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse('news_detail', args=(self.slug,)) + + +class NewsTag(models.Model): + title = models.CharField('Заголовок', max_length=512, null=False, blank=False, unique=True) + slug = models.SlugField('Ссылка', max_length=512, null=False, blank=False, unique=True) + news_list = models.ManyToManyField(News, null=True, blank=True) + + class Meta: + verbose_name = 'тег' + verbose_name_plural = 'теги' + + def __str__(self): + return self.title + + +class NewsComment(models.Model): + created = models.DateTimeField('Дата и время', auto_now_add=True, editable=False) + name = models.CharField('Имя', max_length=45, null=False, blank=False) + email = models.EmailField('Email (не будет опубликован)', null=False, blank=False) + text = models.TextField('Комментарий', null=False, blank=False) + reply_to = models.ForeignKey('self', null=True, blank=True) + news = models.ForeignKey(News, related_name='comments') + + class Meta: + verbose_name = 'комментарий' + verbose_name_plural = 'комментарии' + + def __str__(self): + return '{}: {}'.format(self.name, self.news.title) diff --git a/news/tests.py b/news/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/news/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/news/urls.py b/news/urls.py new file mode 100644 index 0000000..33374a9 --- /dev/null +++ b/news/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls import patterns, url +from django.views.generic import RedirectView +from .views import * + +urlpatterns = patterns('', + url(r'^$', NewsList.as_view(), name='news_index'), + url(r'^(?P[-\w]+)/$', + news_detail, name='news_detail'), + ) diff --git a/news/views.py b/news/views.py new file mode 100644 index 0000000..45c0d63 --- /dev/null +++ b/news/views.py @@ -0,0 +1,48 @@ +from django.contrib import messages +from django.shortcuts import render, get_object_or_404, redirect +from django.views.generic import ListView, DetailView +from django.views.generic.edit import FormView, CreateView +from news.forms import CommentForm +from news.models import * + + +class NewsList(ListView): + model = News + template_name = 'news/list.jinja' + queryset = News.objects.filter(is_public=True) + + def get_queryset(self): + tag = self.request.GET.get('tag', None) + retval = self.queryset + if tag: + retval = self.queryset.filter(tags_list__slug__iexact=tag) + return retval + + def get_context_data(self, **kwargs): + retval = super(NewsList, self).get_context_data() + tag = self.request.GET.get('tag', None) + if tag: + try: + retval['tag'] = NewsTag.objects.get(slug=tag) + except: + pass + return retval + + +def news_detail(request, slug): + object = get_object_or_404(News, slug__iexact=slug) + form = CommentForm(request.POST or None) + if form.is_valid(): + comment = form.save(commit=False) + comment.news = object + comment.save() + messages.success(request, 'Ваш комментарий успешно опубликован!') + return redirect(object.get_absolute_url()+'#comment{}'.format(comment.pk)) + + c = dict( + object=object, + form=form + ) + return render(request, 'news/detail.jinja', c) + + diff --git a/static/less/_.css b/static/less/_.css index 9bca604..03c1482 100644 --- a/static/less/_.css +++ b/static/less/_.css @@ -935,3 +935,10 @@ ul.messages { .well-large { padding: 40px; } +.news-container .comment { + overflow: auto; +} +.news-container .media { + background: #F5F7FA; + padding: 15px; +} diff --git a/static/less/_.less b/static/less/_.less index b0b0587..bead9f7 100644 --- a/static/less/_.less +++ b/static/less/_.less @@ -805,4 +805,13 @@ ul.messages { } .well-large{ padding: 40px; +} +.news-container{ + .comment{ + overflow: auto; + } + .media{ + background: #F5F7FA; + padding: 15px; + } } \ No newline at end of file diff --git a/store/admin.py b/store/admin.py index 6adc851..588c3d6 100644 --- a/store/admin.py +++ b/store/admin.py @@ -33,7 +33,7 @@ class CategoryAdmin(admin.ModelAdmin): list_display = ('title', get_parent_str, 'priority') list_editable = ('priority',) - list_filter = ('parent', ) + list_filter = ('parent__title', ) prepopulated_fields = {"slug": ("title",)} inlines = [AttributeForCategoryInline, ] diff --git a/store/migrations/0017_auto_20150614_1746.py b/store/migrations/0017_auto_20150614_1746.py new file mode 100644 index 0000000..de57c49 --- /dev/null +++ b/store/migrations/0017_auto_20150614_1746.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('store', '0016_auto_20150612_1250'), + ] + + operations = [ + migrations.AddField( + model_name='orderdata', + name='created', + field=models.DateTimeField(auto_now_add=True, verbose_name='Дата и время', default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='orderdata', + name='edited', + field=models.DateTimeField(verbose_name='Изменено', auto_now=True, default=django.utils.timezone.now), + preserve_default=False, + ), + ] diff --git a/store/models.py b/store/models.py index 14a0f15..f415c89 100644 --- a/store/models.py +++ b/store/models.py @@ -258,8 +258,13 @@ class ImageInProduct(models.Model): verbose_name = 'фото товара' verbose_name_plural = 'фото товаров' + def __str__(self): + return '{}: {}'.format(self.pk, self.product.title) + class OrderData(models.Model): + created = models.DateTimeField('Дата и время', auto_now_add=True, editable=False) + edited = models.DateTimeField('Изменено', auto_now=True, editable=False) first_name = models.CharField( 'Имя', max_length=64, blank=False, null=False) last_name = models.CharField( @@ -283,3 +288,10 @@ class OrderData(models.Model): verbose_name = 'заказ' verbose_name_plural = 'заказы' + def __str__(self): + return '{} {}: {}'.format( + self.first_name, + self.last_name, + self.amount + ) +