Beispiel #1
0
class CmsCourse(Course):
    icon = models.CharField(max_length=100, default='fas fa-graduation-cap')
    flow_content = PlaceholderField(
        'flow_content',
        related_name='flow_content',
        help_text=_('Content shown on the flow index page'))
    common_content = PlaceholderField(
        'lesson_common_content',
        related_name='lesson_common_content',
        help_text=_('Content shown in each course lesson'))

    class Meta:
        verbose_name = _('Course')
        verbose_name_plural = _('Courses')

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):
        is_create = self.pk is None
        super().save(force_insert, force_update, using, update_fields)
        if is_create:
            cms.api.add_plugin(
                placeholder=self.flow_content,
                plugin_type='FlowLessonsCMSPlugin',
                language='ru',
            )
            cms.api.add_plugin(
                placeholder=self.common_content,
                plugin_type='CommentsCMSPlugin',
                language='ru',
            )
Beispiel #2
0
class Post(models.Model):
    section = models.ForeignKey(Section,
                                default=None,
                                on_delete=models.SET_DEFAULT,
                                related_name="posts",
                                verbose_name=_("Section"))
    categories = models.ManyToManyField(Category,
                                        related_name="posts",
                                        verbose_name=_("Category"),
                                        blank=True)
    title = models.CharField(_("Title"), default="", max_length=255)
    slug = models.SlugField(_("Slug"), max_length=255)
    image = PlaceholderField(slotname='post_image',
                             related_name='featured_image')
    author = models.CharField(_("Author"),
                              default="",
                              max_length=255,
                              blank=True)
    date = models.DateTimeField(_("Publish date"), default=get_now)
    summary = models.TextField(_("Summary"), blank=True, null=True)
    content = PlaceholderField(slotname='post_content')
    published = models.BooleanField(_("Published"), default=False)
    template = models.CharField(_("Template"),
                                max_length=255,
                                default=POST_DETAIL_TEMPLATE,
                                choices=post_templates)
    created = models.DateTimeField(_("Created"), auto_now_add=True, null=True)
    updated = models.DateTimeField(_("Edited"), auto_now=True)
    typo3_uid = models.IntegerField(_("Typo3 ID", ), null=True)
    typo3_pid = models.CharField(_("Typo3 Related", ),
                                 null=True,
                                 max_length=255)

    def __str__(self):
        return "%s" % self.title

    def get_absolute_url(self):
        return reverse('%s:%s' % (self.section.namespace, POST_DETAIL_URL),
                       args=[self.id, self.slug])

    def get_formatted_date(self):
        return self.date.strftime('%d.%m.%Y.')

    @property
    def cms_edit_text(self):
        return _('Edit information')

    class Meta:
        ordering = ("-date", )
        verbose_name = _("Post")
        verbose_name_plural = _("Posts")
Beispiel #3
0
class ReadingSection(Section):
    class Meta:
        verbose_name_plural = 'Sections (Reading)'
        manager_inheritance_from_future = True

    def absolute_url(self):
        return reverse('core:section_detail',
                       kwargs={
                           'module_slug': self.lesson.topic.module.slug,
                           'topic_slug': self.lesson.topic.slug,
                           'lesson_slug': self.lesson.slug,
                           'slug': self.slug
                       })

    '''
        define method to clear placeholderfield to be signaled on predelete
    '''

    def delete(self, *args, **kwargs):
        print("----- in ReadingSection overridden delete")
        # self.cleanup_placeholders()
        placeholders = [self.content]
        super(ReadingSection, self).delete(*args, **kwargs)

        for ph in placeholders:
            ph.clear()
            ph.delete()

    content = PlaceholderField('reading_content')
Beispiel #4
0
class ActivitySection(Section):
    class Meta:
        verbose_name_plural = 'Sections (Activity)'
        manager_inheritance_from_future = True

    def absolute_url(self):
        return reverse('core:section_detail',
                       kwargs={
                           'module_slug': self.lesson.topic.module.slug,
                           'topic_slug': self.lesson.topic.slug,
                           'lesson_slug': self.lesson.slug,
                           'slug': self.slug
                       })

    def delete(self, *args, **kwargs):
        print("----- in ActivitySection overridden delete")
        # self.cleanup_placeholders()

        placeholders = [self.content]
        super(ActivitySection, self).delete(*args, **kwargs)

        for ph in placeholders:
            ph.clear()
            ph.delete()

    content = PlaceholderField('activity_content')
Beispiel #5
0
class Question(models.Model):
    def composition():
        outline = {
            'findings': u'<p>Add Your Findings here<p><p>Identify Your Audience here<p>'
                        u'<p>Add Your Findings Description here<p><p>Add Your Conclusion and Recommendations here<p>',
                       }
        return outline

    # f_default = composition()
    # defaults = f_default.values()

    number = models.IntegerField(null=True, blank=True, help_text=(_('Use numbers <small>e.g</small> 1, 2 or 3')))
    question = models.CharField(max_length=128, null=True, blank=True)
    findings = RichTextField(null=True, blank=True,
                             default=composition()['findings'],
                             help_text=_(
                                 'Do not delete the tags <pre><code>&lt;p&gt; ... &lt;p&gt;</code></pre>'
                             ))
    image = models.ImageField(max_length=128000, null=True, blank=True, upload_to='media/project')
    project = models.ForeignKey('Project', on_delete=models.CASCADE, null=True, related_name='projects_question')
    add_findings_placeholder = PlaceholderField(slotname='add_findings')

    class Meta:
        permissions = (
            ('can_add_question', 'Can add Question'),
            ('can_edit_question', 'Can edit Question')
        )

    def __str__(self):
        return '{} for {}'.format(self.number, self.project)
Beispiel #6
0
class PostPlaceholderExtension(models.Model):
    post = models.OneToOneField(Post,
                                on_delete=models.CASCADE,
                                related_name="placeholder")
    some_placeholder = PlaceholderField("some_placeholder",
                                        related_name="some_placeholder")

    def delete(self):
        print("delete")
        super().delete()
Beispiel #7
0
class UserProfile(models.Model):
    '''
    '''
    user = models.OneToOneField(User)
    profile_content = PlaceholderField(profile_content,
                                       null=True,
                                       blank=True,
                                       help_text='Content Plugin')

    def __unicode__(self):
        return self.user.username
Beispiel #8
0
class CmsLesson(Lesson):
    lesson_content = PlaceholderField('lesson_content',
                                      related_name='lesson_content')
    support_content = PlaceholderField('support_content',
                                       related_name='support_content')
    show_common_content = models.BooleanField(
        default=True,
        help_text=
        _('Display content common for all lessons across course at the bottom of lesson content'
          ))

    class Meta:
        verbose_name = _('Lesson')
        verbose_name_plural = _('Lessons')

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):
        is_create = self.pk is None
        super().save(force_insert, force_update, using, update_fields)
        if is_create:
            cms.api.add_plugin(
                placeholder=self.lesson_content,
                plugin_type='PageTitleCMSPlugin',
                language='ru',
            )
            cms.api.add_plugin(
                placeholder=self.lesson_content,
                plugin_type='TextCMSPlugin',
                language='ru',
                body=f'<h2>В этом уроке:</h2>{self.brief}',
            )
            cms.api.add_plugin(
                placeholder=self.lesson_content,
                plugin_type='VideoYoutubeCMSPlugin',
                language='ru',
            )
class CMSPlaceholder(models.Model):
    """
    Model to hold content for placeholders on pages outside the CMS hierarchy.
    """
    cmscontent_placeholder = PlaceholderField('cmscontent_placeholder')
    page_identifier = models.CharField(max_length=255,
                                       choices=VALID_IDENTIFIER_CHOICES,
                                       unique=True)

    class Meta:
        ordering = ('page_identifier', )

    def __unicode__(self):
        return self.page_identifier
Beispiel #10
0
class PublisherItem(EditModeAndChangePermissionMixin,
                    PublisherParlerAutoSlugifyModel):
    # TranslatedAutoSlugifyMixin options
    slug_source_field_name = "text"

    translations = TranslatedFields(
        text=models.CharField(max_length=255),
        slug=models.SlugField(max_length=255, db_index=True, blank=True),
    )
    content = PlaceholderField(slotname="item_content")

    #--------------------------------------------------------------------------

    def get_absolute_url(self, language=None):
        language = language or self.get_current_language()
        slug = self.safe_translation_getter('slug', language_code=language)

        with force_language(language):
            if not slug:
                return reverse('%s:publisher-list' %
                               constants.LIST_APPHOOK_NAMESPACE)
            else:
                return reverse(
                    '%s:publisher-detail' % constants.LIST_APPHOOK_NAMESPACE,
                    kwargs={"slug": slug},
                )

    def __str__(self):
        """
        str() used in relation choice fields, wo we used the
        published fields, if available
        """
        if self.publisher_linked is None:
            obj = self
        else:
            obj = self.publisher_linked

        text = obj.safe_translation_getter(field="text",
                                           any_language=True) or "none"

        if self.publisher_is_draft:
            info = "draft,"
            if self.publisher_linked is None:
                info += "not published"
            else:
                info += "is published"
        else:
            info = "published"

        return "%s (pk:%r, %s)" % (text, self.pk, info)
class Post(models.Model):

    title = models.CharField(
        _('Title'), max_length=255, help_text=_('The post title.'))
    slug = models.SlugField(
        _('slug'), max_length=255, unique=True,
        help_text=_('The name (slug) for the post, used in URLs.'))
    excerpt = models.TextField(_('Excerpt'), blank=True)
    featured_image = FilerImageField(
        verbose_name=_('Featured Image'), blank=True, null=True,
        help_text=_('Featured image for this post'),
        related_name='blog_post_featured_images')

    content = PlaceholderField(
        'post content', related_name='post_content', help_text=_('The post content.'))

    author = models.ForeignKey(
        settings.AUTH_USER_MODEL, verbose_name=_('Author'), related_name='posts',
        help_text=_('The author of the post.'))

    creation_date = models.DateTimeField(
        auto_now_add=True, help_text=_('The post\'s creation time.'))

    publication_date = models.DateTimeField(
        _('Publication date'), default=timezone.now, db_index=True,
        help_text=_('Used in the URL. If changed, the URL will change.'))

    class Meta:
        ordering = ('-publication_date',)
        get_latest_by = 'publication_date'

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        kwargs = {
            'year': self.publication_date.year,
            'month': self.publication_date.month,
            'day': self.publication_date.day,
            'slug': self.slug
        }
        return reverse('blog:post_detail', kwargs=kwargs)
