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 }}
+
+
+
+
+
+ Теги:
+
+ {% for tag in object.tags_list.all() %}
+
{{ tag.title }}
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+
+
+{% 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 %}
+
+
+
+
+ {% if tag %}
+ Новости с тегом "{{ tag.title }}"
+
{% endif %}
+ {% for object in object_list %}
+
+
+
+
+
+ {{ 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
+ )
+
+ Комментарии:
+ + + {% if object.comments.all() %} + ++ + + {% for comment in object.comments.all() %} + +-
+
+
+
+
+
+ {% endfor %}
+
+ {% else %} +{{ comment.name }} пишет: #
+{{ comment.created.strftime('%d.%m.%Y %H:%M') }}
+{{ comment.text|striptags }}
+ + +