Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class AbstractPost(DatedModel):
- """ Represents a forum post. A forum post is always linked to a topic. """
- topic = models.ForeignKey(
- 'forum_conversation.Topic', related_name='posts', on_delete=models.CASCADE,
- verbose_name=_('Topic'),
- )
- poster = models.ForeignKey(
- settings.AUTH_USER_MODEL, related_name='posts',
- blank=True, null=True, on_delete=models.CASCADE, verbose_name=_('Poster'),
- )
- anonymous_key = models.CharField(
- max_length=100, blank=True, null=True, verbose_name=_('Anonymous user forum key'),
- )
- # Each post can have its own subject. The subject of the thread corresponds to the
- # one associated with the first post
- subject = models.CharField(verbose_name=_('Subject'), max_length=255)
- # Content
- content = MarkupTextField(
- validators=[
- validators.NullableMaxLengthValidator(machina_settings.POST_CONTENT_MAX_LENGTH),
- ],
- verbose_name=_('Content'),
- )
- # Username: if the user creating a topic post is not authenticated, he must enter a username
- username = models.CharField(max_length=155, blank=True, null=True, verbose_name=_('Username'))
- # A post can be approved before publishing ; defaults to True
- approved = models.BooleanField(default=True, db_index=True, verbose_name=_('Approved'))
- # The user can choose if they want to display their signature with the content of the post
- enable_signature = models.BooleanField(
- default=True, db_index=True, verbose_name=_('Attach a signature'),
- )
- # A post can be edited for several reason (eg. moderation) ; the reason why it has been
- # updated can be specified
- update_reason = models.CharField(
- max_length=255, blank=True, null=True, verbose_name=_('Update reason'),
- )
- # Tracking data
- updated_by = models.ForeignKey(
- settings.AUTH_USER_MODEL, editable=False, blank=True, null=True, on_delete=models.SET_NULL,
- verbose_name=_('Lastly updated by'),
- )
- updates_count = models.PositiveIntegerField(
- editable=False, blank=True, default=0, verbose_name=_('Updates count'),
- )
- objects = models.Manager()
- approved_objects = ApprovedManager()
- if settings.MACHINA_SEARCH_ENGINE == 'postgres': # для постгрес-поиска нужно создать специальные поля
- from django.contrib.postgres.search import SearchVectorField
- content_search = SearchVectorField(null=True)
- class Meta:
- abstract = True
- app_label = 'forum_conversation'
- ordering = ['created', ]
- get_latest_by = 'created'
- verbose_name = _('Post')
- verbose_name_plural = _('Posts')
- if settings.MACHINA_SEARCH_ENGINE == 'postgres': # индексируем спец-поля в постгресе
- from django.contrib.postgres.indexes import GinIndex
- indexes = [ GinIndex(name='content_index', fields=["content_search"]) ]
- def __str__(self):
- return self.subject
- @property
- def is_topic_head(self):
- """ Returns ``True`` if the post is the first post of the topic. """
- return self.topic.first_post.id == self.id if self.topic.first_post else False
- @property
- def is_topic_tail(self):
- """ Returns ``True`` if the post is the last post of the topic. """
- return self.topic.last_post.id == self.id if self.topic.last_post else False
- @property
- def is_alone(self):
- """ Returns ``True`` if the post is the only single post of the topic. """
- return self.topic.posts.count() == 1
- @property
- def position(self):
- """ Returns an integer corresponding to the position of the post in the topic. """
- position = self.topic.posts.filter(Q(created__lt=self.created) | Q(id=self.id)).count()
- return position
- def clean(self):
- """ Validates the post instance. """
- super().clean()
- # At least a poster (user) or a session key must be associated with
- # the post.
- if self.poster is None and self.anonymous_key is None:
- raise ValidationError(
- _('A user id or an anonymous key must be associated with a post.'),
- )
- if self.poster and self.anonymous_key:
- raise ValidationError(
- _('A user id or an anonymous key must be associated with a post, but not both.'),
- )
- if self.anonymous_key and not self.username:
- raise ValidationError(_('A username must be specified if the poster is anonymous'))
- def save(self, *args, **kwargs):
- """ Saves the post instance. """
- new_post = self.pk is None
- super().save(*args, **kwargs)
- # Ensures that the subject of the thread corresponds to the one associated
- # with the first post. Do the same with the 'approved' flag.
- if (new_post and self.topic.first_post is None) or self.is_topic_head:
- if self.subject != self.topic.subject or self.approved != self.topic.approved:
- self.topic.subject = self.subject
- self.topic.approved = self.approved
- # Trigger the topic-level trackers update
- self.topic.update_trackers()
- def delete(self, using=None):
- """ Deletes the post instance. """
- if self.is_alone:
- # The default way of operating is to trigger the deletion of the associated topic
- # only if the considered post is the only post embedded in the topic
- self.topic.delete()
- else:
- super(AbstractPost, self).delete(using)
- self.topic.update_trackers()
Advertisement
Add Comment
Please, Sign In to add comment