Beispiel #12
0
class Post(ModelMeta, TranslatableModel):
    """
    Blog post
    """
    author = models.ForeignKey(dj_settings.AUTH_USER_MODEL,
                               verbose_name=_('Author'), null=True, blank=True,
                               related_name='djangocms_blog_post_author')

    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    date_published = models.DateTimeField(_('Published Since'),
                                          default=timezone.now)
    date_published_end = models.DateTimeField(_('Published Until'), null=True,
                                              blank=True)
    publish = models.BooleanField(_('Publish'), default=False)
    categories = models.ManyToManyField(BlogCategory, verbose_name=_('category'),
                                        related_name='blog_posts',)
    main_image = FilerImageField(verbose_name=_('Main image'), blank=True, null=True,
                                 related_name='djangocms_blog_post_image')
    main_image_thumbnail = models.ForeignKey(ThumbnailOption,
                                             verbose_name=_('Main image thumbnail'),
                                             related_name='djangocms_blog_post_thumbnail',
                                             blank=True, null=True)
    main_image_full = models.ForeignKey(ThumbnailOption,
                                        verbose_name=_('Main image full'),
                                        related_name='djangocms_blog_post_full',
                                        blank=True, null=True)
    enable_comments = models.BooleanField(
        verbose_name=_(u'Enable comments on post'),
        default=settings.BLOG_ENABLE_COMMENTS
    )

    translations = TranslatedFields(
        title=models.CharField(_('Title'), max_length=255),
        slug=models.SlugField(_('slug'), blank=True, db_index=True),
        abstract=HTMLField(_('Abstract')),
        meta_description=models.TextField(verbose_name=_(u'Post meta description'),
                                          blank=True, default=''),
        meta_keywords=models.TextField(verbose_name=_(u'Post meta keywords'),
                                       blank=True, default=''),
        meta_title=models.CharField(verbose_name=_(u'Post meta title'),
                                    help_text=_(u'used in title tag and social sharing'),
                                    max_length=255,
                                    blank=True, default=''),
        post_text=HTMLField(_('Text'), default='', blank=True),
        meta={'unique_together': (('language_code', 'slug'),)}
    )
    content = PlaceholderField('post_content')

    objects = GenericDateTaggedManager()
    tags = TaggableManager(blank=True, related_name='djangocms_blog_tags')

    _metadata = {
        'title': 'get_title',
        'description': 'get_description',
        'og_description': 'get_description',
        'twitter_description': 'get_description',
        'gplus_description': 'get_description',
        'keywords': 'get_keywords',
        'locale': None,
        'image': 'get_image_full_url',
        'object_type': settings.BLOG_TYPE,
        'og_type': settings.BLOG_FB_TYPE,
        'og_app_id': settings.BLOG_FB_APPID,
        'og_profile_id': settings.BLOG_FB_PROFILE_ID,
        'og_publisher': settings.BLOG_FB_PUBLISHER,
        'og_author_url': settings.BLOG_FB_AUTHOR_URL,
        'twitter_type': settings.BLOG_TWITTER_TYPE,
        'twitter_site': settings.BLOG_TWITTER_SITE,
        'twitter_author': settings.BLOG_TWITTER_AUTHOR,
        'gplus_type': settings.BLOG_GPLUS_TYPE,
        'gplus_author': settings.BLOG_GPLUS_AUTHOR,
        'published_time': 'date_published',
        'modified_time': 'date_modified',
        'expiration_time': 'date_published_end',
        'tag': 'get_tags',
        'url': 'get_absolute_url',
    }

    def get_title(self):
        title = self.safe_translation_getter('meta_title', any_language=True)
        if not title:
            title = self.safe_translation_getter('title', any_language=True)
        return title.strip()

    def get_keywords(self):
        return self.safe_translation_getter('meta_keywords').strip().split(',')

    def get_description(self):
        description = self.safe_translation_getter('meta_description', any_language=True)
        if not description:
            description = self.safe_translation_getter('abstract', any_language=True)
        return description.strip()

    def get_image_full_url(self):
        if self.main_image:
            return self.make_full_url(self.main_image.url)
        return ''

    def get_tags(self):
        taglist = [tag.name for tag in self.tags.all()]
        return ','.join(taglist)

    def get_author(self):
        return self.author

    class Meta:
        verbose_name = _('blog article')
        verbose_name_plural = _('blog articles')
        ordering = ('-date_published', '-date_created')
        get_latest_by = 'date_published'

    def __unicode__(self):
        return self.safe_translation_getter('title')

    def save(self, *args, **kwargs):
        super(Post, self).save(*args, **kwargs)
        for lang in self.get_available_languages():
            self.set_current_language(lang)
            if not self.slug and self.title:
                self.slug = slugify(self.title)
        self.save_translations()

    def get_absolute_url(self):
        kwargs = {'year': self.date_published.year,
                  'month': self.date_published.month,
                  'day': self.date_published.day,
                  'slug': self.safe_translation_getter('slug', any_language=True)}
        return reverse('djangocms_blog:post-detail', kwargs=kwargs)

    def thumbnail_options(self):
        if self.main_image_thumbnail_id:
            return self.main_image_thumbnail.as_dict
        else:
            return settings.BLOG_IMAGE_THUMBNAIL_SIZE

    def full_image_options(self):
        if self.main_image_full_id:
            return self.main_image_full.as_dict
        else:
            return settings.BLOG_IMAGE_FULL_SIZE

    def get_full_url(self):
        return self.make_full_url(self.get_absolute_url())
Beispiel #13
0
class CaseStudy(models.Model):
    REGIONS = (
        ('americas', 'The Americas and Caribbean'),
        ('europe-asia-c', 'Europe and Central Asia'),
        ('pacific-asia-e', 'East Asia and the Pacific'),
        ('africa-e-s', 'Eastern and Southern Africa'),
        ('middle-east-africa', 'Middle East and North Africa'),
        ('asia-s', 'South Asia'),
        ('africa-w-c', 'West and Central Africa'),
    )
    region = models.CharField(max_length=20, choices=REGIONS)
    countries = CountryField(multiple=True)
    heading = models.CharField(max_length=128)
    slug = AutoSlugField(populate_from='heading', unique=True, max_length=128)
    featured_image = FilerImageField(verbose_name='Featured Image',
                                     blank=True,
                                     null=True,
                                     related_name='+',
                                     on_delete=models.SET_NULL)

    lead_content = PlaceholderField(slotname='case_study_lead_content',
                                    related_name='lead_case_study',
                                    verbose_name='Case Study Lead Content')
    main_content = PlaceholderField(slotname='case_study_main_content',
                                    related_name='main_case_study',
                                    verbose_name='Case Study Main Content')
    stats_content = PlaceholderField(slotname='case_study_stats_content',
                                     related_name='stats_case_study',
                                     verbose_name='Case Study Stats Content')
    sidebar_content = PlaceholderField(
        slotname='case_study_sidebar_content',
        related_name='sidebar_case_study',
        verbose_name='Case Study Sidebar Content')

    published = models.BooleanField(
        'Published',
        default=False,
        help_text='Indicates if this Case Study is pubilc or still a draft.')

    last_modified = models.DateTimeField(auto_now=True)

    use_cases = models.ManyToManyField(Page, limit_choices_to=use_case_choices)

    class Meta:
        verbose_name_plural = 'Case Studies'

    def __str__(self):
        return self.heading

    def get_absolute_url(self):
        """
        Absolute URL for this object. Expects a given Application name
        to reverse the URL to the correct location.
        """

        return reverse('case_studies:detail', kwargs={'slug': self.slug})

    def get_cms_change_url(self):
        return '{}?edit'.format(self.get_absolute_url())

    def similar(self, count=4, only_published=True):
        qs = CaseStudy.objects.exclude(pk=self.pk)
        if only_published:
            qs = qs.filter(published=True)
        qs = qs
        similar_cases = list(
            qs.filter(
                use_cases__in=self.use_cases.all()).order_by().distinct())
        if len(similar_cases) > count:
            similar_cases = random.sample(similar_cases, count)
        else:
            random.shuffle(similar_cases)
        print(similar_cases)
        remaining = count - len(similar_cases)
        if remaining > 0:
            similar_cases.extend(
                list(
                    qs.exclude(pk__in=[case.pk for case in similar_cases
                                       ]).order_by('?')[:remaining]))
        return similar_cases
Beispiel #14
0
class SellerProfileInstructionsPlaceholder(models.Model):
    """Django CMS placeholder for use in seller profile to add cms content."""
    seller_profile_instructions = PlaceholderField(
        slotname='seller_profile_instructions',
        related_name='seller_profile_instructions')
Beispiel #15
0
class Module(CreationTrackingBaseModel):
    objects = IterativeDeletion_Manager()

    class Meta:
        app_label = 'core'
        ordering = ('name',)
        verbose_name_plural = 'Modules'

    # path to the core module view
    def absolute_url(self):
        return reverse('core:module_detail', kwargs={
            'slug': self.slug,
        })

    # path to the manage page for a module
    def manage_url(self):
        return reverse('manage:module_content', kwargs={
            'slug': self.slug,
        })

    # path to the viewer 'module' page for a module
    def viewer_url(self):
        return reverse('modules:module_detail', kwargs={
            'slug': self.slug,
        })

    # path to the viewer 'module' page for a module
    def reference_url(self):
        return reverse('modules:module_ref', kwargs={
            'ref_id': self.ref_id,
        })

    # added for wizard support. potentially this can be used to redirect between core/manage/module
    def get_absolute_url(self):
        return self.absolute_url()

    def __unicode__(self):
        return self.name

    # needed to show the name in the admin interface (otherwise will show 'Module Object' for all entries)
    def __str__(self):
        return self.name

    def copy_relations(self, oldinstance):
        # Before copying related objects from the old instance, the ones
        # on the current one need to be deleted. Otherwise, duplicates may
        # appear on the public version of the page
        self.topic_item.all().delete()

        for topic_item in oldinstance.topic_item.all():
            # instance.pk = None; instance.pk.save() is the slightly odd but
            # standard Django way of copying a saved model instance
            topic_item.pk = None
            topic_item.plugin = self
            topic_item.save()

    def delete(self, *args, **kwargs):
        print("----- in module overridden delete")
        # self.cleanup_placeholders()
        placeholders = [self.intro]

        # get all child Topics and delete them
        # Topic.objects.filter(module=self).delete()

        self.topics.delete()

        super(Module, self).delete(*args, **kwargs)

        for ph in placeholders:
            ph.clear()
            ph.delete()

    name = models.CharField(u'Module Name',
                            blank=False,
                            default='',
                            help_text=u'Please enter a name for this module',
                            max_length=250,
                            unique=True,
                            )

    ref_id = RandomCharField(unique=True,
                             length=8,
                             include_punctuation=False,
                             )

    slug = AutoSlugField(u'slug',
                         blank=False,
                         default='',
                         max_length=64,
                         unique=True,
                         # populate_from=('name',),
                         populate_from=('ref_id',),
                         help_text=u'Please enter a unique slug for this module (can autogenerate from name field)',
                         )

    # shared_with = models.ManyToManyField(Person, through='ShareMapping')

    tags = TaggableManager(blank=True)

    intro = PlaceholderField('module_intro')
Beispiel #16
0
class Lesson(CreationTrackingBaseModel):
    objects = IterativeDeletion_Manager()

    class Meta:
        app_label = 'core'
        unique_together = ('topic', 'name')  # enforce only unique topic names within a module
        ordering = ('position',)
        verbose_name_plural = 'Lessons'

    def absolute_url(self):
        return reverse('core:lesson_detail', kwargs={
            'module_slug': self.topic.module.slug,
            'topic_slug': self.topic.slug,
            'slug': self.slug
        })

    # path to the manage page for a topic
    def manage_url(self):
        return reverse('manage:lesson_content', kwargs={
            'module_slug': self.topic.module.slug,
            'topic_slug': self.topic.slug,
            'slug': self.slug
        })

    # path to the viewer page for a topic
    def viewer_url(self):
        return reverse('modules:lesson_detail', kwargs={
            'module_slug': self.topic.module.slug,
            'topic_slug': self.topic.slug,
            'slug': self.slug
        })

    def __unicode__(self):
        return self.name

    # needed to show the name in the admin interface (otherwise will show 'Module Object' for all entries)
    def __str__(self):
        return "%s:%s:%s" % (self.topic.module.name, self.topic.name, self.name)

    def copy_relations(self, oldinstance):
        # Before copying related objects from the old instance, the ones
        # on the current one need to be deleted. Otherwise, duplicates may
        # appear on the public version of the page
        self.section_item.all().delete()

        for section_item in oldinstance.section_item.all():
            # instance.pk = None; instance.pk.save() is the slightly odd but
            # standard Django way of copying a saved model instance
            section_item.pk = None
            section_item.plugin = self
            section_item.save()

    def delete(self, *args, **kwargs):
        print("----- in Lesson overridden delete")
        # self.cleanup_placeholders()
        placeholders = [self.summary]

        self.sections.delete()

        super(Lesson, self).delete(*args, **kwargs)

        for ph in placeholders:
            ph.clear()
            ph.delete()

    topic = models.ForeignKey('core.Topic',
                              related_name="lessons",
                              blank=False,
                              default=None,
                              help_text=u'Please specify the Topic for this Lesson.',
                              null=False,
                              on_delete=models.CASCADE,
                              )

    parent = 'topic'

    # position = models.PositiveIntegerField(default=0, editable=False, db_index=True)
    position = models.PositiveIntegerField(default=0, blank=False, null=False)

    ref_id = RandomCharField(unique=True,
                             length=8,
                             include_punctuation=False,
                             )

    name = models.CharField(u'Lesson Name',
                            blank=False,
                            default='',
                            help_text=u'Please enter a name for this Lesson',
                            max_length=250,
                            unique=False,
                            )

    short_name = models.CharField(u'Lesson Short Name',
                                  blank=True,
                                  default='',
                                  help_text=u'(OPTIONAL) A shortened version of this lesson\'s name for use in lesson listings',
                                  max_length=250,
                                  unique=False,
                                  )

    slug = AutoSlugField(u'slug',
                         blank=False,
                         default='',
                         max_length=64,
                         unique=True,
                         # populate_from=('name',),
                         populate_from=('ref_id',),
                         help_text=u'Please enter a unique slug for this Lesson (can autogenerate from name field)',
                         )

    tags = TaggableManager(blank=True)

    summary = PlaceholderField('lesson_summary')
