Забери мусор с собой!



    «Забери мусор с собой!» — так называется сайт, который я сделал пару недель назад на выходных (почти 2 дня делал), как раз к весеннему сезону, когда многие начинают выезжать за город на отдых.

    Главная идея проста — убеждать людей, что природу нужно сохранить чистой. Для этого на сайте призываю всех убирать за собой (и не только за собой) мусор, а также на выбор предлагаются разные варианты плакатов в формате А4, которые можно распечатать на обычном принтере и приколоть канцелярскими кнопками к дереву, такая форма наглядой агитации:

    изображения плакатов


    Графика


    Прежде всего стоит сказать о том, что такие замечательные картинки для плакатов я взял на сайте openclipart.org. Они распространяются под свободной лицензией, и очень качественно отрисованы в векторе, поэтому как нельзя лучше подошли в качестве клипарта.

    Плакаты я нарисовал в векторном редакторе Inkscape, после чего сохранил в pdf файлы, которые посетители сайта могут скачать и распечатать. Редактор справился с этой задачей замечательно.

    «Движок»


    В кавычках — потому что там кода кот наплакал.
    Сайт работает на django, используя одну модельку и три функции. Для каждого плаката с животным есть ссылка на википедию и видеоролик, это сделано для того, чтобы посетители могли узнать больше о животном с плаката. Линки на скачивание pdf обрабатываются функцией, которая ведёт статистику скачиваний плакатов. Вот это практически весь код сайта:

    models.py
    
    # coding: utf-8
    import os
    import settings
    from django.db import models
    from django.core.files.storage import FileSystemStorage
    
    class OverwriteStorage(FileSystemStorage):
        
        def get_available_name(self, name):
            """
            Returns a filename that's free on the target storage system, and
            available for new content to be written to.
            """
            # If the filename already exists, remove it as if it was a true file system
            if self.exists(name):
                os.remove(os.path.join(settings.MEDIA_ROOT, name))
            return name
    
    fs=OverwriteStorage(location=settings.MEDIA_ROOT)
    
    class Poster(models.Model):
        title = models.CharField(max_length=100, verbose_name="Название плаката")
        thumbnail = models.ImageField(upload_to='images/posters',verbose_name="Иконка плаката")
        preview = models.ImageField(upload_to='images/posters',verbose_name="Превьюшка плаката")
        pdf = models.FileField("PDF файл плаката", upload_to='posters/', storage=fs)
        downloads = models.IntegerField("Количество скачиваний постера", default=0)
        wiki_youtube_title = models.CharField(max_length=100, blank=True, default="", verbose_name="Текст ссылки на википедию и ютуб")
        wiki_url = models.URLField("Ссылка на статью в википедии", blank=True)
        video = models.TextField("Код для вставки видеоролика", blank=True)
        youtube_url = models.URLField("Ссылка на ютуб-ролики", blank=True)
    
        def __unicode__(self):
            return u'Плакат "%s"' % self.title
    
        def get_absolute_url(self): 
            return "/poster/%d/" % self.id
    
        class Meta():
            ordering = ['id']
            verbose_name = "постер"
            verbose_name_plural = "постеры"
    
    
    views.py
    # coding: utf-8
    
    from models import *
    
    from django.shortcuts import render_to_response, get_object_or_404
    from django.template import RequestContext
    from django.http import HttpResponseRedirect
    
    def index(request):
        posters = Poster.objects.all()
        return render_to_response('website/index.html',
                                  {'posters': posters,},
                                  context_instance=RequestContext(request))
    
    def poster(request, poster_id, please_explain=False):
        poster = get_object_or_404(Poster, id=poster_id)
        return render_to_response('website/poster.html',
                                  {'poster': poster,
                                   'please_explain': please_explain,},
                                  context_instance=RequestContext(request))
    
    def download_poster(request, poster_id):
        poster = get_object_or_404(Poster, id=poster_id)
        poster.downloads += 1
        poster.save()
        return HttpResponseRedirect('/static/' + poster.pdf.url)
    


    В модельке я добавил youtube_url, т.к. каждый раз html код вставлять избыточно, тем более на всех страницах плеер одинакового размера. Добавить добавил, а миграцию и шаблоны не переделывал, т.к. и так работает. В общем, недооптимизировал.

    please_explain во вьюшке poster добавлено для того, чтобы посетители с другого сайта, перешедшие по баннерам, видели коротенькое объяснение, для чего нужен этот сайт.

    css


    Т.к. я не дизайнер, для оформления использовал простейшие стили, а для работы с css используется фреймворк Compass. Он позволяет разрабатывать разметку сайта на основе сетки, что сильно упрощает таким как я создание более-менее кроссбраузерного контента (IE поддерживается «из коробки»). Одно время я отрицательно относился к css фреймворкам, но Compass поменял моё отношение.

    В основе Compass два других фреймворка — SASS и Blueprint. SASS это фактически такой препроцессор для css файлов — там есть и переменные, и эквивалент функций и многое другое.

    Исходный код *.scss файла компилится и получается обычный css файл, но с комментами. Его потом можно обработать любым компрессором и будет всё ОК.

    Если надумаете ставить Compass в Ubuntu, последовательность такая (в 10.04 по крайней мере):

    sudo apt-get install ruby rubygems rubygems-update
    cd /var/lib/gems/КАКАЯ.ТО.ВЕРСИЯ/gems/rubygems-update-КАКАЯ.ТО.ВЕРСИЯ
    sudo ruby setup.rb
    sudo gem install compass
    

    Что касается резиновости, blueprint и compass — почему-то последняя версия неоптимально компилирует mixin liquid. Неоптимально — в смысле просто дописывает его в конец файла, переопределяя вышестоящие стили, из-за этого css файл гораздо больше в размере. Чтобы победить это, можете в своём главном scss файле использовать такую конструкцию:
    @import "blueprint/reset";
    @import "blueprint/scaffolding";
    @import "blueprint/liquid";
    @import "blueprint/typography";
    @import "blueprint/utilities";
    @import "blueprint/form";
    @import "blueprint/interaction";
    
    @include blueprint-typography;
    @include blueprint-utilities;
    @include blueprint-liquid-grid;
    @include blueprint-interaction;
    @include blueprint-form;  
    

    Обещанные картинки


    У моего друга есть сайт, и он предложил повесить на нём баннеры для привлечения внимания к сайту. Я решил, что надо найти какие-то интересные малоизвестные факты о животных, и использовать их в качестве текстов. Получилось вот так:

    Ваше мнение и участие


    Естественно, меня прежде всего интересует ваше мнение — что можно улучшить? Может быть, есть какие-то мысли, что можно добавить на сайт. Я думал ещё на страницы плакатов добавить инструкции по изготовлению несложных оригами на тему животных, а дочка предложила добавить анекдоты.

    Ну и конечно же, большая просьба рассказать об этом сайте своим друзьям и знакомым, тем более сегодня пятница, завтра наверняка многие поедут на природу. Чем больше будет небезразличных людей, тем лучше будет наша жизнь и чище природа.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 23

      +13
      Забери мусор с собой, %username%!

      image
        +2
        Насчёт гипножабы не додумался :-)
        +3
        Что если такой плакат:
        ▢ Захватить мусор
          0
          Идею примерно понял, спасибо!
          0
          Начинание правильное и полезное. В качестве идеи могу предложить следующее: добавить некую фичу, дающую возможность пользователям отметить/задать места больше всего нуждающиеся в помощи, если еще и с голосованием, то вообще отлично. Чтобы каждый зашедший мог увидеть: «вот самое проблемное место в моем регионе, мы как-раз хотели устроить субботник, а давайте съездим туда». Было бы удобно )
            0
            ОК, спасибо, это хорошая идея.
            0
            Хорошая идея.
            Баннерам не хватает идеологии. «У улитки 100500 зубов» И чё? «И они её не помогут, если ты завалишь её мусором». Как-то так.
            Сделайте доступными коды баннеров.
            Сделайте больше соц кнопок через аггрегаторы типа www.addthis.com
            PS А ещё мне понравилось что вы не называете свой сайт этим великим и ужасным словом «Стартап» ))
              +1
              Я намеренно сделал баннеры без какой-либо доп. информации, просто для привлечения внимания. Многим не нравится, когда сразу грузят.

              Больше кнопок на страницах плакатов. Не знаю, стоит ли на первую больше.

              Баннеры да, надо сделать доступными для встраивания, спасибо.

              Конечно же это никакой не стартап, т.к. к бизнесу не имеет никакого отношения :-)
                0
                >>Я намеренно сделал баннеры без какой-либо доп. информации, просто для привлечения внимания. Многим не нравится, когда сразу грузят.

                Просто констатация факта «У улитки 100500 зубов» уже логически законченное выражение, которое не поощряет клик по баннеру. А если хотя бы сделать «У улитки 100500 зубов, НО...» уже создает предпосылку к тому, что читатель баннера заинтересуется, «а что дальше?». То же самое желательно придумать и для плакатов, а то ЦА может воспринять «Эй, лось, забери мусор с собой» )) Хотя может я усложняю сильно, и достаточно просто меньшим шрифтом написать возле лося некий «мотиватор».
                  0
                  Насчёт «но..» интересно.
                  В плакат я пытался разные тексты вставлять, но всё как-то нехорошо получалось, поэтому остановился на одной фразе. Не копирайтер всё-таки, программист :-)
                  0
                  Стартап — необязательно бизнес. Скорее «начинание».
                  0
                  >У улитки 100500 зубов» И чё? «И они её не помогут, если ты завалишь её мусором

                  Можно полюбопытствовать. что они должны «её помочь» ??? :)
                    0
                    Это просто пример концепта идеологии. Может не очень удачный. И вообще я хотел сказать о том, что просто констатация факта — скучна и закончена. Для того чтобы пользователь нажал на баннер нужно что-то ему за это дать. Вернее давать тоже не обязательно — главное дать понять, что он что-то получит если нажмет на баннер. Таким образом:
                    1. Мы размещаем «У улитки 100500 зубов, и они ей не помогут, если ты завалишь её дом мусором. (Кликни здесь, чтобы помочь улитке)»
                    2. Зритель задает вопрос: «Чем могут помочь улитке 100500 её зубов?» и жмет на баннер.
                    3. Тут главное направить на страницу с улиткой, иначе внимание рассеится и эффект будет не тот.
                    4. ПРОФИТ.
                      0
                      Мне кажется, что вместо 1. «но...» интереснее — правда как-то интригует. А уже там где плакат, разместить информацию, почему улитке плохо от загрязнения.
                        0
                        > разместить информацию, почему улитке плохо от загрязнения.

                        Думаю, что лучше не идти от противного «давайте не мусорить, а то кому-то будет от этого плохо», т.к. в этом случае наше «не мусорить» будет означать «от жалости к животным». Для кого-то работает, для кого-то нет.

                        Лучше в стиле «пусть будет чисто: и нам хорошо и улиткам». Поддерживать что-то в конструктивном направлении всегда приятнее.
                  +1
                  На плакатах довольно много черного — возможно, кому-то станет жалко на своем принтере так тратить картридж.
                  Спасибо за работу в направлении чистоты и экологии!
                    0
                    Да у меня жена такая. Я люблю плакаты делать, каждый раз мне выговаривает :-)
                    На это можно легко отвечать, ткнув пальцем в кипы распечаток, у моей например пачек 20 распечатанных дома хранится, не меньше. А сколько в офисах уходит — это вообще мрак.
                    +4
                    У вас что-то с доменом, он почему-то написан кириллическими символами, я бы на вашем месте поправил
                      +1
                      Можете таким пользоваться, если удобнее: xn--80acaphjiwsabsdmca3a.xn--p1ai

                      Если серьёзно — я решил что в этом конкретном случае рф домен будет удобнее, т.к. ЦА вся местная, наша, российская :-)
                      +1
                      Отличная тема, спасибо. Больше всего радует, что на плакатах написано не «не оставляй мусор», а «забери с собой» — позитивнее однако :)
                        0
                        Спасибо, тут вот ещё подсказали, будем думать :)
                        –2
                        Можно несколько замечаний по коду?
                        from models import *

                        К чему здесь wild import?
                        from models import Poster

                        def index — можно использовать generic views
                        То же касается и poster view.

                        import settings — было бы уместнее:
                        from django.conf import settings

                        Не стоит использовать абсолютные url.
                        Есть функция reverse:
                        from django.core.urlresolvers import reverse

                        Ну и наконец, не надо вызывать class Meta
                        class Meta:
                        ordering = ['id']
                        verbose_name = "постер"
                        verbose_name_plural = "постеры"
                          +1
                          насчёт wild согласен, это плохая практика, но так быстрее, а времени не оч. много было

                          generic вьюхи это хорошо, но когда они не меняются, а когда меняются, код имхо лучше читается у обычных, поэтому я не использую generic

                          reverse обычно использую, кстати в urls.py всё поименовано

                          Meta не вызывается, ставить пустые скобки — привычка из С++,
                          >>> class C1():
                          … pass
                          >>> class C2:
                          … pass
                          >>> c1 = C1()
                          >>> c2 = C2()
                          >>> type(c1)
                          0: <type 'instance'>
                          >>> type(c2)
                          1: <type 'instance'>
                          >>> type(C1)
                          2: <type 'classobj'>
                          >>> type(C2)
                          3: <type 'classobj'>

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое