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