Beispiel #17
0
class Post(TranslatableModel):
    """
    Blog post
    """
    author = models.ForeignKey(User, verbose_name=_('Author'), null=True, blank=True)

    date_created = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    date_published = models.DateTimeField(_('Published Since'),
                                          default=timezone.now)
    date_published_end = models.DateTimeField(_('Published Until'), null=True,
                                              blank=True)
    publish = models.BooleanField(_('Publish'), default=False)
    categories = models.ManyToManyField(BlogCategory, verbose_name=_('category'),
                                        related_name='blog_posts',)
    main_image = FilerImageField(verbose_name=_('Main image'), blank=True, null=True)
    main_image_thumbnail = models.ForeignKey(ThumbnailOption,
                                             verbose_name=_('Main image thumbnail'),
                                             related_name='blog_post_thumbnail',
                                             blank=True, null=True)
    main_image_full = models.ForeignKey(ThumbnailOption,
                                        verbose_name=_('Main image full'),
                                        related_name='blog_post_full',
                                        blank=True, null=True)

    translations = TranslatedFields(
        title=models.CharField(_('Title'), max_length=255),
        slug=models.SlugField(_('slug'), blank=True, db_index=True),
        abstract=HTMLField(_('Text')),
        meta={'unique_together': (('language_code', 'slug'),)}
    )
    content = PlaceholderField("post_content")

    objects = GenericDateTaggedManager()
    tags = TaggableManager(blank=True)

    class Meta:
        verbose_name = _('blog article')
        verbose_name_plural = _('blog articles')
        ordering = ("-date_published", "-date_created")

    def __unicode__(self):
        return self.safe_translation_getter('title')

    def save(self, *args, **kwargs):
        super(Post, self).save(*args, **kwargs)
        for lang in self.get_available_languages():
            self.set_current_language(lang)
            if not self.slug and self.title:
                self.slug = slugify(self.title)
        self.save_translations()

    def get_absolute_url(self):
        kwargs = {'year': self.date_published.year,
                  'month': self.date_published.month,
                  'day': self.date_published.day,
                  'slug': self.slug}
        return reverse('djangocms_blog:post-detail', kwargs=kwargs)

    def thumbnail_options(self):
        if self.main_image_thumbnail_id:
            return self.main_image_thumbnail.as_dict
        else:
            return settings.BLOG_IMAGE_THUMBNAIL_SIZE
        
    def get_full_url(self):
        s = Site.objects.get_current()
        if s.domain.find('http') > -1:
            return "%s%s" % (s.domain, self.get_absolute_url())
        else:
            return "http://%s%s" % (s.domain, self.get_absolute_url())

    def full_image_options(self):
        if self.main_image_fulll_id:
            return self.main_image_full.as_dict
        else:
            return settings.BLOG_IMAGE_FULL_SIZE
Beispiel #18
0
class Lesson(Publication):

    # TODO: if needed for publishable, can inherit parent's meta
    #       class Meta(Publishable.Meta):
    class Meta:
        app_label = 'core'
        #unique_together = ('parent_lesson', 'name')  # enforce only unique topic names within a module
        #ordering = ('name',)
        ordering = ('position', )
        verbose_name_plural = 'Lessons'

    ########################################
    #   Fields
    ########################################

    # boolean field representing if a lesson is (soft) deleted
    #   TODO: this has not been factored into the system yet, implementation will require revision of delete method
    is_deleted = models.BooleanField(default=False)

    # the reference id for a lesson (used in slug generation)
    #   this reference id will be maintained for all copies of this lesson
    ref_id = models.UUIDField(default=uuid.uuid4, editable=False)

    # marks the parent lesson for a lesson
    #       this field will be auto-populated by the generated forms
    #       it from the dynamic interface
    parent_lesson = models.ForeignKey(
        'self',
        related_name="sub_lessons",
        blank=True,
        default=None,
        help_text=u'Specify a Parent Lesson for this Sub-Lesson.',
        null=True,
        on_delete=models.CASCADE,
    )

    # Being that lessons will be clonable
    #   maintain a linkage to the lesson copied from
    #   used for giving credit to original creator
    # derived_from_lesson = models.ForeignKey('self',
    #                           related_name="derivations",
    #                           blank=True,
    #                           default=None,
    #                           help_text=u'Lesson this lesson was copied from.',
    #                           null=True,
    #                           on_delete=models.SET_NULL,
    #                           )

    # position amongst siblings, siblings can be of type Lessons or Sections
    position = models.PositiveIntegerField(default=0, blank=False, null=False)

    #   zero based depth level of lesson
    #       exclusively set by backend
    depth = models.PositiveIntegerField(default=0, blank=False, null=False)

    # depth Identifier
    #   exclusively set by backend
    depth_label = models.CharField(
        u'Depth Label',
        blank=False,
        default='Module',
        help_text=u'The depth-level label for this lesson',
        max_length=10,
        unique=False,
    )

    name = models.CharField(
        u'Lesson Name',
        blank=False,
        default='',
        help_text=u'Please enter a name for this Lesson',
        max_length=250,
        unique=False,
    )

    short_name = models.CharField(
        u'Lesson Short Name',
        blank=True,
        default='',
        help_text=
        u'(OPTIONAL) A shortened version of this lesson\'s name for use in lesson listings',
        max_length=250,
        unique=False,
    )

    slug = AutoSlugField(
        u'slug',
        blank=False,
        default='',
        max_length=8,
        unique=True,
        populate_from=('ref_id', ),
        help_text=
        u'Please enter a unique slug for this Lesson (can autogenerate from name field)',
    )

    tags = TaggableManager(blank=True)

    # many to many relationship for collaborators
    # allowed to make edits to the draft of a publication
    collaborators = models.ManyToManyField(User,
                                           related_name="collaborations",
                                           through='Collaboration')

    # the content of this lesson
    summary = PlaceholderField('lesson_summary')

    ########################################
    # Cloning references
    ########################################

    # the date this lesson was cloned from a published lesson
    derived_date = models.DateTimeField(null=True)

    # the published lesson this lesson was derived from's ref_id
    derived_lesson_slug = models.CharField(null=True,
                                           default=None,
                                           editable=False,
                                           max_length=8)

    # the user that created the lesson this was derived from
    derived_lesson_creator = models.ForeignKey(User,
                                               null=True,
                                               blank=True,
                                               related_name='inspired_lessons')

    #   the default related name for this many-to-many field is lesson_set
    #
    # learning_objectives = models.ManyToManyField('core.LearningObjective')

    #   the default related name for this many-to-many field is lesson_set
    #       these will potentially be polymorphic to account for different
    #       resource types potentially needing different attributes
    #
    # resources = models.ManyToManyField('core.Resource')

    # TODO: potentially add 1-to-1 relationship to a publishable (instead of direct inheritance)
    #           this will allow for a lesson to be a child and root
    #           e.g. root.publishable = [publishable object], child.publishable = None
    #       ______________________________
    #       parent_link
    #           When True and used in a model which inherits from another
    #           concrete model, indicates that this field should be used as
    #           the link back to the parent class, rather than the extra
    #           OneToOneField which would normally be implicitly created
    #           by subclassing.
    #
    # publishable = models.OneToOneField('core.Publishable', default=None, on_delete=modeld.SET_NULL, parent_link=True)

    def __str__(self):
        return self.name

    ########################################
    #   URL Methods
    ########################################

    # define for use by FormMixin
    # (calls this method specifically, but isn't defined by default... right...)
    def get_absolute_url(self):
        return self.absolute_url()

    def absolute_url(self):
        return reverse('core:lesson_detail', kwargs={'slug': self.slug})

    # path to the manage page for a topic
    def manage_url(self):
        return reverse('manage:lesson_content', kwargs={'slug': self.slug})

    # path to the edit page for a topic
    def edit_url(self):
        return reverse('editor:lesson_edit', kwargs={'slug': self.slug})

    # path to the viewer page for a topic
    def viewer_url(self):
        return reverse('modules:lesson_detail', kwargs={'slug': self.slug})

    # path to the viewer 'module' page for a module
    def reference_url(self):
        return reverse('modules:module_ref', kwargs={
            'ref_id': self.ref_id,
        })

    ########################################
    #   Query Methods/properties
    ########################################

    # TODO: Watch for this, as formsets may not access this with update
    def save(self, **kwargs):
        # print('---- in custom lesson save')
        # set depth level on save
        if self.parent_lesson:
            self.depth = self.parent_lesson.depth + 1
        else:
            self.depth = 0

        # TODO: this needs to be flipped
        # based on depth level set the depth label
        self.depth_label = {
            0: 'Module',
            1: 'Topic',
            2: 'Lesson',
        }.get(self.depth, "INVALID")

        super(Lesson, self).save(**kwargs)

    def delete(self, *args, **kwargs):

        # self.cleanup_placeholders()
        placeholders = [self.summary]

        self.sections.delete()
        self.sub_lessons.delete()

        super(Lesson, self).delete(*args, **kwargs)

        for ph in placeholders:
            ph.clear()
            ph.delete()

    def validate_unique(self, exclude=None):
        # add a conditional unique constraint to prevent
        #   creation of multiple drafts with the same name
        #   this is only valid if a base lesson so check that it's not a root lesson too
        #   TODO: watch this, it could be inadequate when 'lesson-copy' becomes enabled later in development
        #           if not self.parent_lesson and self.is_draft and Lesson.objects.exclude(pk=self.pk).filter(name=self.name, is_draft=True).exists():
        #               raise ValidationError('A Draft-Lesson with this name already exists')

        return super(Lesson, self).validate_unique(exclude)

    @property
    def total_depth(self):
        '''
            method to return the total depth of this lesson's structure
            (the max level of nested children)
        :return: integer representation of child depth
        '''

        if self.sub_lessons:

            max_depth = 0
            for sub_lesson in self.sub_lessons.all():
                max_depth = max(max_depth, sub_lesson.total_depth)

            return max_depth + 1
        else:
            return 1

    @property
    def num_children(self):
        return self.num_sections + self.num_sub_lessons

    @property
    def num_sections(self):
        return self.sections.count()

    @property
    def num_sub_lessons(self):
        return self.sub_lessons.count()

    def derivation(self):
        '''
            Method to copy a published lesson instance and set
            derivation attributes to point to this lesson and it's creator

        :return: new lesson instance with attributes set to link to derived lesson
        '''

        derivation = self.copy()
        derivation.derived_date = now()
        derivation.derived_lesson_slug = self.slug
        derivation.derived_lesson_creator = self.created_by

        return derivation

    def derive_children_from(self, from_lesson):
        self.sections.delete()
        self.sub_lessons.delete()

        for section_item in from_lesson.sections.all():
            # copy the section items and set their linked lesson to this new instance
            new_section = section_item.copy()

            new_section.lesson = self
            new_section.position = section_item.position

            # save the copied section instance
            new_section.save()
            new_section.copy_content(section_item)
            new_section.copy_children(section_item)

        for sub_lesson in from_lesson.sub_lessons.all():
            # copy the sub-lesson items and set their linked parent_lesson to this new instance
            new_lesson = sub_lesson.derivation()

            new_lesson.parent_lesson = self
            new_lesson.position = sub_lesson.position

            # save the copied sub-lesson instance
            new_lesson.save()
            new_lesson.copy_content(sub_lesson)
            new_lesson.derive_children_from(sub_lesson)

    ########################################
    #   Publication Method overrides
    ########################################

    def copy(self, maintain_ref=False):
        '''
            generate a new (unsaved) lesson instance based on this lesson, with a fresh ref_id if specified.

            Notes:
                The newly generated instance:
                    - removes reference to parent
                    - marks 'position' as 0
                    - and sets 'is_deleted' to False

                Additionally, this method does not copy placeholder(content), tags, collaborators, or
                child-objects (use copy_content (or copy_children for children) after save to do this)


        :return: a new (unsaved) copy of this lesson
        '''

        new_instance = Lesson(
            parent_lesson=None,
            position=0,
            is_deleted=False,
            name=self.name,
            short_name=self.short_name,
        )

        # if specified, mark this new instance as the same lesson
        # typically only used in publication methods
        if maintain_ref:
            new_instance.ref_id = self.ref_id

        if self.derived_date:
            new_instance.derived_date = self.derived_date
            new_instance.derived_lesson_slug = self.derived_lesson_slug
            new_instance.derived_lesson_creator = self.derived_lesson_creator

        return new_instance

    def copy_children(self, from_instance, maintain_ref=False):
        '''
            Copy child relations (sub_lessons/sections) from a passed lesson, with the option of specifying
            if the ref_id should be maintained. this should only happen during publishing.

        :param from_instance: Lesson instance from which the child relations are provided.
        :param maintain_ref: Boolean representing if the ref_id should be maintained on the child objects, this should only be true in the case of publication.

        :return: None
        '''
        # copy over the content
        #self.copy_content(from_instance)

        # Before copying related objects from the old instance, the ones
        # on the current one need to be deleted. Otherwise, duplicates may
        # appear on the public version of the page
        self.sections.delete()
        self.sub_lessons.delete()
        #self.app_refs.delete()

        for section_item in from_instance.sections.all():
            # copy the section items and set their linked lesson to this new instance
            new_section = section_item.copy(maintain_ref)

            new_section.lesson = self
            new_section.position = section_item.position

            # save the copied section instance
            new_section.save()
            new_section.copy_content(section_item)
            new_section.copy_children(section_item, maintain_ref)

        for sub_lesson in from_instance.sub_lessons.all():
            # copy the sub-lesson items and set their linked parent_lesson to this new instance
            new_lesson = sub_lesson.copy(maintain_ref)

            new_lesson.parent_lesson = self
            new_lesson.position = sub_lesson.position

            # save the copied sub-lesson instance
            new_lesson.save()
            new_lesson.copy_content(sub_lesson)
            new_lesson.copy_children(sub_lesson, maintain_ref)

        for app_ref in from_instance.app_refs.all():
            new_ref = AppReference(
                app_name=app_ref.app_name,
                app_link=app_ref.app_link,
                lesson=self,
            )
            new_ref.save()

        for learning_obj in from_instance.learning_objectives.all():
            new_lo = Learning_Objective(
                lesson=self,
                condition=learning_obj.condition,
                task=learning_obj.task,
                degree=learning_obj.degree,
                verb=learning_obj.verb,
            )

            new_lo.save()

            for outcome in learning_obj.outcomes.all():
                new_lo.outcomes.add(outcome)

    def copy_content(self, from_instance):
        '''
            copy content including tags, and placeholder plugins to this instance from a passed Lesson

        :param from_instance: a Lesson object the content/tags are being copied from
        :return: None
        '''

        # add any tags from the 'from_instance'
        self.tags.add(*list(from_instance.tags.names()))

        # clear any existing plugins
        self.summary.clear()

        # get the list of plugins in the 'from_instance's intro
        plugins = from_instance.summary.get_plugins_list()

        # copy 'from_instance's intro plugins to this object's intro
        copy_plugins_to(plugins, self.summary, no_signals=True)

    def get_Publishable_parent(self):

        # return self.topic.module
        # if this isn't the parent lesson traverse up until root is reached.
        if self.parent_lesson:
            return self.parent_lesson.get_Publishable_parent()
        else:
            return self

    @property
    def is_dirty(self):

        # if this is the root lesson
        if not self.parent_lesson:

            # if this root lesson is not published, return dirty
            #if not self.is_published(): return True

            # TODO: need to check if this is the draft copy or not

            # if this is the draft instance, and not published return true
            if self.publish_status == Publication.DRAFT_ONLY:
                return True

            # get the publication date to check against

            pub_date = None

            if self.publish_status == Publication.PUBLISHED:
                # if this is a published draft-copy
                pub_date = self.published_copy.published_date
            else:
                # if this is the current publication
                pub_date = self.published_date

            # if this is a published copy
            result = any([
                super(Lesson, self).is_dirty,
                self.summary.cmsplugin_set.filter(
                    changed_date__gt=pub_date).exists(),
            ])

            if result:
                return result

            # if this lesson is clean, check it's children
            for t in self.sub_lessons.all():
                if t.is_dirty:
                    return True

            for t in self.sections.all():
                if t.is_dirty:
                    return True

        else:
            # if this lesson is a child lesson, check if it's root lesson has
            # a published copy, if not mark dirty
            parent_publication = self.get_Publishable_parent()

            if parent_publication.publish_status == Publication.DRAFT_ONLY:
                return True

            pub_date = None
            if parent_publication.publish_status == Publication.PUBLISHED:
                # if this is a published draft-copy
                pub_date = parent_publication.published_copy.published_date
            else:
                # if this is the current publication
                pub_date = parent_publication.published_date

            # otherwise, check that this lesson has no plugins saved
            #   after the publication date
            result = any([
                #super(Lesson, self).is_dirty,
                self.changed_date > pub_date,
                self.summary.cmsplugin_set.filter(
                    changed_date__gt=pub_date).exists(),
            ])

            if result:
                return result

            # if not check children
            for t in self.sub_lessons.all():
                if t.is_dirty:
                    return True

            for t in self.sections.all():
                if t.is_dirty:
                    return True

        return False

    def has_draft_access(self, user):

        # if passes the default permission check (owner/admin) return true
        if (super(Lesson, self).has_draft_access(user)):
            return True
        else:
            # else check if the current user is a collaborator for this lesson
            # or is a collaborator on the root object

            access_conditions = [
                self.collaborators.filter(pk=user.pk).exists(),
                self.get_Publishable_parent().collaborators.filter(
                    pk=user.pk).exists(),
            ]

            return any(access_conditions)

    def has_edit_access(self, user):

        # user can edit if they are the owner or have been marked as a collaborator with
        # edit access on either this lesson or the parent publication
        access_conditions = [
            self.get_owner() == user,
            Collaboration.objects.filter(publication=self,
                                         collaborator=user,
                                         can_edit=True).exists(),
            Collaboration.objects.filter(
                publication=self.get_Publishable_parent(),
                collaborator=user,
                can_edit=True).exists(),
        ]

        return any(access_conditions)

    def get_owner(self):
        '''
            get the owner of the lesson (created-by), if this is a child lesson
            return the owner of it's parent
        :return: user who created the root lesson
        '''
        if self.parent_lesson:
            return self.parent_lesson.get_Publishable_parent().get_owner()
        else:
            return self.created_by
