class Blog(models.Model, CoverImageMixin): title = models.CharField(max_length=140) slug = models.CharField(max_length=140, db_index=True) cover = models.ImageField(upload_to="blog_cover", blank=True, null=True) nav_icon = models.ImageField(upload_to="blog_nav_icon", blank=True, null=True) block_header = SimpleMDEField(max_length=10000, blank=True, null=True) block_footer = SimpleMDEField(max_length=10000, blank=True, null=True) def __str__(self): return self.title def get_posts(self): return Post.objects.blog_posts(blog=self) def has_language(self, language): if BlogTitle.objects.filter(blog=self, language=language).first(): return True return False def get_language_object(self, language): language_object = BlogTitle.objects.filter(blog=self, language=language).first() if language_object is None: language_object = BlogTitle.objects.filter( blog=self, language=settings.LANGUAGE_CODE).first() return language_object
class TagTitle(models.Model): tag = models.ForeignKey(Tag, db_index=True) language = models.CharField(max_length=15, db_index=True, choices=settings.LANGUAGES) name = models.CharField(max_length=140) description = SimpleMDEField(max_length=200) meta_title = SimpleMDEField(max_length=70, blank=True, null=True) meta_description = SimpleMDEField(max_length=156, blank=True, null=True) class Meta: unique_together = ("tag", "language") def __str__(self): return self.name
class Story(models.Model): title = models.CharField(max_length=200) pub_date = models.DateTimeField() text = SimpleMDEField() # text = models.TextField() slug = models.SlugField(max_length=40, unique=True) author = models.ForeignKey(User) coverphoto = models.ImageField(upload_to='coverphoto/', default='coverphoto/None/no-img.jpg') site = models.ForeignKey(Site) category = models.ForeignKey(Category, blank=True, null=True) tags = TaggableManager() # tags = models.ManyToManyField(Tag) def get_absolute_url(self): return "%s/%s/%s/" % (self.pub_date.year, self.pub_date.month, self.slug) def __unicode__(self): return self.title class Meta: verbose_name_plural = 'stories' ordering = ["-pub_date"]
class Tag(models.Model): user = models.ForeignKey(DepartmentMember, related_name='+', null=True, blank=True, on_delete=models.CASCADE, verbose_name='Nhân Viên') tag_name = models.TextField(max_length=500, null=True, blank=True, verbose_name='Công Việc') tag_description = SimpleMDEField(null=True, blank=True, verbose_name='Mô Tả') period_start = models.DateTimeField(null=True, blank=True, verbose_name='Thời Gian Bắt Đầu') period_end = models.DateTimeField(null=True, blank=True, verbose_name='Thời Gian Kết Thúc') weight = models.IntegerField(default=0, null=True, blank=True) quantity = models.IntegerField(default=0, null=True, blank=True) finished = models.IntegerField(default=0, null=True, blank=True) progress = models.FloatField(default=0, null=True, blank=True) state = models.CharField(max_length=2, choices=STATE_TAG_CHOICE, null=True, blank=True, verbose_name='Trạng Thái') created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) created_by = models.ForeignKey(Profile, related_name='+', null=True, blank=True, on_delete=models.CASCADE) updated_at = models.DateTimeField(auto_now=True, null=True, blank=True) removed = models.BooleanField(default=False) def __str__(self): return self.tag_name def get_state(self): return next(y for x, y in STATE_TAG_CHOICE if self.state == x) class Meta: ordering = ('-created_at',)
class DesignElement(models.Model): name = models.CharField(max_length=300) parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name="children") project = models.ForeignKey(Project, on_delete=models.CASCADE, blank=True, null=True, related_name="design_elements") element_type = models.ForeignKey(ElementType, on_delete=models.CASCADE, related_name="elements") description = SimpleMDEField("Element description", null=True, blank=True) def serializable_object(self): obj = { 'name': self.name, 'children': [], 'description': self.description, 'tasks': [], 'id': self.pk, 'element_type': model_to_dict(self.element_type) } for child in self.children.all(): obj['children'].append(child.serializable_object()) for task in self.tasks.all(): obj["tasks"].append(task.serializable_object()) return obj def __str__(self): return self.name
class Project(models.Model): category = models.ForeignKey('Category') author = models.ForeignKey('auth.User') image = models.ImageField(upload_to='myblog/image/project') image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(100, 50)], format='JPEG', options={'quality': 60}) title = models.CharField(max_length=200) summary = models.CharField(max_length=1000) body = SimpleMDEField(verbose_name=u'') created_date = models.DateTimeField(default=timezone.now) published_date = models.DateField(default=timezone.now) slug = models.SlugField(unique=True) likes = models.PositiveIntegerField(default=0) @property def total_likes(self): return self.likes.count() def __str__(self): return self.title def publish(self): self.published_date = timezone.now() self.status == self.STATUS_PUBLIC self.save()
class Task(models.Model): user = models.ForeignKey(DepartmentMember, related_name='+', null=True, blank=True, on_delete=models.CASCADE) task_name = models.TextField(max_length=500, null=True, blank=True) task_description = SimpleMDEField(null=True, blank=True) period_start = models.DateTimeField(null=True, blank=True, verbose_name='Thời Gian Bắt Đầu') period_end = models.DateTimeField(null=True, blank=True, verbose_name='Thời Gian Kết Thúc') unit_of_measure = models.CharField(max_length=100, null=True, blank=True) target_value = models.IntegerField(default=0, null=True, blank=True) result_value = models.IntegerField(default=0, null=True, blank=True) progress = models.FloatField(default=0, null=True, blank=True) weight = models.IntegerField(default=0, null=True, blank=True) tag = models.ForeignKey(Tag, related_name='+', null=True, blank=True, on_delete=models.CASCADE) state = models.CharField(max_length=2, choices=STATE_TASK_CHOICE, null=True, blank=True, verbose_name='Trạng Thái') is_finished = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) updated_at = models.DateTimeField(auto_now=True, null=True, blank=True) removed = models.BooleanField(default=False) def __str__(self): return self.task_name def get_state(self): return next(y for x, y in STATE_TASK_CHOICE if self.state == x) class Meta: ordering = ('-created_at',)
class Event(models.Model): uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True) title = models.CharField(max_length=200) invitee_capacity = models.PositiveIntegerField(default=0) event_day = models.DateField() initial_hour = models.TimeField() end_hour = models.TimeField() place_name = models.CharField(max_length=200) address = models.CharField(max_length=250) latitude = models.DecimalField(default=0, max_digits=20, decimal_places=12) longitude = models.DecimalField(default=0, max_digits=20, decimal_places=12) zoom = models.PositiveSmallIntegerField(default=18) cover_image = models.ImageField() description = SimpleMDEField(max_length=2000, blank=True, null=True) def __str__(self): return f"{self.title}" def invitees(self): return Invitee.objects.filter(event=self, cancelled=False) def invitees_count(self): return self.invitees().count() def enroll_user(self, user): if self.invitees().filter(user=user).exists(): raise ValidationError(f"The user {user} is already invited") if self.invitee_capacity == 0 or self.invitee_capacity > self.invitees_count( ): return Invitee.objects.create(event=self, user=user)
class Gallery(models.Model): class Meta: verbose_name = _("gallery") verbose_name_plural = _("galleries") ordering = ['sort_order'] portfolio = models.ForeignKey(Portfolio, blank=True, null=True, on_delete=models.CASCADE) sort_order = SortOrderField(_("Sort")) name = models.CharField(max_length=100) slug = models.SlugField(max_length=50, blank=True, null=True) synopsis = models.CharField(blank=True, null=True, max_length=200) abstract = SimpleMDEField(blank=True, null=True) thumbnail = models.ImageField(blank=True, upload_to='thumbnail') created_date = models.DateTimeField(auto_now_add=True) modified_date = models.DateTimeField(auto_now=True) # Reverse reference: portfoliomedia_set (0-n) def __str__(self): if self.portfolio: return "{name} ({portfolio})".format( name=self.name, portfolio=self.portfolio ) else: return self.name def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.name) for portfoliomedia in self.portfoliomedia_set.iterator(): if portfoliomedia.portfolio != self.portfolio: portfoliomedia.portfolio = self.portfolio portfoliomedia.save() super().save(*args, **kwargs) def get_absolute_url(self): return reverse('gallery', kwargs={'gallery_slug': self.slug}) @cached_property def abstract_html(self): if self.abstract: return markdownify(self.abstract) else: return self.abstract @cached_property def featured_thumbnail(self): if self.thumbnail: return self.thumbnail elif self.featured_media: return self.featured_media.featured_thumbnail else: return None @cached_property def featured_media(self): portfoliomedia = self.portfoliomedia_set.select_related('media').first() return portfoliomedia.media if portfoliomedia else None
class Tile(models.Model): """A block tile that renders a view or an object. """ column = models.ForeignKey(Column) position = models.PositiveIntegerField(default=0) view_name = models.CharField( max_length=200, help_text="""A view to be rendered in this tile. This view is \ typically a snippet of a larger page. If you are unsure test and see if \ it works. If this value is set it has precedence over target.""", null=True, blank=True) target_content_type = models.ForeignKey( ContentType, related_name="tile_target_content_type", null=True, blank=True, ) target_object_id = models.PositiveIntegerField( null=True, blank=True, ) target = GenericForeignKey( "target_content_type", "target_object_id", ) markdown = SimpleMDEField(null=True, blank=True) style = models.CharField( max_length=200, default="tile", help_text="""The style of template that is used to render the item \ inside the tile if target is set.""", null=True, blank=True) class_name = models.CharField( max_length=200, help_text="One or more CSS classes that are applied to the tile.", null=True, blank=True, ) @property def label(self): # Dangling targets pose a problem try: target = self.target except AttributeError: target = "Target has been deleted" return unicode(self.view_name or target or self.markdown[:100]) @cached_property def content(self): if not self.markdown: return "" return mark_safe(markdown.markdown(self.markdown)) class Meta: ordering = ['position']
class Organization(models.Model): title = models.CharField(max_length=200) description = SimpleMDEField(max_length=2000, blank=True, null=True) cover_image = models.ImageField(blank=True, null=True) def save(self, *args, **kwargs): self.pk = 1 super(Organization, self).save(*args, **kwargs)
class Tag(models.Model, CoverImageMixin): COLOR_CHOICES = ( ("red", "red"), ("orange", "orange"), ("yellow", "yellow"), ("olive", "olive"), ("green", "green"), ("teal", "teal"), ("blue", "blue"), ("violet", "violet"), ("purple", "purple"), ("pink", "pink"), ("brown", "brown"), ("grey", "grey"), ("black", "black"), ) blog = models.ForeignKey(Blog, db_index=True) cover = models.ImageField(upload_to="tag_cover", blank=True, null=True) name = models.CharField(max_length=140) slug = models.CharField(max_length=140) color = models.CharField(max_length=14, choices=COLOR_CHOICES) meta_title = SimpleMDEField(max_length=70, blank=True, null=True) meta_description = SimpleMDEField(max_length=156, blank=True, null=True) def __str__(self): return self.name def has_language(self, language): if TagTitle.objects.filter(tag=self, language=language).first(): return True return False def get_posts(self): return Post.objects.published_tag(tag=self) def get_post_count(self): return Post.objects.published_tag(tag=self).count() def get_language_object(self, language): language_object = TagTitle.objects.filter(tag=self, language=language).first() if language_object is None: language_object = TagTitle.objects.filter( tag=self, language=settings.LANGUAGE_CODE).first() return language_object
class AuthorBio(models.Model): author = models.ForeignKey(Author, db_index=True) bio = SimpleMDEField(max_length=255) language = models.CharField(max_length=15, db_index=True, choices=settings.LANGUAGES) def __str__(self): return "{} {}".format(self.author, self.language)
class Portfolio(models.Model): class Meta: verbose_name = _("portfolio") verbose_name_plural = _("portfolios") site = models.ForeignKey(Site, blank=True, null=True, on_delete=models.CASCADE) title = models.CharField(max_length=100) subtitle = models.CharField(max_length=100, blank=True, null=True) slug = models.SlugField(max_length=50, blank=True, null=True) blurb = SimpleMDEField(blank=True, null=True) theme_id = models.CharField(max_length=50, choices=SITE_THEME_OPTIONS, verbose_name=_('theme')) meta_description = models.CharField(max_length=500, blank=True, null=True) meta_keywords = models.CharField(max_length=500, blank=True, null=True) created_date = models.DateTimeField(auto_now_add=True) modified_date = models.DateTimeField(auto_now=True) # Reverse reference: gallery_set (0-n) # Reverse reference: portfoliomedia_set (0-n) objects = PortfolioManager() def __str__(self): return self.title def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.name) super().save(*args, **kwargs) def get_absolute_url(self): return reverse('index') @cached_property def blurb_html(self): if self.blurb: return markdownify(self.blurb) else: return self.blurb def get_all_galleries(self): yield from self.gallery_set.all() def get_all_portfoliomedia(self): yield from self.portfoliomedia_set.select_related('media') def get_all_media(self): for portfoliomedia in self.get_all_portfoliomedia(): yield portfoliomedia.media @cached_property def theme(self): return SITE_THEMES.get(self.theme_id) @cached_property def featured_gallery(self): return self.gallery_set.select_related('media').first()
class Department(models.Model): # PHÒNG BAN: TÊN PHÒNG BAN, CẤP BẬC CỦA PHÒNG BAN, MÔ TẢ PHÒNG BAN, NGƯỜI ĐỨNG ĐẦU, CHỨC VỤ department_name = models.CharField(max_length=100, unique=True) department_level = models.IntegerField(default=0) department_desc = SimpleMDEField(null=True, blank=True) # department_leader = models.OneToOneField(Profile, related_name='+', null=True) # leader_title = models.CharField(max_length=225, default='Trưởng Phòng') removed = models.BooleanField(default=False) def __str__(self): return self.department_name
class About(models.Model): author = models.ForeignKey('auth.User') title = models.CharField(max_length=200) body = SimpleMDEField(verbose_name=u'') created_date = models.DateTimeField( default=timezone.now) published_date = models.DateTimeField( blank=True, null=True) def publish(self): self.published_date = timezone.now() self.save() def __str__(self): return self.title
class Author(models.Model, CoverImageMixin, ProfileImageMixin): user = models.OneToOneField(User, related_name="author_profile") cover = models.ImageField(upload_to="author_cover", blank=True, null=True) profile_image = models.ImageField(upload_to="image", blank=True, null=True) slug = models.CharField(max_length=140) location = models.CharField(max_length=100) website = models.URLField(max_length=100) facebook_profile = models.URLField(max_length=100) twitter_profile = models.URLField(max_length=100) block_header = SimpleMDEField(max_length=10000, blank=True, null=True) block_footer = SimpleMDEField(max_length=10000, blank=True, null=True) def __str__(self): return self.user.email def get_language_object(self, language): language_object = AuthorBio.objects.filter(author=self, language=language).first() if language_object is None: language_object = AuthorBio.objects.filter( author=self, language=settings.LANGUAGE_CODE).first() return language_object def has_language(self, language): if AuthorBio.objects.filter(author=self, language=language).first(): return True return False def get_posts(self): return Post.objects.author_posts(author=self) def get_post_count(self): return Post.objects.author_posts(author=self).count() def get_name(self): return "{} {}".format(self.user.first_name, self.user.last_name)
class Post(TimeStampedModel): title = models.CharField( _("title"), max_length=200) slug = models.SlugField( _("slug"), unique=True) content = SimpleMDEField( _("Markdown content"), simplemde_options={ 'showIcons': ['heading-smaller', 'heading-bigger', 'horizontal-rule'], 'spellChecker': False, }) body = models.TextField( _("HTML content"), blank=True) description = models.TextField( _("HTML description"), blank=True) author = models.ForeignKey( settings.AUTH_USER_MODEL, verbose_name=_("author"), blank=True, null=True, on_delete=models.SET_NULL) pub_date = models.DateTimeField( _("publication date"), null=True, blank=True) objects = PublishedManager() class Meta: ordering = ['-pub_date', '-created'] verbose_name = _("post") verbose_name_plural = _("posts") def __str__(self): return self.title def __repr__(self): return "<Post: {}>".format(self.slug) def get_absolute_url(self): return reverse_lazy('blog:post', kwargs={'slug': self.slug}) def save(self, *args, **kwargs): content = re.split(r'(?<!-)----(?!-)', self.content, maxsplit=1) self.body = commonmark("".join(content)) self.description = commonmark(content[0]) return super().save(*args, **kwargs) save.alters_data = True
class Milestone(models.Model): name = models.CharField(max_length=200) description = SimpleMDEField('Project Description') project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="milestones", null=True, blank=True) creation_date = models.DateTimeField('Creation Time', auto_now_add=True) starting_date = models.DateTimeField('Starting Date', blank=True, null=True) due_date = models.DateTimeField('Due Date', blank=True, null=True) closing_date = models.DateTimeField('Closing Date', blank=True, null=True) def __str__(self): return self.name
class Article(models.Model): image = models.ImageField(_("image"), upload_to='uploads/%Y/%m/%d/', null=True, blank=True) subject = models.CharField(_("subject"), max_length=255) last_updated = models.DateTimeField(auto_now_add=True) user = models.ForeignKey("accounts.User", verbose_name=_("user"), on_delete=models.CASCADE) message = SimpleMDEField(verbose_name='message') created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.subject def get_page_count(self): count = self.pbjects.count() pages = count / 10 return math.ceil(pages) def has_many_pages(self, count=None): if count is None: count = self.get_page_count() return count > 5 def get_page_range(self): count = self.get_page_count() if self.has_many_pages(count): return range(1, 5) return range(1, count + 1) def get_last_ten_posts(self): return self.order_by('-created_at')[:10] def get_message_as_markdown(self): return mark_safe(markdown(self.message, safe_mode='escape')) class Meta: verbose_name = _("article") verbose_name_plural = _("articles")
class ProgrammingLanguage(models.Model): name = models.CharField(max_length=200, unique=True) slug = AutoSlugField(max_length=100, populate_from='name', editable=True, blank=True, db_index=True, unique=True) desc = SimpleMDEField(blank=True) desc_safe = models.TextField(blank=True) order = models.PositiveIntegerField(default=0) def __str__(self): return self.name def get_absolute_url(self): return reverse('profiles:language', args=[self.slug]) class Meta: ordering = ('-order', 'name')
class Page(models.Model): title = models.CharField(max_length=200) slug = AutoSlugField(max_length=50, populate_from='title', editable=True, blank=True, db_index=True, unique=True) content = SimpleMDEField(blank=True) content_safe = models.TextField(blank=True) desc = models.CharField(max_length=300, blank=True) public = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.title class Meta: ordering = ('-updated_at',) def get_absolute_url(self): return reverse('pages:detail', args=[self.slug])
class Technology(models.Model): name = models.CharField(max_length=200, unique=True) slug = AutoSlugField(max_length=100, populate_from='name', editable=True, blank=True, db_index=True, unique=True) desc = SimpleMDEField(blank=True) desc_safe = models.TextField(blank=True) order = models.PositiveIntegerField(default=0) class Meta: verbose_name_plural = 'Technologies' ordering = ('-order', 'name') def __str__(self): return self.name def get_absolute_url(self): return reverse('profiles:tech', args=[self.slug])
class Post(TimeStampedModel): title = models.CharField(_("title"), max_length=200) slug = models.SlugField(_("slug"), unique=True) content = SimpleMDEField(_("Markdown content")) body = models.TextField(_("HTML content"), blank=True) description = models.TextField(_("HTML description"), blank=True) author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("author"), blank=True, null=True, on_delete=models.SET_NULL) pub_date = models.DateTimeField(_("publication date"), null=True, blank=True) objects = PublishedManager() class Meta: ordering = ['-pub_date', '-created'] verbose_name = _("post") verbose_name_plural = _("posts") def __str__(self): return self.title def __repr__(self): return "<Post: {}>".format(self.slug) def get_absolute_url(self): return reverse_lazy('blog:post', kwargs={'slug': self.slug}) def save(self, *args, **kwargs): content = self.content.split("----", 1) self.body = markdown("".join(content)) self.description = markdown(content[0]) return super().save(*args, **kwargs) save.alters_data = True
class Comment(MPTTModel): post = models.ForeignKey('CmsPost', on_delete=models.CASCADE, verbose_name='Пост') author = models.ForeignKey('auth.User', verbose_name='Автор') text = SimpleMDEField(verbose_name='Текст') parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True, verbose_name='Відповідь на') is_deleted = models.BooleanField(default=False, verbose_name='Видалено') created_date = models.DateTimeField(default=timezone.now, verbose_name='Дата створення', unique=True) modifed_date = models.DateTimeField(null=True, blank=True, verbose_name='Дата редагування') def __str__(self): return self.text @property def short_text(self): return truncatechars(self.text, 50) class Meta: verbose_name = 'Коментар' verbose_name_plural = 'Коментарі' permissions = (('moderate_comment', 'Модерація коментарів'), ) class MPTTMeta: order_insertion_by = ['created_date']
class Entry(models.Model): title = models.CharField(max_length=4000, verbose_name=u'Title') content = SimpleMDEField(verbose_name=u'mardown content')
class Markdown(models.Model): title = models.CharField(max_length=32) content = SimpleMDEField()
class Profile(models.Model): user = models.OneToOneField(User, related_name='profile') languages = models.ManyToManyField(ProgrammingLanguage, related_name='+', blank=True) location = models.ForeignKey(Location, blank=True, null=True) rate = models.DecimalField(default=1, max_digits=5, decimal_places=2, db_index=True) is_available = models.BooleanField(default=False, db_index=True) name = models.CharField(max_length=200, blank=True) job_title = models.CharField(max_length=200, blank=True) birth_year = models.PositiveSmallIntegerField(null=True, blank=True) SEX_CHOICES = ( ('M', 'Male'), ('F', 'Female'), ) sex = models.CharField(max_length=1, choices=SEX_CHOICES, blank=True) avatar = ProcessedImageField(upload_to=upload_avatar, blank=True, processors=[ResizeToFill(320, 320)], format='JPEG', options={'quality': 75}) ENGLISH_CHOICES = ( ('N', 'Native'), ('E', 'Excellent'), ('G', 'Good Reading, Good Speaking'), ('R', 'Good Reading, Average Speaking'), ('E', 'Good Enough for Works'), ) english_level = models.CharField(choices=ENGLISH_CHOICES, blank=True, max_length=1, db_index=True) software = models.ManyToManyField(Software, related_name='+', blank=True) hardware = models.ManyToManyField(Hardware, related_name='+', blank=True) about = SimpleMDEField(blank=True) about_safe = models.TextField(blank=True) # social links homepage = models.URLField(max_length=200, blank=True) twitter = models.CharField(max_length=200, blank=True) github = models.CharField(max_length=200, blank=True) banned = models.BooleanField(default=False, db_index=True) banned_until = models.DateTimeField(null=True, blank=True) banned_reason = models.TextField(blank=True) total_points = models.PositiveIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) # this profile is ready once has skills to be updated is_ready = models.BooleanField(default=False, db_index=True) def __str__(self): return self.user.username def get_avatar_url(self): if self.avatar: return self.avatar.url return settings.PERSON_DEFAULT def get_name(self): if self.name: return self.name return self.user.username def get_age(self): if self.birth_year: year = timezone.now().year age = round(year - self.birth_year) if 10 <= age <= 80: return age return '' def get_techs_list(self): return TechnologyMasteringLevel.objects.filter( user=self.user, removed=False).order_by('-year_exp') def has_techs(self): return TechnologyMasteringLevel.objects.filter(user=self.user, removed=False).exists() def get_homepage_name(self): if self.homepage: o = urlparse(self.homepage) return o.netloc return '' def show_refs(self): if self.homepage or self.github or self.twitter: return True return False def show_gears(self): if self.software.exists() or self.hardware.exists(): return True return False def get_absolute_url(self): return reverse('profiles:profile', args=[self.user.username]) def build_search_text(self): name_ = unidecode(self.name) name = self.name if self.name == name_ else '{} {}'.format( self.name, name_) txt = '{} {} {} {}'.format(self.user.username, name, self.user.email, self.job_title) return txt def build_search_autocomplete(self): name_ = unidecode(self.name) name = self.name if self.name == name_ else '{} {}'.format( self.name, name_) txt = '{} {}'.format(self.user.username, name) return txt class Meta: ordering = ('-created_at', )
class Story(models.Model): DRAFT = 'draft' # visible just for you SHARED = 'shared' # share with specific user PUBLIC = 'public' # everyone can access that. STATUS_CHOICES = ( (DRAFT, 'draft'), (SHARED, 'shared'), (PUBLIC, 'public'), ) short_url = models.CharField(max_length=22, default=helpers.create_short_url, unique=True) title = models.CharField(max_length=500) slug = models.CharField( max_length=140, unique=True, blank=True ) # force the unicity of the slug (story lookup from the short_url) abstract = models.CharField(max_length=500, blank=True, null=True) contents = SimpleMDEField( verbose_name=u'mardown content', default='') # It will store the last markdown contents. metadata = JSONField(default=json.dumps({ 'title': { 'en': '', 'fr': '' }, 'abstract': { 'en': '', 'fr': '' } })) # it will contain, JSON fashion date = models.DateTimeField(blank=True, null=True) # date displayed (metadata) date_created = models.DateTimeField(auto_now_add=True) date_last_modified = models.DateTimeField(auto_now=True) status = models.CharField(max_length=10, choices=STATUS_CHOICES) owner = models.ForeignKey(User) # at least the first author, the one who owns the file. authors = models.ManyToManyField(User, related_name='authors', blank=True) # collaborators watchers = models.ManyToManyField(User, related_name='watchers', blank=True) # collaborators documents = models.ManyToManyField(Document, related_name='documents', through='Caption', blank=True) # the leading document(s), e.g. an interview covers = models.ManyToManyField(Document, related_name='covers', blank=True) tags = models.ManyToManyField(Tag, blank=True) # tags # cover thumbnail, e.g. http://www.eleganzadelgusto.com/wordpress/wp-content/uploads/2014/05/Marcello-Mastroianni-for-Arturo-Zavattini.jpg cover = models.URLField(max_length=500, blank=True, null=True) # cover copyright or caption, markdown flavoured. If any cover_copyright = models.CharField(max_length=140, blank=True, null=True) # set the plural name and fix the default sorting order class Meta: ordering = ('-date_last_modified', ) verbose_name_plural = 'stories' # get story path based on random generated shorten url def get_path(self): return os.path.join(self.owner.profile.get_path(), self.short_url + '.md') def __unicode__(self): return '%s - by %s' % (self.title, self.owner.username) # store into the whoosh index def store(self, ix=None): if ix is None: ix = helpers.get_whoosh_index() writer = ix.writer() writer.update_document( title=self.title, path=u"%s" % self.id, content=u"\n".join( BeautifulSoup( markdown(u"\n".join( filter(None, [self.title, self.abstract, self.contents])), extensions=['footnotes'])).findAll(text=True)), tags=u",".join([u'%s' % t.name for t in self.tags.all()]), classname=u"story") writer.commit() def save(self, *args, **kwargs): self.slug = slugify(self.title) try: metadata = json.loads(self.metadata) if 'title' not in metadata: metadata['title'] = {} if 'abstract' not in metadata: metadata['abstract'] = {} for default_language_code, label, language_code in settings.LANGUAGES: logger.debug(' lang:%s' % language_code) if language_code not in metadata['title']: metadata['title'][language_code] = self.title if language_code not in metadata['abstract']: metadata['abstract'][language_code] = self.abstract logger.debug('metadata %s' % metadata) self.metadata = json.dumps(metadata) except Exception as e: logger.exception(e) # reconcile metadata with the current languages super(Story, self).save(*args, **kwargs)
class PostTitle(models.Model): post = models.ForeignKey(Post, db_index=True) title = models.CharField(max_length=255) language = models.CharField(max_length=15, db_index=True, choices=settings.LANGUAGES) description = SimpleMDEField(max_length=80000) body = SimpleMDEField(max_length=80000) meta_title = SimpleMDEField(max_length=70, blank=True, null=True) meta_description = SimpleMDEField(max_length=156, blank=True, null=True) published = models.BooleanField(blank=True, default=False) is_draft = models.BooleanField(default=True, editable=False, db_index=True) public_post_title = models.OneToOneField( "self", on_delete=models.SET_NULL, related_name="post_draft", null=True, editable=False, ) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) published_date = models.DateTimeField(blank=True, null=True) class Meta: unique_together = ("post", "language", "is_draft") def get_absolute_url(self): from django.core.urlresolvers import reverse return reverse('post-detail', kwargs={ 'blog_slug': self.post.blog.slug, 'post_slug': self.post.slug }) def edited(self): if self.public_post_title: if all(( self.public_post_title.post == self.post, self.public_post_title.title == self.title, self.public_post_title.language == self.language, self.public_post_title.description == self.description, self.public_post_title.body == self.body, self.public_post_title.meta_title == self.meta_title, self.public_post_title.meta_description == self.meta_description, )): return False return True return False def create_public_post(self): publisher_public = PostTitle( post=self.post, title=self.title, language=self.language, description=self.description, body=self.body, meta_title=self.meta_title, meta_description=self.meta_description, is_draft=False, published=True, published_date=timezone.now(), ) publisher_public.save() self.public_post_title = publisher_public self.published = True self.publisher_edited = False self.published_date = timezone.now() self.save() def publish(self): if self.public_post_title is None: self.create_public_post() expire_blog_post(self) return True else: if self.edited(): publisher_public = self.public_post_title self.public_post_title = None publisher_public.delete() self.create_public_post() expire_blog_post(self) return True return False def unpublish(self): publisher_public = self.public_post_title self.public_post_title = None publisher_public.delete() self.published = False self.published_date = None expire_blog_post(self) self.save()