parent
6d7fcc76b1
commit
fad441d3ac
21 changed files with 488 additions and 4 deletions
@ -0,0 +1,113 @@ |
|||||||
|
{% extends 'base.jinja' %} |
||||||
|
{% block content %} |
||||||
|
<div class=" breadcrumbs"> |
||||||
|
<ol class="breadcrumb breadcrumb-arrow"> |
||||||
|
<li><a href="/">Главная</a></li> |
||||||
|
<li><a href="/news/">Новости</a></li> |
||||||
|
<li class="active"><span>{{ object.title }}</span></li> |
||||||
|
|
||||||
|
</ol> |
||||||
|
</div><h2 class=""> |
||||||
|
{{ object.title }} |
||||||
|
</h2><br/> |
||||||
|
<div class="well well-lg news-container"> |
||||||
|
|
||||||
|
<p class="text-muted"> |
||||||
|
<small> |
||||||
|
<span class="glyphicon glyphicon-time" |
||||||
|
aria-hidden="true"></span> {{ object.created.strftime('%d.%m.%Y') }} |
||||||
|
<span class="glyphicon glyphicon-comment" aria-hidden="true"></span> <a |
||||||
|
href="#comments">Комментарии ({{ object.comments.count() }})</a> |
||||||
|
</small> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p class="text-center"> |
||||||
|
{% set im = object.image %} |
||||||
|
<img src="/static/{{ im.url }}" alt="" style="max-width: 100%" class=""/> |
||||||
|
</p> |
||||||
|
{{ object.text|linebreaks|safe }} |
||||||
|
|
||||||
|
<hr/> |
||||||
|
<div class="row"> |
||||||
|
<div class="social-links col-xs-6"> |
||||||
|
<h5 class="text-left"> |
||||||
|
Теги:</h5> |
||||||
|
|
||||||
|
{% for tag in object.tags_list.all() %} |
||||||
|
<a href="/news/?tag={{ tag.slug }}"><span class="badge"><span |
||||||
|
class="glyphicon glyphicon-tag"></span> {{ tag.title }}</span></a> |
||||||
|
{% endfor %} |
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="tags col-xs-6"> |
||||||
|
<h5 class="text-left"> |
||||||
|
Поделиться ссылкой:</h5> |
||||||
|
|
||||||
|
<script type="text/javascript" src="//yastatic.net/share/share.js" charset="utf-8"></script> |
||||||
|
<div class="yashare-auto-init" data-yashareL10n="ru" data-yashareType="small" |
||||||
|
data-yashareQuickServices="vkontakte,facebook,twitter,odnoklassniki,moimir,gplus" |
||||||
|
data-yashareLink="http://batiskaf-kz.kz{{ object.get_absolute_url() }}" |
||||||
|
data-yashareTitle="{{ object.title }}" data-yashareTheme="counter"></div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<hr/> |
||||||
|
<div class="comments"> |
||||||
|
<a name="comments"></a> |
||||||
|
|
||||||
|
<h3 class="text-left"> |
||||||
|
Комментарии:</h3> |
||||||
|
|
||||||
|
|
||||||
|
{% if object.comments.all() %} |
||||||
|
|
||||||
|
<ul class="media-list"> |
||||||
|
|
||||||
|
|
||||||
|
{% for comment in object.comments.all() %} |
||||||
|
|
||||||
|
<li class="media"> |
||||||
|
<a name="comment{{ comment.pk }}"></a> |
||||||
|
<div class="media-body"> |
||||||
|
<h4 class="media-heading text-left">{{ comment.name }} пишет: <small><a |
||||||
|
href="{{ request.get_full_path() }}#comment{{ comment.pk }}">#</a></small></h4> |
||||||
|
<p>{{ comment.created.strftime('%d.%m.%Y %H:%M') }}</p> |
||||||
|
<p>{{ comment.text|striptags }}</p> |
||||||
|
<!-- Nested media object --> |
||||||
|
|
||||||
|
</div> |
||||||
|
</li> |
||||||
|
|
||||||
|
{% endfor %} |
||||||
|
</ul> |
||||||
|
{% else %} |
||||||
|
<div class="alert alert-warning alert-dismissable"> |
||||||
|
<strong>Пока нет ни одного комментария!</strong> Вы можете <a href="#comment">стать первым</a>! |
||||||
|
</div> |
||||||
|
{% endif %} |
||||||
|
|
||||||
|
</div> |
||||||
|
<div class="comment"> |
||||||
|
<a name="comment"></a> |
||||||
|
<h4 class="text-center"> |
||||||
|
Оставить комментарий:</h4> |
||||||
|
|
||||||
|
<div class="comment-form col-xs-6 col-xs-offset-3"> |
||||||
|
<form action="" class="form" method="post"><input type="hidden" name="csrfmiddlewaretoken" |
||||||
|
value="{{ csrf_token }}"> |
||||||
|
{{ form|bootstrap }} |
||||||
|
<div class="form-group text-left"> |
||||||
|
<button type="submit" name="comment-send" class="btn btn-primary"><span |
||||||
|
class="glyphicon glyphicon-comment" aria-hidden="true"></span> Отправить |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
</div> |
||||||
|
|
||||||
|
{% endblock %} |
||||||
|
|
||||||
@ -0,0 +1,55 @@ |
|||||||
|
{% extends 'base.jinja' %} |
||||||
|
{% block content %} |
||||||
|
<div class=" breadcrumbs"> |
||||||
|
<ol class="breadcrumb breadcrumb-arrow"> |
||||||
|
<li><a href="/">Главная</a></li> |
||||||
|
<li><a href="/news/">Новости</a></li> |
||||||
|
|
||||||
|
<li class="active"><span>Новости |
||||||
|
{% if tag %} |
||||||
|
с тегом "{{ tag.title }}" |
||||||
|
{% endif %} |
||||||
|
</span></li> |
||||||
|
</ol> |
||||||
|
</div> |
||||||
|
<script type="text/javascript" src="//yastatic.net/share/share.js" charset="utf-8"></script> |
||||||
|
{% if tag %} |
||||||
|
<h3>Новости с тегом "{{ tag.title }}" |
||||||
|
</h3> <br/>{% endif %} |
||||||
|
{% for object in object_list %} |
||||||
|
<div class="well well-lg news-container"> |
||||||
|
<h2 class="text-left"> |
||||||
|
<a href="{{ url('news_detail', args=(object.slug,)) }}">{{ object.title }}</a> |
||||||
|
</h2> |
||||||
|
|
||||||
|
<p class="text-muted"> |
||||||
|
<small> |
||||||
|
<span class="glyphicon glyphicon-time" |
||||||
|
aria-hidden="true"></span> {{ object.created.strftime('%d.%m.%Y') }} |
||||||
|
<span class="glyphicon glyphicon-comment" aria-hidden="true"></span> <a |
||||||
|
href="{{ url('news_detail', args=(object.slug,)) }}#comment">Комментировать</a> |
||||||
|
</small> |
||||||
|
</p> |
||||||
|
<p class="text-center"> |
||||||
|
{% set im = object.image|thumbnail("400x400") %} |
||||||
|
<a href="{{ url('news_detail', args=(object.slug,)) }}"><img src="/static/{{ im.url }}" alt=""/></a> |
||||||
|
</p> |
||||||
|
{{ object.text|truncate(520)|linebreaks|safe }} |
||||||
|
<p class="text-right"><a href="{{ url('news_detail', args=(object.slug,)) }}">Продолжить читать →</a> |
||||||
|
</p> |
||||||
|
<hr/> |
||||||
|
<div class="social-links"> |
||||||
|
<strong> |
||||||
|
Поделиться ссылкой: |
||||||
|
|
||||||
|
<div class="yashare-auto-init" data-yashareL10n="ru" data-yashareType="small" |
||||||
|
data-yashareQuickServices="vkontakte,facebook,twitter,odnoklassniki,moimir,gplus" |
||||||
|
data-yashareLink="http://batiskaf-kz.kz{{ object.get_absolute_url() }}" |
||||||
|
data-yashareTitle="{{ object.title }}" data-yashareTheme="counter"></div> |
||||||
|
</strong> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{% endfor %} |
||||||
|
|
||||||
|
{% endblock %} |
||||||
|
|
||||||
@ -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') |
||||||
|
|
||||||
@ -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'] |
||||||
@ -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'), |
||||||
|
), |
||||||
|
] |
||||||
@ -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'), |
||||||
|
), |
||||||
|
] |
||||||
@ -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'), |
||||||
|
), |
||||||
|
] |
||||||
@ -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) |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.test import TestCase |
||||||
|
|
||||||
|
# Create your tests here. |
||||||
@ -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<slug>[-\w]+)/$', |
||||||
|
news_detail, name='news_detail'), |
||||||
|
) |
||||||
@ -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) |
||||||
|
|
||||||
|
|
||||||
@ -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, |
||||||
|
), |
||||||
|
] |
||||||
Loading…
Reference in new issue