Beispiel #19
0
class Article(PolymorphicModel):
    namespace = models.CharField(_('Application instance'), max_length=200)
    title = models.CharField(_('Title'), max_length=250)
    slug = models.SlugField(_('Slug'),
                            max_length=250,
                            db_index=True,
                            unique=False)
    pub_date = models.DateField(_('Publication date'), editable=True)
    perex = HTMLField(_('Perex'), blank=True, default='')
    text = PlaceholderField('article_text')
    page_title = models.CharField(
        _('Page title'),
        max_length=250,
        blank=True,
        null=True,
        help_text=_('Overwrite the title (html title tag)'))
    menu_title = models.CharField(
        _('Menu title'),
        max_length=250,
        blank=True,
        null=True,
        help_text=_('Overwrite the title in the menu'))
    meta_desc = models.TextField(
        _('Meta description'),
        blank=True,
        default='',
        help_text=_('The text displayed in search engines.'))
    public = models.BooleanField(default=False, verbose_name=_('Public'))

    class Meta:
        ordering = ('-pub_date', )
        unique_together = [('pub_date', 'slug')]
        verbose_name = _('Article')
        verbose_name_plural = _('Articles')

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        errors = self._perform_unique_checks([(Article, ('pub_date', 'slug'))])
        if errors:
            raise ValidationError(errors)
        super(Article, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse(
            '{}:detail'.format(self.namespace),
            kwargs={
                'year': '{:%Y}'.format(self.pub_date),
                'month': '{:%m}'.format(self.pub_date),
                'day': '{:%d}'.format(self.pub_date),
                'slug': self.slug,
            },
        )

    def get_edit_url(self):
        return reverse('admin:{}_{}_change'.format(self._meta.app_label,
                                                   self._meta.model_name),
                       args=(self.id, ))

    def get_page(self):
        return Page.objects.get(application_namespace=self.namespace,
                                publisher_is_draft=False)

    def get_title(self):
        return self.title

    def get_page_title(self):
        return self.page_title or self.title

    def get_menu_title(self):
        return self.menu_title or self.title
class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
    """
    Blog post
    """
    author = models.ForeignKey(dj_settings.AUTH_USER_MODEL,
                               verbose_name=_('author'),
                               null=True,
                               blank=True,
                               related_name='djangocms_blog_post_author',
                               on_delete=models.PROTECT)

    date_created = models.DateTimeField(_('created'), auto_now_add=True)
    date_modified = models.DateTimeField(_('last modified'), auto_now=True)
    date_published = models.DateTimeField(_('published since'),
                                          null=True,
                                          blank=True)
    date_published_end = models.DateTimeField(_('published until'),
                                              null=True,
                                              blank=True)
    date_featured = models.DateTimeField(_('featured date'),
                                         null=True,
                                         blank=True)
    publish = models.BooleanField(_('publish'), default=False)
    categories = models.ManyToManyField('djangocms_blog.BlogCategory',
                                        verbose_name=_('category'),
                                        related_name='blog_posts',
                                        blank=True)
    main_image = FilerImageField(verbose_name=_('main image'),
                                 blank=True,
                                 null=True,
                                 on_delete=models.SET_NULL,
                                 related_name='djangocms_blog_post_image')
    main_image_thumbnail = models.ForeignKey(
        thumbnail_model,
        verbose_name=_('main image thumbnail'),
        related_name='djangocms_blog_post_thumbnail',
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    main_image_full = models.ForeignKey(
        thumbnail_model,
        verbose_name=_('main image full'),
        related_name='djangocms_blog_post_full',
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    enable_comments = models.BooleanField(
        verbose_name=_('enable comments on post'),
        default=get_setting('ENABLE_COMMENTS'))
    sites = models.ManyToManyField(
        'sites.Site',
        verbose_name=_('Site(s)'),
        blank=True,
        help_text=_('Select sites in which to show the post. '
                    'If none is set it will be '
                    'visible in all the configured sites.'))
    app_config = AppHookConfigField(BlogConfig,
                                    null=True,
                                    verbose_name=_('app.config'))

    translations = TranslatedFields(
        title=models.CharField(_('title'), max_length=752),
        slug=models.SlugField(_('slug'),
                              max_length=752,
                              blank=True,
                              db_index=True,
                              allow_unicode=True),
        subtitle=models.CharField(verbose_name=_('subtitle'),
                                  max_length=767,
                                  blank=True,
                                  default=''),
        abstract=HTMLField(_('abstract'),
                           blank=True,
                           default='',
                           configuration='BLOG_ABSTRACT_CKEDITOR'),
        meta_description=models.TextField(
            verbose_name=_('post meta description'), blank=True, default=''),
        meta_keywords=models.TextField(verbose_name=_('post meta keywords'),
                                       blank=True,
                                       default=''),
        meta_title=models.CharField(
            verbose_name=_('post meta title'),
            help_text=_('used in title tag and social sharing'),
            max_length=2000,
            blank=True,
            default=''),
        post_text=HTMLField(_('text'),
                            default='',
                            blank=True,
                            configuration='BLOG_POST_TEXT_CKEDITOR'),
        meta={'unique_together': (('language_code', 'slug'), )})
    media = PlaceholderField('media', related_name='media')
    content = PlaceholderField('post_content', related_name='post_content')
    liveblog = PlaceholderField('live_blog', related_name='live_blog')
    enable_liveblog = models.BooleanField(
        verbose_name=_('enable liveblog on post'), default=False)

    objects = GenericDateTaggedManager()
    tags = TaggableManager(blank=True, related_name='djangocms_blog_tags')

    related = SortedManyToManyField('self',
                                    verbose_name=_('Related Posts'),
                                    blank=True,
                                    symmetrical=False)

    amount = models.CharField(max_length=200,
                              default='R50',
                              choices=donations_amount)
    goal = models.CharField(max_length=200,
                            default='R30 000',
                            choices=donations_goal)

    _metadata = {
        'title': 'get_title',
        'description': 'get_description',
        'keywords': 'get_keywords',
        'og_description': 'get_description',
        'twitter_description': 'get_description',
        'gplus_description': 'get_description',
        'locale': 'get_locale',
        'image': 'get_image_full_url',
        'image_width': 'get_image_width',
        'image_height': 'get_image_height',
        'object_type': 'get_meta_attribute',
        'og_type': 'get_meta_attribute',
        'og_app_id': 'get_meta_attribute',
        'og_profile_id': 'get_meta_attribute',
        'og_publisher': 'get_meta_attribute',
        'og_author_url': 'get_meta_attribute',
        'og_author': 'get_meta_attribute',
        'twitter_type': 'get_meta_attribute',
        'twitter_site': 'get_meta_attribute',
        'twitter_author': 'get_meta_attribute',
        'gplus_type': 'get_meta_attribute',
        'gplus_author': 'get_meta_attribute',
        'published_time': 'date_published',
        'modified_time': 'date_modified',
        'expiration_time': 'date_published_end',
        'tag': 'get_tags',
        'url': 'get_absolute_url',
    }

    class Meta:
        verbose_name = _('blog article')
        verbose_name_plural = _('blog articles')
        ordering = ('-date_published', '-date_created')
        get_latest_by = 'date_published'

    def __str__(self):
        default = ugettext('Post (no translation)')
        return self.safe_translation_getter('title',
                                            any_language=True,
                                            default=default)

    @property
    def guid(self, language=None):
        if not language:
            language = self.get_current_language()
        base_string = '-{0}-{2}-{1}-'.format(
            language, self.app_config.namespace,
            self.safe_translation_getter('slug',
                                         language_code=language,
                                         any_language=True))
        return hashlib.sha256(force_bytes(base_string)).hexdigest()

    @property
    def date(self):
        if self.date_featured:
            return self.date_featured
        return self.date_published

    def save(self, *args, **kwargs):
        """
        Handle some auto configuration during save
        """
        if self.publish and self.date_published is None:
            self.date_published = timezone.now()
        if not self.slug and self.title:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

    def save_translation(self, translation, *args, **kwargs):
        """
        Handle some auto configuration during save
        """
        if not translation.slug and translation.title:
            translation.slug = slugify(translation.title)
        super(Post, self).save_translation(translation, *args, **kwargs)

    def get_absolute_url(self, lang=None):
        if not lang or lang not in self.get_available_languages():
            lang = get_language()
        if not lang or lang not in self.get_available_languages():
            lang = self.get_current_language()
        with switch_language(self, lang):
            category = self.categories.first()
            kwargs = {}
            if self.date_published:
                current_date = self.date_published
            else:
                current_date = self.date_created
            urlconf = get_setting('PERMALINK_URLS')[
                self.app_config.url_patterns]
            if '<year>' in urlconf:
                kwargs['year'] = current_date.year
            if '<month>' in urlconf:
                kwargs['month'] = '%02d' % current_date.month
            if '<day>' in urlconf:
                kwargs['day'] = '%02d' % current_date.day
            if '<slug>' in urlconf:
                kwargs['slug'] = self.safe_translation_getter(
                    'slug', language_code=lang, any_language=True)  # NOQA
            if '<category>' in urlconf:
                kwargs['category'] = category.safe_translation_getter(
                    'slug', language_code=lang, any_language=True)  # NOQA
            return reverse('%s:post-detail' % self.app_config.namespace,
                           kwargs=kwargs)

    def get_title(self):
        title = self.safe_translation_getter('meta_title', any_language=True)
        if not title:
            title = self.safe_translation_getter('title', any_language=True)
        return title.strip()

    def get_keywords(self):
        """
        Returns the list of keywords (as python list)
        :return: list
        """
        return self.safe_translation_getter('meta_keywords',
                                            default='').strip().split(',')

    def get_description(self):
        description = self.safe_translation_getter('meta_description',
                                                   any_language=True)
        if not description:
            description = self.safe_translation_getter('abstract',
                                                       any_language=True)
        return escape(strip_tags(description)).strip()

    def get_image_full_url(self):
        if self.main_image:
            return self.build_absolute_uri(self.main_image.url)
        return ''

    def get_image_width(self):
        if self.main_image:
            return self.main_image.width

    def get_image_height(self):
        if self.main_image:
            return self.main_image.height

    def get_tags(self):
        """
        Returns the list of object tags as comma separated list
        """
        taglist = [tag.name for tag in self.tags.all()]
        return ','.join(taglist)

    def get_author(self):
        """
        Return the author (user) objects
        """
        return self.author

    def _set_default_author(self, current_user):
        if not self.author_id and self.app_config.set_author:
            if get_setting('AUTHOR_DEFAULT') is True:
                user = current_user
            else:
                user = get_user_model().objects.get(
                    username=get_setting('AUTHOR_DEFAULT'))
            self.author = user

    def thumbnail_options(self):
        if self.main_image_thumbnail_id:
            return self.main_image_thumbnail.as_dict
        else:
            return get_setting('IMAGE_THUMBNAIL_SIZE')

    def full_image_options(self):
        if self.main_image_full_id:
            return self.main_image_full.as_dict
        else:
            return get_setting('IMAGE_FULL_SIZE')

    @property
    def is_published(self):
        """
        Checks wether the blog post is *really* published by checking publishing dates too
        """
        return (self.publish and
                (self.date_published and self.date_published <= timezone.now())
                and (self.date_published_end is None
                     or self.date_published_end > timezone.now()))

    def should_knock(self, signal_type, created=False):
        """
        Returns whether to emit knocks according to the post state
        """
        new = (self.app_config.send_knock_create and self.is_published
               and self.date_published == self.date_modified)
        updated = self.app_config.send_knock_update and self.is_published
        return (new or updated) and signal_type in ('post_save', 'post_delete')

    def get_cache_key(self, language, prefix):
        return 'djangocms-blog:{2}:{0}:{1}'.format(language, self.guid, prefix)

    @property
    def liveblog_group(self):
        return 'liveblog-{apphook}-{lang}-{post}'.format(
            lang=self.get_current_language(),
            apphook=self.app_config.namespace,
            post=self.safe_translation_getter('slug', any_language=True))

    def get_gallery_image(self):
        """
        Returns the best gallery image
        """
        from api.models import Gallery
        if self.id:
            gallery = Gallery.objects.filter(blog_post=self.id)
            if gallery:
                self.main_image = gallery[0].image
                self.save()
                return gallery[0].image
        return False
Beispiel #21
0
class Post(ModelMeta, TranslatableModel):
    """
    Blog post
    """
    author = models.ForeignKey(dj_settings.AUTH_USER_MODEL,
                               verbose_name=_('author'),
                               null=True,
                               blank=True,
                               related_name='djangocms_blog_post_author')

    date_created = models.DateTimeField(_('created'), auto_now_add=True)
    date_modified = models.DateTimeField(_('last modified'), auto_now=True)
    date_published = models.DateTimeField(_('published since'),
                                          default=timezone.now)
    date_published_end = models.DateTimeField(_('published until'),
                                              null=True,
                                              blank=True)
    publish = models.BooleanField(_('publish'), default=False)
    categories = models.ManyToManyField(
        'djangocms_blog.BlogCategory',
        verbose_name=_('category'),
        related_name='blog_posts',
    )
    main_image = FilerImageField(verbose_name=_('main image'),
                                 blank=True,
                                 null=True,
                                 on_delete=models.SET_NULL,
                                 related_name='djangocms_blog_post_image')
    main_image_thumbnail = models.ForeignKey(
        'cmsplugin_filer_image.ThumbnailOption',
        verbose_name=_('main image thumbnail'),
        related_name='djangocms_blog_post_thumbnail',
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    main_image_full = models.ForeignKey(
        'cmsplugin_filer_image.ThumbnailOption',
        verbose_name=_('main image full'),
        related_name='djangocms_blog_post_full',
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    enable_comments = models.BooleanField(
        verbose_name=_('enable comments on post'),
        default=get_setting('ENABLE_COMMENTS'))
    sites = models.ManyToManyField(
        'sites.Site',
        verbose_name=_('Site(s)'),
        blank=True,
        help_text=_('Select sites in which to show the post. '
                    'If none is set it will be '
                    'visible in all the configured sites.'))
    app_config = AppHookConfigField(BlogConfig,
                                    null=True,
                                    verbose_name=_('app. config'))

    translations = TranslatedFields(
        title=models.CharField(_('title'), max_length=255),
        slug=models.SlugField(_('slug'), blank=True, db_index=True),
        abstract=HTMLField(_('abstract'), blank=True, default=''),
        meta_description=models.TextField(
            verbose_name=_('post meta description'), blank=True, default=''),
        meta_keywords=models.TextField(verbose_name=_('post meta keywords'),
                                       blank=True,
                                       default=''),
        meta_title=models.CharField(
            verbose_name=_('post meta title'),
            help_text=_('used in title tag and social sharing'),
            max_length=255,
            blank=True,
            default=''),
        post_text=HTMLField(_('text'), default='', blank=True),
        meta={'unique_together': (('language_code', 'slug'), )})
    content = PlaceholderField('post_content', related_name='post_content')

    objects = GenericDateTaggedManager()
    tags = TaggableManager(blank=True, related_name='djangocms_blog_tags')

    _metadata = {
        'title': 'get_title',
        'description': 'get_description',
        'keywords': 'get_keywords',
        'og_description': 'get_description',
        'twitter_description': 'get_description',
        'gplus_description': 'get_description',
        'locale': 'get_locale',
        'image': 'get_image_full_url',
        'object_type': 'get_meta_attribute',
        'og_type': 'get_meta_attribute',
        'og_app_id': 'get_meta_attribute',
        'og_profile_id': 'get_meta_attribute',
        'og_publisher': 'get_meta_attribute',
        'og_author_url': 'get_meta_attribute',
        'og_author': 'get_meta_attribute',
        'twitter_type': 'get_meta_attribute',
        'twitter_site': 'get_meta_attribute',
        'twitter_author': 'get_meta_attribute',
        'gplus_type': 'get_meta_attribute',
        'gplus_author': 'get_meta_attribute',
        'published_time': 'date_published',
        'modified_time': 'date_modified',
        'expiration_time': 'date_published_end',
        'tag': 'get_tags',
        'url': 'get_absolute_url',
    }

    class Meta:
        verbose_name = _('blog article')
        verbose_name_plural = _('blog articles')
        ordering = ('-date_published', '-date_created')
        get_latest_by = 'date_published'

    def __str__(self):
        return self.safe_translation_getter('title')

    def get_absolute_url(self, lang=None):
        if not lang:
            lang = get_language()
        category = self.categories.first()
        kwargs = {}
        urlconf = get_setting('PERMALINK_URLS')[self.app_config.url_patterns]
        if '<year>' in urlconf:
            kwargs['year'] = self.date_published.year
        if '<month>' in urlconf:
            kwargs['month'] = '%02d' % self.date_published.month
        if '<day>' in urlconf:
            kwargs['day'] = '%02d' % self.date_published.day
        if '<slug>' in urlconf:
            kwargs['slug'] = self.safe_translation_getter(
                'slug', language_code=lang, any_language=True)  # NOQA
        if '<category>' in urlconf:
            kwargs['category'] = category.safe_translation_getter(
                'slug', language_code=lang, any_language=True)  # NOQA
        return reverse('%s:post-detail' % self.app_config.namespace,
                       kwargs=kwargs)

    def get_meta_attribute(self, param):
        """
        Retrieves django-meta attributes from apphook config instance
        :param param: django-meta attribute passed as key
        """
        attr = None
        value = getattr(self.app_config, param)
        if value:
            attr = getattr(self, value, None)
        if attr is not None:
            if callable(attr):
                try:
                    data = attr(param)
                except TypeError:
                    data = attr()
            else:
                data = attr
        else:
            data = value
        return data

    def save_translation(self, translation, *args, **kwargs):
        if not translation.slug and translation.title:
            translation.slug = slugify(translation.title)
        super(Post, self).save_translation(translation, *args, **kwargs)

    def get_title(self):
        title = self.safe_translation_getter('meta_title', any_language=True)
        if not title:
            title = self.safe_translation_getter('title', any_language=True)
        return title.strip()

    def get_keywords(self):
        return self.safe_translation_getter('meta_keywords').strip().split(',')

    def get_locale(self):
        return self.get_current_language()

    def get_description(self):
        description = self.safe_translation_getter('meta_description',
                                                   any_language=True)
        if not description:
            description = self.safe_translation_getter('abstract',
                                                       any_language=True)
        return escape(strip_tags(description)).strip()

    def get_image_full_url(self):
        if self.main_image:
            return self.make_full_url(self.main_image.url)
        return ''

    def get_tags(self):
        taglist = [tag.name for tag in self.tags.all()]
        return ','.join(taglist)

    def get_author(self):
        return self.author

    def thumbnail_options(self):
        if self.main_image_thumbnail_id:
            return self.main_image_thumbnail.as_dict
        else:
            return get_setting('IMAGE_THUMBNAIL_SIZE')

    def full_image_options(self):
        if self.main_image_full_id:
            return self.main_image_full.as_dict
        else:
            return get_setting('IMAGE_FULL_SIZE')

    def get_full_url(self):
        return self.make_full_url(self.get_absolute_url())
Beispiel #22
0
class ActivitySection(Section):
    class Meta:
        verbose_name = "Activity Section"
        verbose_name_plural = 'Activity Sections'
        manager_inheritance_from_future = True

    content = PlaceholderField('activity_content')

    def absolute_url(self):
        return reverse('core:section_detail',
                       kwargs={
                           'lesson_slug': self.lesson.slug,
                           'slug': self.slug
                       })

    def delete(self, *args, **kwargs):
        #print("----- in ActivitySection overridden delete")
        # self.cleanup_placeholders()

        placeholders = [self.content]
        super(ActivitySection, self).delete(*args, **kwargs)

        for ph in placeholders:
            ph.clear()
            ph.delete()

    ########################################
    #   Publication Method overrides
    ########################################

    def copy(self, maintain_ref=False):
        '''
            generate a new Activity instance based on this Activitiy instance with a fresh ref_id and no parent
        :return: a new lesson with a fresh reference id
        '''
        new_instance = ActivitySection(
            lesson=None,
            is_deleted=False,
            position=0,
            name=self.name,
            short_name=self.short_name,
            duration=self.duration,
        )

        if maintain_ref:
            new_instance.ref_id = self.ref_id

        return new_instance

    def copy_children(self, from_instance, maintain_ref=False):

        # copy over the resources for this activity
        self.resources.all().delete()

        for resource in from_instance.resources.all():
            new_resource = Resource(
                display_text=resource.display_text,
                resource_link=resource.resource_link,
                resource_type=resource.resource_type,
                activity=self,
            )

            new_resource.save()

    def copy_content(self, from_instance):

        # add any tags from the 'from_instance'
        self.tags.add(*list(from_instance.tags.names()))

        # clear any existing plugins
        self.content.clear()

        # get the list of plugins in the 'from_instance's intro
        plugins = from_instance.content.get_plugins_list()

        # copy 'from_instance's intro plugins to this object's intro
        copy_plugins_to(plugins, self.content, no_signals=True)

    @property
    def is_dirty(self):

        # a module is considered dirty if it's pub_status is pending, or if it contains any plugins
        # edited after the most recent change date.

        #result = super(ActivitySection, self).is_dirty() or self.content.cmsplugin_set.filter(changed_date__gt=self.changed_date).exists()

        result = any([
            super(ActivitySection, self).is_dirty,
            self.content.cmsplugin_set.filter(
                changed_date__gt=self.get_Publishable_parent(
                ).published_copy.creation_date).exists()
        ])

        return result
Beispiel #23
0
class Doctor(TranslationHelperMixin, TranslatedAutoSlugifyMixin,
             TranslatableModel):
    slug_source_field_name = 'name'

    translations = TranslatedFields(
        name=models.CharField(_('name'),
                              max_length=255,
                              blank=False,
                              default='',
                              help_text=_("Provide this person's name.")),
        slug=models.SlugField(
            _('unique slug'),
            max_length=255,
            blank=True,
            default='',
            help_text=_("Leave blank to auto-generate a unique slug.")),
        speciality=models.CharField(_('speciality'), max_length=255),
        sub_speciality=models.CharField(_('sub speciality'),
                                        max_length=255,
                                        blank=True),
        function=models.CharField(_('role'),
                                  max_length=255,
                                  blank=True,
                                  default=''),
    )

    phone = models.CharField(verbose_name=_('phone'),
                             null=True,
                             blank=True,
                             max_length=100)
    mobile = models.CharField(verbose_name=_('mobile'),
                              null=True,
                              blank=True,
                              max_length=100)
    email = models.EmailField(verbose_name=_("email"), blank=True, default='')
    website = models.URLField(verbose_name=_('website'), null=True, blank=True)
    section = models.ForeignKey(Section,
                                verbose_name=_('Section'),
                                related_name='doctors',
                                null=True,
                                blank=True,
                                on_delete=models.SET_NULL)
    visual = FilerImageField(null=True,
                             blank=True,
                             default=None,
                             on_delete=models.SET_NULL)

    facebook = models.URLField(verbose_name=_('Facebook'), blank=True)
    twitter = models.URLField(verbose_name=_('Twitter'), blank=True)
    linkedin = models.URLField(verbose_name=_('LinkedIn'), blank=True)

    content = PlaceholderField('doctor_content', related_name='doctor_content')
    content_bottom = PlaceholderField('doctor_content_bottom',
                                      related_name='doctor_content_bottom')
    sidebar = PlaceholderField('doctor_sidebar', related_name='doctor_sidebar')
    sidebar_bottom = PlaceholderField('doctor_sidebar_bottom',
                                      related_name='doctor_sidebar_bottom')

    class Meta:
        verbose_name = _('Doctor')
        verbose_name_plural = _('Doctors')

    def __str__(self):
        pkstr = str(self.pk)
        name = self.safe_translation_getter('name',
                                            default='',
                                            any_language=True).strip()
        return name if len(name) > 0 else pkstr

    def get_absolute_url(self, language=None):
        if not language:
            language = get_current_language()
        slug, language = self.known_translation_getter('slug',
                                                       None,
                                                       language_code=language)
        if slug:
            kwargs = {'slug': slug}
        else:
            kwargs = {'pk': self.pk}
        with override(language):
            # do not fail with 500 error so that if detail view can't be
            # resolved we still can use plugins.
            try:
                url = reverse('nnuh_doctors:doctor-detail', kwargs=kwargs)
            except NoReverseMatch:
                url = ''
        return url
Beispiel #24
0
class Terms(ModelMeta, TranslatableModel):
    """
    Terms Agreement Model
    """
    author = models.ForeignKey(
        dj_settings.AUTH_USER_MODEL,
        verbose_name=_(u'author'),
        null=True,
        blank=True,
        related_name='app_terms_author',
    )

    date_created = models.DateTimeField(_(u'created'), auto_now_add=True)
    date_modified = models.DateTimeField(_(u'last modified'), auto_now=True)
    date_published = models.DateTimeField(_(u'published Since'),
                                          default=timezone.now)
    date_published_end = models.DateTimeField(_(u'published Until'),
                                              null=True,
                                              blank=True)
    publish = models.BooleanField(_(u'publish'), default=False)
    categories = models.ManyToManyField(
        'app.AppCategory',
        verbose_name=_(u'category'),
        related_name='app_terms_categories',
    )
    main_image = FilerImageField(verbose_name=_(u'main image'),
                                 blank=True,
                                 null=True,
                                 on_delete=models.SET_NULL,
                                 related_name='app_terms_image')
    main_image_thumbnail = models.ForeignKey(
        'cmsplugin_filer_image.ThumbnailOption',
        verbose_name=_(u'main image thumbnail'),
        related_name='app_terms_thumbnail',
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    main_image_full = models.ForeignKey(
        'cmsplugin_filer_image.ThumbnailOption',
        verbose_name=_(u'main image full'),
        related_name='app_terms_full',
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    enable_comments = models.BooleanField(
        verbose_name=_(u'enable comments on terms agreement'),
        default=get_setting('ENABLE_COMMENTS'))
    sites = models.ManyToManyField(
        'sites.Site',
        verbose_name=_(u'Site(s)'),
        blank=True,
        null=True,
        help_text=_(u'Select sites in which to show the terms agreement '
                    u'If none is set it will be '
                    u'visible in all the configured sites.'))

    translations = TranslatedFields(
        title=models.CharField(_(u'title'), max_length=255),
        slug=models.SlugField(_(u'slug'), blank=True, db_index=True),
        abstract=HTMLField(_(u'abstract'), blank=True, default=''),
        meta_description=models.TextField(
            verbose_name=_(u'terms meta description'), blank=True, default=''),
        meta_keywords=models.TextField(verbose_name=_(u'terms meta keywords'),
                                       blank=True,
                                       default=''),
        meta_title=models.CharField(
            verbose_name=_(u'terms meta title'),
            help_text=_(u'used in title tag and social sharing'),
            max_length=255,
            blank=True,
            default=''),
        terms_text=HTMLField(_(u'text'), default='', blank=True),
        meta={'unique_together': [
            (
                'slug',
                'language_code',
            ),
        ]},
    )
    content = PlaceholderField('terms_content',
                               related_name='app_terms_content')

    objects = GenericDateTaggedManager()
    tags = TaggableManager(blank=True, related_name='app_tags')

    _metadata = {
        'title': 'get_title',
        'description': 'get_description',
        'og_description': 'get_description',
        'twitter_description': 'get_description',
        'gplus_description': 'get_description',
        'keywords': 'get_keywords',
        'locale': None,
        #'image': 'get_image_full_url',
        'object_type': get_setting('TYPE'),
        'og_type': get_setting('FB_TYPE'),
        'og_app_id': get_setting('FB_APPID'),
        'og_profile_id': get_setting('FB_PROFILE_ID'),
        'og_publisher': get_setting('FB_PUBLISHER'),
        'og_author_url': get_setting('FB_AUTHOR_URL'),
        'twitter_type': get_setting('TWITTER_TYPE'),
        'twitter_site': get_setting('TWITTER_SITE'),
        'twitter_author': get_setting('TWITTER_AUTHOR'),
        'gplus_type': get_setting('GPLUS_TYPE'),
        'gplus_author': get_setting('GPLUS_AUTHOR'),
        'published_time': 'date_published',
        'modified_time': 'date_modified',
        'expiration_time': 'date_published_end',
        'tag': 'get_tags',
        'url': 'get_absolute_url',
    }

    class Meta:
        verbose_name = _('app terms')
        verbose_name_plural = _('app terms agreements')
        ordering = ('-date_published', '-date_created')
        get_latest_by = 'date_published'

    def __str__(self):
        return self.safe_translation_getter('title')

    def get_absolute_url(self):
        #import pdb; pdb.set_trace()
        kwargs = {
            'year':
            self.date_published.year,
            'month':
            '%02d' % self.date_published.month,
            'day':
            '%02d' % self.date_published.day,
            'article_slug':
            self.safe_translation_getter('slug',
                                         language_code=get_language(),
                                         any_language=True)
        }
        return reverse('app:terms-detail', kwargs=kwargs)

    def save(self, *args, **kwargs):
        super(Terms, self).save(*args, **kwargs)
        main_lang = self.get_current_language()
        for lang in self.get_available_languages():
            self.set_current_language(lang)
            if not self.slug and self.title:
                self.slug = slugify(self.title)
        self.set_current_language(main_lang)
        self.save_translations()

    def get_title(self):
        title = self.safe_translation_getter('meta_title', any_language=True)
        if not title:
            title = self.safe_translation_getter('title', any_language=True)
        return title.strip()

    def get_keywords(self):
        return self.safe_translation_getter('meta_keywords').strip().split(',')

    def get_description(self):
        description = self.safe_translation_getter('meta_description',
                                                   any_language=True)
        if not description:
            description = self.safe_translation_getter('abstract',
                                                       any_language=True)
        return escape(strip_tags(description)).strip()

    def get_image_full_url(self):
        if self.main_image:
            return self.make_full_url(self.main_image.url)
        return ''

    def get_tags(self):
        taglist = [tag.name for tag in self.tags.all()]
        return ','.join(taglist)

    def get_author(self):
        return self.author

    def thumbnail_options(self):
        if self.main_image_thumbnail_id:
            return self.main_image_thumbnail.as_dict
        else:
            return get_setting('IMAGE_THUMBNAIL_SIZE')

    def full_image_options(self):
        if self.main_image_full_id:
            return self.main_image_full.as_dict
        else:
            return get_setting('IMAGE_FULL_SIZE')

    def get_full_url(self):
        return self.make_full_url(self.get_absolute_url())
Beispiel #25
0
class ReadingSection(Section):
    class Meta:
        verbose_name = "Reading Section"
        verbose_name_plural = 'Reading Sections'
        manager_inheritance_from_future = True

    content = PlaceholderField('reading_content')

    def absolute_url(self):
        return reverse('core:section_detail',
                       kwargs={
                           'lesson_slug': self.lesson.slug,
                           'slug': self.slug
                       })

    def delete(self, *args, **kwargs):
        #print("----- in ReadingSection overridden delete")
        # self.cleanup_placeholders()
        placeholders = [self.content]
        super(ReadingSection, self).delete(*args, **kwargs)

        for ph in placeholders:
            ph.clear()
            ph.delete()

    ########################################
    #   Publication Method overrides
    ########################################

    def copy(self, maintain_ref=False):
        '''
            generate a new ReadingSection instance based on this ReadingSection instance with a fresh ref_id and no parent
        :return: a new lesson with a fresh reference id
        '''
        new_instance = ReadingSection(
            lesson=None,
            position=0,
            is_deleted=False,
            name=self.name,
            short_name=self.short_name,
            duration=self.duration,
        )

        if maintain_ref:
            new_instance.ref_id = self.ref_id

        return new_instance

    def copy_children(self, from_instance, maintain_ref=False):

        # copy over the content
        #self.copy_content(from_instance)
        pass

    def copy_content(self, from_instance):

        # add any tags from the 'from_instance'
        self.tags.add(*list(from_instance.tags.names()))

        # clear any existing plugins
        self.content.clear()

        # get the list of plugins in the 'from_instance's intro
        plugins = from_instance.content.get_plugins_list()

        # copy 'from_instance's intro plugins to this object's intro
        copy_plugins_to(plugins, self.content, no_signals=True)

    @property
    def is_dirty(self):

        # a module is considered dirty if it's pub_status is pending, or if it contains any plugins
        # edited after the most recent change date.

        # get parent publication object
        parent_publication = self.get_Publishable_parent()

        if parent_publication.publish_status == Publication.DRAFT_ONLY:
            return True

        pub_date = None
        if parent_publication.publish_status == Publication.PUBLISHED:
            # if this is a published draft-copy
            pub_date = parent_publication.published_copy.published_date
        else:
            # if this is the current publication
            pub_date = parent_publication.published_date

        result = any([
            super(ReadingSection, self).is_dirty,
            self.content.cmsplugin_set.filter(
                changed_date__gt=pub_date).exists()
        ])

        return result
class Migration(migrations.Migration):

    dependencies = [
        ('cms', '__latest__'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('filer', '__latest__'),
    ]

    operations = [
        migrations.CreateModel(
            name='Post',
            fields=[
                ('id',
                 models.AutoField(verbose_name='ID',
                                  serialize=False,
                                  auto_created=True,
                                  primary_key=True)),
                ('title',
                 models.CharField(help_text='The post title.',
                                  max_length=255,
                                  verbose_name='Title')),
                ('slug',
                 models.SlugField(
                     help_text='The name (slug) for the post, used in URLs.',
                     unique=True,
                     max_length=255,
                     verbose_name='slug')),
                ('excerpt', models.TextField(verbose_name='Excerpt',
                                             blank=True)),
                ('creation_date',
                 models.DateTimeField(help_text="The post's creation time.",
                                      auto_now_add=True)),
                ('publication_date',
                 models.DateTimeField(
                     default=django.utils.timezone.now,
                     help_text=
                     'Used in the URL. If changed, the URL will change.',
                     verbose_name='Publication date',
                     db_index=True)),
                ('author',
                 models.ForeignKey(related_name='posts',
                                   verbose_name='Author',
                                   to=settings.AUTH_USER_MODEL,
                                   help_text='The author of the post.')),
                ('content',
                 PlaceholderField(related_name='post_content',
                                  slotname='post content',
                                  editable=False,
                                  to='cms.Placeholder',
                                  help_text='The post content.',
                                  null=True)),
                ('featured_image',
                 FilerImageField(related_name='blog_post_featured_images',
                                 verbose_name='Featured Image',
                                 blank=True,
                                 null=True,
                                 to='filer.Image',
                                 help_text='Featured image for this post')),
            ],
            options={
                'ordering': ('-publication_date', ),
                'get_latest_by': 'publication_date',
            },
        ),
    ]
Beispiel #27
0
class Project(CMSPlugin):
    objects = models.Manager()

    slug = models.SlugField(_('slug'),
                            max_length=255,
                            blank=True,
                            db_index=True)

    title = models.CharField(max_length=250, null=True, blank=True)
    sub_title = models.CharField(max_length=250, null=True, blank=True)
    short_description = models.TextField(default='')
    description = HTMLField(_('description'), blank=True, default='')
    skills = models.CharField(max_length=255, null=True, blank=True)
    roles = models.CharField(max_length=255, null=True, blank=True)
    client = models.CharField(max_length=255, null=True, blank=True)
    length = models.CharField(max_length=50, null=True, blank=True)

    demo_url = models.URLField(max_length=255, null=True, blank=True)
    android_demo_url = models.URLField(max_length=500,
                                       null=True,
                                       blank=True,
                                       default='')
    ios_demo_url = models.URLField(max_length=500,
                                   null=True,
                                   blank=True,
                                   default='')
    youtube_embed_url = models.CharField(max_length=255,
                                         null=True,
                                         blank=True,
                                         default='')

    top_image = models.ImageField(upload_to='portfolio/img/top_image/',
                                  max_length=500,
                                  null=True,
                                  blank=True,
                                  default='')
    # published_date = models.DateTimeField(null=True, blank=True)

    # Placeholder property
    use_case = PlaceholderField('use_case')

    is_published = models.BooleanField(null=False, blank=False, default=True)
    is_homepage_display = models.BooleanField(null=False,
                                              blank=False,
                                              default=True)
    is_list_display = models.BooleanField(null=False,
                                          blank=False,
                                          default=True)

    tags = models.ManyToManyField(Tag,
                                  verbose_name=_('tag'),
                                  related_name='project')

    created_at = models.DateTimeField(auto_now_add=True,
                                      auto_now=False,
                                      editable=False)
    updated_at = models.DateTimeField(auto_now=True, editable=True)

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        """
        Handle some auto configuration during save
        """
        # if self.publish and self.date_published is None:
        #     self.date_published = timezone.now()
        if not self.slug and self.title:
            self.slug = slugify(self.title)
        super(Project, self).save(*args, **kwargs)

    def test_function(self):
        return '{}: test'.format(self.title)

    @property
    def sorted_mediaaset_set(self):
        return self.mediaasset_set.order_by('id')
Beispiel #28
0
class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
    """
    Blog post
    """

    author = models.ForeignKey(
        dj_settings.AUTH_USER_MODEL,
        verbose_name=_("author"),
        null=True,
        blank=True,
        related_name="djangocms_blog_post_author",
        on_delete=models.PROTECT,
    )

    date_created = models.DateTimeField(_("created"), auto_now_add=True)
    date_modified = models.DateTimeField(_("last modified"), auto_now=True)
    date_published = models.DateTimeField(_("published since"),
                                          null=True,
                                          blank=True)
    date_published_end = models.DateTimeField(_("published until"),
                                              null=True,
                                              blank=True)
    date_featured = models.DateTimeField(_("featured date"),
                                         null=True,
                                         blank=True)
    categories = models.ManyToManyField("djangocms_blog.BlogCategory",
                                        verbose_name=_("category"),
                                        related_name="blog_posts",
                                        blank=True)

    enable_comments = models.BooleanField(
        verbose_name=_("enable comments on post"),
        default=get_setting("ENABLE_COMMENTS"))
    sites = models.ManyToManyField(
        "sites.Site",
        verbose_name=_("Site(s)"),
        blank=True,
        help_text=_("Select sites in which to show the post. "
                    "If none is set it will be "
                    "visible in all the configured sites."),
    )
    app_config = AppHookConfigField(BlogConfig,
                                    null=True,
                                    verbose_name=_("app. config"))

    translations = TranslatedFields(
        title=models.CharField(_("title"), max_length=752),
        slug=models.SlugField(_("slug"),
                              max_length=752,
                              blank=True,
                              db_index=True,
                              allow_unicode=True),
        subtitle=models.CharField(verbose_name=_("subtitle"),
                                  max_length=767,
                                  blank=True,
                                  default=""),
        abstract=HTMLField(_("abstract"),
                           blank=True,
                           default="",
                           configuration="BLOG_ABSTRACT_CKEDITOR"),
        main_image=FilerImageField(
            verbose_name=_("main image"),
            blank=True,
            null=True,
            on_delete=models.SET_NULL,
            related_name="djangocms_blog_post_image",
        ),
        main_image_thumbnail=models.ForeignKey(
            thumbnail_model,
            verbose_name=_("main image thumbnail"),
            related_name="djangocms_blog_post_thumbnail",
            on_delete=models.SET_NULL,
            blank=True,
            null=True,
        ),
        main_image_full=models.ForeignKey(
            thumbnail_model,
            verbose_name=_("main image full"),
            related_name="djangocms_blog_post_full",
            on_delete=models.SET_NULL,
            blank=True,
            null=True,
        ),
        meta_description=models.TextField(
            verbose_name=_("post meta description"), blank=True, default=""),
        meta_keywords=models.TextField(verbose_name=_("post meta keywords"),
                                       blank=True,
                                       default=""),
        meta_title=models.CharField(
            verbose_name=_("post meta title"),
            help_text=_("used in title tag and social sharing"),
            max_length=2000,
            blank=True,
            default="",
        ),
        post_text=HTMLField(_("text"),
                            default="",
                            blank=True,
                            configuration="BLOG_POST_TEXT_CKEDITOR"),
        meta={"unique_together": (("language_code", "slug"), )},
        is_publish=models.BooleanField(_('publish'), default=False),
    )
    media = PlaceholderField("media", related_name="media")
    content = PlaceholderField("post_content", related_name="post_content")
    liveblog = PlaceholderField("live_blog", related_name="live_blog")
    enable_liveblog = models.BooleanField(
        verbose_name=_("enable liveblog on post"), default=False)

    objects = GenericDateTaggedManager()
    tags = TaggableManager(blank=True, related_name="djangocms_blog_tags")

    related = SortedManyToManyField("self",
                                    verbose_name=_("Related Posts"),
                                    blank=True,
                                    symmetrical=False)

    _metadata = {
        "title": "get_title",
        "description": "get_description",
        "keywords": "get_keywords",
        "og_description": "get_description",
        "twitter_description": "get_description",
        "gplus_description": "get_description",
        "locale": "get_locale",
        "image": "get_image_full_url",
        "image_width": "get_image_width",
        "image_height": "get_image_height",
        "object_type": "get_meta_attribute",
        "og_type": "get_meta_attribute",
        "og_app_id": "get_meta_attribute",
        "og_profile_id": "get_meta_attribute",
        "og_publisher": "get_meta_attribute",
        "og_author_url": "get_meta_attribute",
        "og_author": "get_meta_attribute",
        "twitter_type": "get_meta_attribute",
        "twitter_site": "get_meta_attribute",
        "twitter_author": "get_meta_attribute",
        "gplus_type": "get_meta_attribute",
        "gplus_author": "get_meta_attribute",
        "published_time": "date_published",
        "modified_time": "date_modified",
        "expiration_time": "date_published_end",
        "tag": "get_tags",
        "url": "get_absolute_url",
    }

    class Meta:
        verbose_name = _("blog article")
        verbose_name_plural = _("blog articles")
        ordering = ("-date_published", "-date_created")
        get_latest_by = "date_published"

    def __str__(self):
        default = gettext("Post (no translation)")
        return self.safe_translation_getter("title",
                                            any_language=True,
                                            default=default)

    @property
    def guid(self, language=None):
        if not language:
            language = self.get_current_language()
        base_string = "-{0}-{2}-{1}-".format(
            language,
            self.app_config.namespace,
            self.safe_translation_getter("slug",
                                         language_code=language,
                                         any_language=True),
        )
        return hashlib.sha256(force_bytes(base_string)).hexdigest()

    @property
    def date(self):
        if self.date_featured:
            return self.date_featured
        return self.date_published

    def save(self, *args, **kwargs):
        """
        Handle some auto configuration during save
        """
        if self.safe_translation_getter(
                "is_publish") and self.date_published is None:
            self.date_published = timezone.now()
        if not self.slug and self.title:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)

    def save_translation(self, translation, *args, **kwargs):
        """
        Handle some auto configuration during save
        """
        if not translation.slug and translation.title:
            translation.slug = slugify(translation.title)
        super().save_translation(translation, *args, **kwargs)

    def get_absolute_url(self, lang=None):
        lang = _get_language(self, lang)
        with switch_language(self, lang):
            category = self.categories.first()
            kwargs = {}
            if self.date_published:
                current_date = self.date_published
            else:
                current_date = self.date_created
            urlconf = get_setting("PERMALINK_URLS")[
                self.app_config.url_patterns]
            if "<year>" in urlconf:
                kwargs["year"] = current_date.year
            if "<month>" in urlconf:
                kwargs["month"] = "%02d" % current_date.month
            if "<day>" in urlconf:
                kwargs["day"] = "%02d" % current_date.day
            if "<slug>" in urlconf:
                kwargs["slug"] = self.safe_translation_getter(
                    "slug", language_code=lang, any_language=True)  # NOQA
            if "<category>" in urlconf:
                kwargs["category"] = category.safe_translation_getter(
                    "slug", language_code=lang, any_language=True)  # NOQA
            return reverse("%s:post-detail" % self.app_config.namespace,
                           kwargs=kwargs)

    def get_title(self):
        title = self.safe_translation_getter("meta_title", any_language=True)
        if not title:
            title = self.safe_translation_getter("title", any_language=True)
        return title.strip()

    def get_keywords(self):
        """
        Returns the list of keywords (as python list)
        :return: list
        """
        return self.safe_translation_getter("meta_keywords",
                                            default="").strip().split(",")

    def get_description(self):
        description = self.safe_translation_getter("meta_description",
                                                   any_language=True)
        if not description:
            description = self.safe_translation_getter("abstract",
                                                       any_language=True)
        return escape(strip_tags(description)).strip()

    def get_image_full_url(self):
        if self.main_image:
            return self.build_absolute_uri(self.main_image.url)
        return ""

    def get_image_width(self):
        if self.main_image:
            return self.main_image.width

    def get_image_height(self):
        if self.main_image:
            return self.main_image.height

    def get_tags(self):
        """
        Returns the list of object tags as comma separated list
        """
        taglist = [tag.name for tag in self.tags.all()]
        return ",".join(taglist)

    def get_author(self):
        """
        Return the author (user) objects
        """
        return self.author

    def _set_default_author(self, current_user):
        if not self.author_id and self.app_config.set_author:
            if get_setting("AUTHOR_DEFAULT") is True:
                user = current_user
            else:
                user = get_user_model().objects.get(
                    username=get_setting("AUTHOR_DEFAULT"))
            self.author = user

    def thumbnail_options(self):
        if self.main_image_thumbnail_id:
            return self.main_image_thumbnail.as_dict
        else:
            return get_setting("IMAGE_THUMBNAIL_SIZE")

    def full_image_options(self):
        if self.main_image_full_id:
            return self.main_image_full.as_dict
        else:
            return get_setting("IMAGE_FULL_SIZE")

    @property
    def is_published(self):
        """
        Checks wether the blog post is *really* published by checking publishing dates too
        """
        return (self.safe_translation_getter("is_publish") and
                (self.date_published and self.date_published <= timezone.now())
                and (self.date_published_end is None
                     or self.date_published_end > timezone.now()))

    def should_knock(self, signal_type, created=False):
        """
        Returns whether to emit knocks according to the post state
        """
        new = self.app_config.send_knock_create and self.is_published and self.date_published == self.date_modified
        updated = self.app_config.send_knock_update and self.is_published
        return (new or updated) and signal_type in ("post_save", "post_delete")

    def get_cache_key(self, language, prefix):
        return "djangocms-blog:{2}:{0}:{1}".format(language, self.guid, prefix)

    @property
    def liveblog_group(self):
        return "liveblog-{apphook}-{lang}-{post}".format(
            lang=self.get_current_language(),
            apphook=self.app_config.namespace,
            post=self.safe_translation_getter("slug", any_language=True),
        )
Beispiel #29
0
class AbstractArticle(TimestampMixin, PublishingMixin):
    """
    Model for creating and storing and Article object
    """

    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255, unique=True)
    author = models.ForeignKey(to=Author,
                               on_delete=models.CASCADE,
                               related_name="%(app_label)s_articles")
    photo = FilerImageField(
        related_name="%(app_label)s_%(class)s_images",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )

    intro = models.CharField(max_length=255)
    content = PlaceholderField(slotname="article_content",
                               related_name="%(app_label)s_article_content")
    tags = models.ManyToManyField(to=Tag,
                                  verbose_name="Tags",
                                  related_name="%(app_label)s_%(class)s_tags")
    category = models.ForeignKey(to=Category,
                                 on_delete=models.CASCADE,
                                 related_name="%(app_label)s_articles")
    meta_title = models.CharField(max_length=160, blank=True)
    meta_description = models.CharField(max_length=255, blank=True)

    plugin_text = models.TextField(blank=True, editable=False)

    objects = ArticleQuerySet.as_manager()

    class Meta:
        abstract = True
        ordering = ["-publish_at"]

    def __str__(self):
        """
        Returns the string representation of the article object
        """
        return f"{self.title} article by {self.author}"

    def save(self, *args, **kwargs):
        """
        Override save method so we can store the plugin text
        """
        if self.content:
            self.plugin_text = self.plain_text
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        """
        Builds the url for the article object
        """
        return reverse("news:detail", kwargs={"slug": self.slug})

    @cached_property
    def plain_text(self):
        """
        Renders all the plaintext plugins from the placeholder field
        """

        # We need to use this weird ContentRenderer in order to render the plugins
        renderer = ContentRenderer(request=RequestFactory())
        text = ""

        for plugin in self.content.cmsplugin_set.all():
            html = renderer.render_plugin(plugin, {})
            text += strip_tags(html)

        return text.strip()

    @cached_property
    def read_time(self):
        """
        Return estimated article reading time
        """
        word_count = len(self.plain_text.split())
        mins = round(word_count / 240.0)
        if word_count and mins < 1:
            return 1
        return mins
Beispiel #30
0
class News(models.Model):
    """
    News
    """
    author = models.ForeignKey(AUTH_USER_MODEL,
                               verbose_name=_('author'),
                               null=True,
                               blank=True,
                               related_name='news_author')
    category = models.ForeignKey("NewsCategory",
                                 verbose_name=_('category'),
                                 related_name="news_category",
                                 null=True,
                                 blank=True,
                                 default=None)

    meta_description = models.TextField(
        verbose_name=_('news meta description'), blank=True, default='')
    meta_keywords = models.TextField(verbose_name=_('news meta keywords'),
                                     blank=True,
                                     default='')
    meta_title = models.CharField(
        verbose_name=_('news meta title'),
        help_text=_('used in title tag and social sharing'),
        max_length=255,
        blank=True,
        default='')

    title = models.CharField(_('Title'), max_length=255)
    slug = AutoSlugField(_('Slug'),
                         max_length=128,
                         unique=True,
                         editable=True,
                         populate_from='title',
                         help_text=_('A slug is a short name which uniquely'
                                     ' identifies the news item'))
    description = HTMLField(_('Description'),
                            blank=True,
                            configuration='CKEDITOR_SETTINGS_NEWS')
    content = PlaceholderField('news_content', related_name='news_content')

    publish = models.BooleanField(_('Published'), default=False)

    date_created = models.DateTimeField(_('created'), auto_now_add=True)
    date_modified = models.DateTimeField(_('last modified'), auto_now=True)
    date_published = models.DateTimeField(_('published since'),
                                          default=timezone.now)
    date_published_end = models.DateTimeField(_('published until'),
                                              null=True,
                                              blank=True)

    enable_comments = models.BooleanField(
        verbose_name=_('enable comments on post'), default=ENABLE_COMMENTS)

    images = models.ManyToManyField(
        'filer.Image',
        through='NewsImages',
        verbose_name=_("News images"),
    )

    # Oscar links
    linked_products = models.ManyToManyField(
        'catalogue.Product',
        blank=True,
        verbose_name=_("Linked products"),
        help_text=_(
            "These are products that can be shown with news post "
            "or news post can be shown on the specific product's page."))
    linked_categories = models.ManyToManyField(
        'catalogue.Category',
        blank=True,
        verbose_name=_("Linked product's categories"),
        help_text=_("Show news for that categories "
                    "or display news on the category page"))
    linked_classes = models.ManyToManyField(
        'catalogue.ProductClass',
        blank=True,
        verbose_name=_("Linked product's classes"),
        help_text=_("Show news for that classes "
                    "or display news on the specific class product's pages"))

    sites = models.ManyToManyField(
        'sites.Site',
        verbose_name=_('Site(s)'),
        blank=True,
        help_text=_('Select sites in which to show the post. '
                    'If none is set it will be '
                    'visible in all the configured sites.'))

    tags = TaggableManager(blank=True, related_name='news_tags')

    objects = NewsManager()
    published = PublishedNewsManager()

    class Meta:
        app_label = 'oscar_news'
        verbose_name = _('News')
        verbose_name_plural = _('News')
        ordering = ('-date_published', )

    def __unicode__(self):
        return self.title

    @property
    def is_published(self):
        """
        Checks whether the news entry is *really* published by checking publishing dates too
        """
        return (self.publish and
                (self.date_published and self.date_published <= timezone.now())
                and (self.date_published_end is None
                     or self.date_published_end > timezone.now()))

    def _set_default_author(self, current_user):
        if not self.author_id:
            if AUTHOR_DEFAULT is True:
                user = current_user
            else:
                user = get_user_model().objects.get(username=AUTHOR_DEFAULT)
            self.author = user

    def get_absolute_url(self):
        """
        method below inherited and slightly customized
        """
        cache_key = 'NEWS_ENTRY_URL_%s' % self.pk
        url = cache.get(cache_key)
        if not url:
            # temporarily use link to news detail
            url = reverse('oscar_news:entry-detail',
                          kwargs={'slug': self.slug})
            cache.set(cache_key, url)
        return url

    def get_tags(self, queryset=None):
        """
        :return: the list of object's tags annotated with counters.
        Tags are limited by published news.
        """
        queryset = queryset or News.published.get_queryset()
        return get_tag_cloud(self.__class__, queryset, set(self.tags.all()))

    def get_all_tags(self):
        """
        :return: List of all object's tags including unpublished
        """
        return self.get_tags(News.objects.all())

    def _get_next_or_previous_published(self, is_next):
        if not self.pk:
            raise ValueError(
                "get_next/get_previous cannot be used on unsaved objects.")
        op = 'gt' if is_next else 'lt'
        order = '' if is_next else '-'
        field = 'date_published'
        param = force_text(getattr(self, field))
        q = Q(**{'%s__%s' % (field, op): param})
        q = q | Q(**{field: param, 'pk__%s' % op: self.pk})
        qs = self.__class__.published.using(self._state.db).filter(q).order_by(
            '%s%s' % (order, field), '%spk' % order)
        try:
            return qs[0]
        except IndexError:
            raise self.DoesNotExist("%s matching query does not exist." %
                                    self.__class__._meta.object_name)

    def get_next_published(self):
        return self._get_next_or_previous_published(is_next=True)

    def get_previous_published(self):
        return self._get_next_or_previous_published(is_next=False)