Successfully reported this slideshow.
Your SlideShare is downloading. ×

Журнальная вёрстка в Django

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 35 Ad

More Related Content

Slideshows for you (15)

Similar to Журнальная вёрстка в Django (20)

Advertisement

Recently uploaded (20)

Advertisement

Журнальная вёрстка в Django

  1. 1. Журнальная вёрстка Делаем “красиво” с Django Алексей Дубков alex@evid.ru MoscowDjango, 01/03/2012
  2. 2. CMS против • Раньше верстали руками • Сейчас копируют и вставляют • Скучный “Текст” • HTML-редактор не спасает • Скудное оформление
  3. 3. Что хочется • Перемешивать текст и графику • Делать выноски, плашки • Делать колонки • Расставлять акценты • Галерею, вот прямо сюда
  4. 4. И так...
  5. 5. В чём идея? • Любой элемент — блок • Блоки: текст + графика • Сверху-вниз • Слева-направо • Блоки независимы друг от друга
  6. 6. Итак, блоки • Они могут быть разных типов • Как-то отсортированы • Привязаны к Статье, Новости и т.д.
  7. 7. # blocks/models.py from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes import generic class Block(models.Model): BLOCK_TYPES = ( (11, u'T-01: Обычный текст'), (21, u'P-01: Картинки 250x в 3 колонки'),) CAN_COLLAPSE = (21,) content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey( 'content_type', 'object_id') block_type = models.IntegerField(choices=BLOCK_TYPES) sort = models.IntegerField(default=20) image = models.ImageField(blank=True) title = models.CharField(max_length=255, blank=True) text = models.TextField(blank=True)
  8. 8. # blocks/admin.py from django.contrib import admin from django.contrib.contenttypes.generic import GenericStackedInline from blocks.models import Block class BlockInline(GenericStackedInline): model = Block extra = 0 fieldsets = ( (None, { 'fields': (('block_type', 'sort',), 'image', 'title', 'text',) }), )
  9. 9. Вывести блоки • Выбираем блоки для статьи • Склеиваем (CAN_COLLAPSE) • Отдельный рендер для блока • Склеиваем конечный HTML
  10. 10. # blocks/utils.py from django.template import RequestContext, loader from django.contrib.contenttypes.models import ContentType from blocks.models import Block def get_blocks_html(request, obj): content_type = ContentType.objects.get( model=obj.__class__.__name__) blocks = Block.objects.filter( content_type=content_type, object_id=obj.id).order_by('sort') blocks_count = blocks.count()
  11. 11. # blocks/utils.py ... bl = [] # blocks tuple (type, data) if blocks_count: it = 0 i = 0 while i < blocks_count: type = blocks[i].block_type if type in Block.CAN_COLLAPSE: result = [] it = i for j in blocks[i:]: if j.block_type == type: result.append(j) it += 1 else: break bl.append([type, {'blocks':result}]) i = it - 1 else: bl.append([type, blocks[i].__dict__]) i += 1
  12. 12. # blocks/utils.py ... html = '' # result html if blocks_count: for (type, item) in bl: t_name = "blocks/block-%s.html" % type t = loader.get_template(t_name) render = t.render( RequestContext(request, item)) html += render return html
  13. 13. Шаблоны • В простых шаблонах сразу выводятся переменные {{ title }}, {{ text }}... • В склееных шаблонах нужен цикл • {{ for item in blocks }}
  14. 14. Пример • Делаем статьи • Подключаем админку • Блоки подключаем через inlines • Делаем вывод
  15. 15. # articles/models.py from django.db import models class Article(models.Model): title = models.CharField(max_length=64) pub_date = models.DateField() blocks_html = models.TextField(blank=True) class Meta: ordering = ['-pub_date']
  16. 16. # articles/admin.py from django.contrib import admin from articles.models import Article from blocks.admin import BlockInline class ArticleAdmin(admin.ModelAdmin): save_on_top = True inlines = [BlockInline, ] list_display = ( 'title', 'pub_date',) admin.site.register(Article, ArticleAdmin)
  17. 17. # articles/views.py def articles_one(request, id): obj = get_object_or_404(Article, id=id) blocks_html = get_blocks_html(request, obj) return render_to_response( 'articles/articles_one.html', {'obj': obj,'blocks_html': blocks_html,}, context_instance=RequestContext(request))
  18. 18. Ньюансы • Как хранить картинки • Утомительная сортировка • Производительность
  19. 19. # blocks/models.py def image_upload(instance, filename): return "block/%s/%s" % (instance.content_object.block_image_path(), filename.lower()) # artiles/models.py class Article(models.Model): ... def block_image_path(self): return "article/%d/%02d/%d" % ( self.pub_date.year, self.pub_date.month, self.id)
  20. 20. $(document).ready(function(){ $('#block-block-content_type-object_id-group .add-row a').click(function(){ var totalBlocks=$('#id_block-block-content_type-object_id- TOTAL_FORMS').val(); var sortFieldId="#id_block-block-content_type- object_id-"+parseInt(totalBlocks-2)+"-sort"; var newSortFieldId="#id_block-block-content_type- object_id-"+parseInt(totalBlocks-1)+"-sort"; var lastSortVal=$(sortFieldId).val(); var newSortVal=parseInt(lastSortVal)+10; $(newSortFieldId).val(newSortVal); })
  21. 21. Скорость • Производительность низкая • Можно сохранять HTML • Переопределив save_model в админке сохранять дважды
  22. 22. Минусы • Сложно в обучении • Можно “накакафонить” • Подгонять контент под формат
  23. 23. Спасибо

×