예제 #1
0
    def test_choices(self):

        types_dict = choices_list(
            (1, 'T1'),
            (2, 'T2'),
        )

        assert len(types_dict) == 2
        assert types_dict[1] == 'T1'
        assert types_dict[2] == 'T2'

        assert list(types_dict.keys()) == [1, 2]

        ch = get_choices(types_dict)
        assert len(ch) == 2

        assert ch[0][0] == 1
        assert ch[0][1] == 'T1'

        assert ch[1][0] == 2
        assert ch[1][1] == 'T2'
예제 #2
0
    def test_choices(self):

        types_dict = choices_list(
            (1, 'T1'),
            (2, 'T2'),
        )

        assert len(types_dict) == 2
        assert types_dict[1] == 'T1'
        assert types_dict[2] == 'T2'

        assert list(types_dict.keys()) == [1, 2]

        ch = get_choices(types_dict)
        assert len(ch) == 2

        assert ch[0][0] == 1
        assert ch[0][1] == 'T1'

        assert ch[1][0] == 2
        assert ch[1][1] == 'T2'
예제 #3
0
class Reference(InheritedModel, RealmBaseModel, CommonEntityModel, ModelWithDiscussions, ModelWithCompiledText):
    """Модель сущности `Справочник`."""

    TYPE_CHAPTER = 1
    TYPE_PACKAGE = 2
    TYPE_MODULE = 3
    TYPE_FUNCTION = 4
    TYPE_CLASS = 5
    TYPE_METHOD = 6
    TYPE_PROPERTY = 7

    TYPES = choices_list(
        (TYPE_CHAPTER, 'Раздел справки'),
        (TYPE_PACKAGE, 'Описание пакета'),
        (TYPE_MODULE, 'Описание модуля'),
        (TYPE_FUNCTION, 'Описание функции'),
        (TYPE_CLASS, 'Описание класса/типа'),
        (TYPE_METHOD, 'Описание метода класса/типа'),
        (TYPE_PROPERTY, 'Описание свойства класса/типа'),
    )

    type = models.PositiveIntegerField(
        'Тип статьи', choices=get_choices(TYPES), default=TYPE_CHAPTER,
        help_text='Служит для структурирования информации. Справочные статьи разных типов могут выглядеть по-разному.')

    parent = models.ForeignKey(
        'self', related_name='children', verbose_name='Родитель', db_index=True, null=True, blank=True,
        help_text='Укажите родительский раздел. '
                  'Например, для модуля можно указать раздел справки, в которому он относится; '
                  'для метода — класс.')

    version_added = models.ForeignKey(
        Version, related_name='%(class)s_added', verbose_name='Добавлено в', null=True, blank=True,
        help_text='Версия Python, для которой впервые стала актульна данная статья<br>'
                  '(версия, где впервые появился модуль, пакет, класс, функция).')

    version_deprecated = models.ForeignKey(
        Version, related_name='%(class)s_deprecated', verbose_name='Устарело в', null=True, blank=True,
        help_text='Версия Python, для которой впервые данная статья перестала быть актуальной<br>'
        '(версия, где модуль, пакет, класс, функция были объявлены устаревшими).')

    func_proto = models.CharField(
        'Прототип', max_length=250, null=True, blank=True,
        help_text='Для функций/методов. Описание интерфейса, например: <i>my_func(arg, kwarg=None)</i>')

    func_params = models.TextField(
        'Параметры', null=True, blank=True,
        help_text='Для функций/методов. Описание параметров функции.')

    func_result = models.CharField(
        'Результат', max_length=250, null=True, blank=True,
        help_text='Для функций/методов. Описание результата, например: <i>int</i>.')

    history = HistoricalRecords()

    class Meta:
        verbose_name = 'Статья справочника'
        verbose_name_plural = 'Справочник'
        ordering = ('parent_id', 'title')

    class Fields:
        title = {
            'verbose_name': 'Название',
            'help_text': ('Здесь следует указать название раздела справки '
                          'или пакета, модуля, класса, метода, функции и т.п.',)
        }
        description = {
            'verbose_name': 'Кратко',
            'help_text': 'Краткое описание для раздела или пакета, модуля, класса, метода, функции и т.п.',
        }
        text_src = {
            'verbose_name': 'Описание',
            'help_text': 'Подробное описание. Здесь же следует располагать примеры кода.',
        }

    notify_on_publish = False
    autogenerate_slug = True

    def is_type_callable(self):
        return self.type in (self.TYPE_METHOD, self.TYPE_FUNCTION)

    def is_type_method(self):
        return self.type == self.TYPE_METHOD

    def is_type_module(self):
        return self.type == self.TYPE_MODULE

    def is_type_class(self):
        return self.type == self.TYPE_CLASS

    def is_type_chapter(self):
        return self.type == self.TYPE_CHAPTER

    @classmethod
    def get_actual(cls, parent=None, exclude_id=None):
        qs = cls.objects.published()

        if parent is not None:
            qs = qs.filter(parent=parent)

        if exclude_id is not None:
            qs = qs.exclude(pk=exclude_id)

        return qs.order_by('-time_published').all()
