import re from django.db import models from django.db.models.signals import post_save, pre_delete from .search import Question as QuestionDoc, Answer as AnswerDoc tag_re = re.compile(r'<([^>]+)>') class User(models.Model): email = models.CharField(max_length=200) date_joined = models.DateTimeField() display_name = models.CharField(max_length=200) url = models.CharField(max_length=400) location = models.CharField(max_length=400) description = models.TextField() views = models.PositiveIntegerField() votes_up = models.PositiveIntegerField() votes_down = models.PositiveIntegerField() age = models.PositiveIntegerField() def to_search(self): return { 'display_name': self.display_name, 'url': self.url, } class Post(models.Model): owner = models.ForeignKey(User, blank=True, null=True) creation_date = models.DateTimeField() last_activity_date = models.DateTimeField() rating = models.IntegerField() body = models.TextField() comment_count = models.PositiveIntegerField() @property def comments(self): return self.comment_set.order_by('creation_date') def to_search(self): data = { '_id': self.pk, 'id': self.pk, 'creation_date': self.creation_date, 'last_activity_date': self.last_activity_date, 'body': self.body, 'rating': self.rating, 'comments': [c.to_search() for c in self.comments], 'comment_count': self.comment_count, } if self.owner: data['owner'] = self.owner.to_search() return data class Meta: abstract = True class Question(Post): answer_count = models.PositiveIntegerField() tags_string = models.TextField() title = models.CharField(max_length=1024) favorite_count = models.PositiveIntegerField() view_count = models.PositiveIntegerField() accepted_answer = models.ForeignKey('Answer', related_name='accepted_for', null=True, blank=True) last_editor = models.ForeignKey(User, null=True, blank=True, related_name='last_edited_questions') last_edit_date = models.DateTimeField(null=True, blank=True) @property def answers(self): return self.answer_set.order_by('-creation_date') @property def tags(self): return tag_re.findall(self.tags_string) def to_search(self): d = super(Question, self).to_search() d.update({ 'tags': self.tags, 'title': self.title, 'favorite_count': self.favorite_count, 'view_count': self.view_count, 'answer_count': self.answer_count, 'has_accepted_answer': bool(self.accepted_answer_id), }) if self.last_editor_id: try: d.update({ 'last_editor': self.last_editor.to_search(), 'last_edit_date': self.last_edit_date }) except models.ObjectDoesNotExist: pass return QuestionDoc(**d) class Answer(Post): question = models.ForeignKey(Question) def to_search(self): d = super(Answer, self).to_search() return AnswerDoc(meta={'id': d.pop('_id'), 'parent': self.question_id}, **d) class Comment(models.Model): owner = models.ForeignKey(User, blank=True, null=True) creation_date = models.DateTimeField() rating = models.IntegerField() text = models.TextField() class Meta: abstract = True def to_search(self): data = { 'creation_date': self.creation_date, 'rating': self.rating, 'text': self.text, } if self.owner: data['owner'] = self.owner.to_search() return data class QuestionComment(Comment): post = models.ForeignKey(Question, related_name='comment_set') class AnswerComment(Comment): post = models.ForeignKey(Answer, related_name='comment_set') def update_search(instance, **kwargs): instance.to_search().save() def remove_from_search(instance, **kwargs): instance.to_search().delete() post_save.connect(update_search, sender=Answer) post_save.connect(update_search, sender=Question) pre_delete.connect(remove_from_search, sender=Answer) pre_delete.connect(remove_from_search, sender=Question)