예제 #4
0
class Event(InheritedModel, RealmBaseModel, CommonEntityModel, ModelWithDiscussions, ModelWithCategory,
            ModelWithCompiledText):
    """Модель сущности `Событие`."""

    SPEC_DEDICATED = 1
    SPEC_HAS_SECTION = 2
    SPEC_HAS_SOME = 3

    SPECS = choices_list(
        (SPEC_DEDICATED, 'Только Python'),
        (SPEC_HAS_SECTION, 'Есть секция/отделение про Python'),
        (SPEC_HAS_SOME, 'Есть упоминания про Python'),
    )

    TYPE_MEETING = 1
    TYPE_CONFERENCE = 2
    TYPE_LECTURE = 3
    TYPE_SPRINT = 4

    TYPES = choices_list(
        (TYPE_MEETING, 'Встреча'),
        (TYPE_LECTURE, 'Лекция'),
        (TYPE_CONFERENCE, 'Конференция'),
        (TYPE_SPRINT, 'Спринт'),
    )

    url = models.URLField('Страница в сети', null=True, blank=True)

    contacts = models.CharField(
        'Контактные лица', null=True, blank=True, max_length=255,
        help_text=('Контактные лица через запятую, координирующие/устраивающие событие.%s' %
                   ModelWithAuthorAndTranslator._hint_userlink))

    place = models.ForeignKey(
        Place, verbose_name='Место', related_name='events', null=True, blank=True,
        help_text=('Укажите место проведения мероприятия.<br><b>Конкретный адрес следует указывать в описании.</b><br>'
                   'Например: «Россия, Новосибирск» или «Новосибирск», но не «Нск».'))

    specialization = models.PositiveIntegerField('Специализация', choices=get_choices(SPECS), default=SPEC_DEDICATED)
    type = models.PositiveIntegerField('Тип', choices=get_choices(TYPES), default=TYPE_MEETING)
    time_start = models.DateTimeField('Начало', null=True, blank=True)
    time_finish = models.DateTimeField('Завершение', null=True, blank=True,
                                       help_text='Дату завершения можно и не указывать.')
    fee = models.BooleanField('Участие платное', default=False, db_index=True)

    history = HistoricalRecords()

    class Meta:
        verbose_name = 'Событие'
        verbose_name_plural = 'События'

    class Fields:
        description = {
            'verbose_name': 'Краткое описание',
            'help_text': 'Краткое описание события. %s' % HINT_IMPERSONAL_REQUIRED,
        }
        text_src = {
            'verbose_name': 'Описание, контактная информация',
            'help_text': '%s' % HINT_IMPERSONAL_REQUIRED,
        }
        cover = 'Логотип'

    def save(self, *args, **kwargs):
        if not self.pk:
            self.status = self.STATUS_PUBLISHED
        super().save(*args, **kwargs)

    def get_display_type(self):
        return self.TYPES[self.type]

    def get_display_specialization(self):
        return self.SPECS[self.specialization]

    def is_in_past(self):
        field = self.time_finish or self.time_start
        if field is None:
            return None
        return field < timezone.now()

    def is_now(self):
        if not all([self.time_start, self.time_finish]):
            return False
        return self.time_start <= timezone.now() <= self.time_finish

    @classmethod
    def get_paginator_objects(cls):
        now = timezone.now().date().isoformat()
        # Сначала грядущие в порядке приближения, потом прошедшие.
        return cls.objects.published().extra(
            select={'in_future': "time_start > '%s'" % now}).order_by('-in_future', 'time_start').all()
예제 #5
0
class Article(InheritedModel, RealmBaseModel, CommonEntityModel, ModelWithDiscussions, ModelWithCategory,
              ModelWithCompiledText):
    """Модель сущности `Статья`."""

    LOCATION_INTERNAL = 1
    LOCATION_EXTERNAL = 2

    LOCATIONS = choices_list(
        (LOCATION_INTERNAL, 'На этом сайте'),
        (LOCATION_EXTERNAL, 'На другом сайте'),
    )

    SOURCE_HANDMADE = 1
    SOURCE_SCRAPING = 2
    SOURCE_RSS = 3

    SOURCES = choices_list(
        (SOURCE_HANDMADE, 'Написана на этом сайте'),
        (SOURCE_SCRAPING, 'Соскоблена с другого сайта'),
        (SOURCE_RSS, 'Взята из RSS'),
    )

    source = models.PositiveIntegerField(
        'Тип источника', choices=get_choices(SOURCES), default=SOURCE_HANDMADE,
        help_text='Указывает на механизм, при помощи которого статья появилась на сайте.')

    location = models.PositiveIntegerField(
        'Расположение статьи', choices=get_choices(LOCATIONS), default=LOCATION_INTERNAL,
        help_text='Статью можно написать прямо на этом сайте, либо сформировать статью-ссылку на внешний ресурс.')

    url = models.URLField(
        'URL статьи', null=True, blank=False, unique=True,
        help_text='Внешний URL, по которому доступна статья, которой вы желаете поделиться.')

    published_by_author = models.BooleanField('Я являюсь автором данной статьи', default=True)

    history = HistoricalRecords()

    class Meta:
        verbose_name = 'Статья'
        verbose_name_plural = 'Статьи'

    class Fields:
        description = {
            'verbose_name': 'Введение',
            'help_text': 'Пара-тройка предложений, описывающих, о чём пойдёт речь в статье.',
        }
        linked = {
            'verbose_name': 'Связанные статьи',
            'help_text': ('Выберите статьи, которые имеют отношение к данной. '
                          'Так, например, можно объединить статьи цикла.',)
        }

    def is_handmade(self):
        """Возвращат флаг, указывающий на то, что статья создана на этом сайте.

        :return:
        """
        return self.source == self.SOURCE_HANDMADE

    def update_data_from_url(self, url):
        """Обновляет данные статьи, собирая информация, доступную по указанному URL.

        :param url:
        :return:
        """
        result = scrape_page(url)
        if result is None:
            raise RemoteSourceError('Не удалось получить данные статьи. Проверьте доступность указанного URL.')

        self.title = result['title']
        self.description = result['content_less']
        self.text_src = result['content_more']
        self.source = self.SOURCE_SCRAPING