<commit_before>from datetime import datetime

from django.db import models
from django.contrib import admin
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django.contrib.contenttypes.models import ContentType

from ella.ellaadmin import widgets
from ella.photos.models import Photo
from ella.core.managers import RelatedManager
from ella.core.cache import get_cached_object, get_cached_list
from ella.core.models import Listing, Category, Author, Source

class Interviewee(models.Model):
    user = models.ForeignKey(User, null=True, blank=True)
    author = models.ForeignKey(Author, null=True, blank=True)
    name = models.CharField(_('Name'), maxlength=200, blank=True)
    slug = models.CharField(_('Slug'), maxlength=200)
    description = models.TextField(_('Description'), blank=True)

    class Meta:
        verbose_name = _('Interviewee')
        verbose_name_plural = _('Interviewees')
        ordering = ('name',)

    def __unicode__(self):
        if self.author_id:
            return unicode(get_cached_object(Author, pk=self.author_id))
        elif self.user_id:
            return unicode(get_cached_object(User, pk=self.user_id))
        return self.name


class Interview(models.Model):
    # Titles
    title = models.CharField(_('Title'), maxlength=255)
    upper_title = models.CharField(_('Upper title'), maxlength=255, blank=True)
    slug = models.CharField(_('Slug'), db_index=True, maxlength=255)

    # Contents
    perex = models.TextField(_('Perex'))
    content = models.TextField(_('Text'))

    reply_from = models.DateTimeField(_('Reply from'))
    reply_to = models.DateTimeField(_('Reply to'))

    ask_from = models.DateTimeField(_('Ask from'))
    ask_to = models.DateTimeField(_('Ask to'))

    # Authors and Sources
    authors = models.ManyToManyField(Author, verbose_name=_('Authors'))
    source = models.ForeignKey(Source, blank=True, null=True, verbose_name=_('Source'))
    interviewees = models.ManyToManyField(Interviewee, verbose_name=_('Interviewees'))

    category = models.ForeignKey(Category, verbose_name=_('Category'))

    # Main Photo
    photo = models.ForeignKey(Photo, blank=True, null=True, verbose_name=_('Photo'))

    objects = RelatedManager()


    def asking_started(self):
        now = datetime.now()
        return  self.ask_from <= now

    def asking_ended(self):
        now = datetime.now()
        return  self.ask_to > now

    def can_reply(self):
        now = datetime.now()
        return self.reply_from <= now < self.reply_to

    def can_ask(self):
        return self.asking_started() and not self.asking_ended()

    def get_questions(self):
        now = datetime.now()

        q = self.question_set.all()

        if now >= self.ask_to:
            q = q.order_by('submit_date')
        else:
            q = q.order_by('-submit_date')

        if now >= self.reply_from:
            # only answered questions
            q = q.filter(answer__pk__isnull=False).distinct()

        # TODO: caching
        return q

    def unanswered_questions(self):
        # TODO: caching
        q = self.question_set.all().order_by('submit_date').exclude(pk__in=[ q['id'] for q in self.question_set.filter(answer__pk__isnull=False).values('id') ])
        return q

    def get_interviewees(self, user=None):
        if not user:
            from ella.core.middleware import get_current_request
            request = get_current_request()
            user = request.user
        if not hasattr(self, '_interviewees'):
            if not user.is_authenticated() or not self.can_reply():
                self._interviewees = []
            else:
                # TODO: filter only those interviewees that can be replying now (permission-wise)
                self._interviewees = get_cached_list(Interviewee, interview__pk=self.pk)
        return self._interviewees

    def get_photo(self):
        if not hasattr(self, '_photo'):
            try:
                self._photo = get_cached_object(Photo, pk=self.photo_id)
            except Photo.DoesNotExist:
                self._photo = None
        return self._photo

    @property
    def main_listing(self):
        try:
            return get_cached_object(
                    Listing,
                    target_ct=ContentType.objects.get_for_model(self.__class__),
                    target_id=self.id,
                    category=self.category_id
)
        except Listing.DoesNotExist:
            return None

    def get_absolute_url(self):
        listing = self.main_listing
        if listing:
            return listing.get_absolute_url()

    def full_url(self):
        absolute_url = self.get_absolute_url()
        if absolute_url:
            return '<a href="%s">url</a>' % absolute_url
        return 'no url'
    full_url.allow_tags = True


    class Meta:
        verbose_name = _('Interview')
        verbose_name_plural = _('Interviews')
        ordering = ('-ask_from',)

    def __unicode__(self):
        return self.title


class Question(models.Model):
    interview = models.ForeignKey(Interview)
    content = models.TextField(_('Question text'))

    # author if is authorized
    user = models.ForeignKey(User, verbose_name=_('authorized author'), blank=True, null=True, related_name='interview_question_set')
    # author otherwise
    nickname = models.CharField(_("anonymous author's nickname"), maxlength=200, blank=True)
    email = models.EmailField(_('authors email (optional)'), blank=True)

    # authors ip address
    ip_address = models.IPAddressField(_('ip address'), blank=True, null=True)

    # comment metadata
    submit_date = models.DateTimeField(_('date/time submitted'), default=datetime.now, editable=True)
    is_public = models.BooleanField(_('is public'), default=True)

    def is_authorized(self):
        if self.user_id:
            return True
        return False

    @property
    def author(self):
        if self.is_authorized():
            user = get_cached_object(User, pk=self.user_id)
            return user.username
        return self.nickname

    @property
    def answers(self):
        if not hasattr(self, '_answers'):
            # TODO: caching
            self._answers = list(self.answer_set.all())
        return self._answers

    def answered(self):
        return bool(self.answers)

    class Meta:
        ordering = ('-submit_date',)
        verbose_name = _('Question')
        verbose_name_plural = _('Questions')


class Answer(models.Model):
    question = models.ForeignKey(Question)
    interviewee = models.ForeignKey(Interviewee)

    submit_date = models.DateTimeField(_('date/time submitted'), default=datetime.now)
    content = models.TextField(_('Answer text'))

    class Meta:
        ordering = ('-submit_date',)
        verbose_name = _('Answer')
        verbose_name_plural = _('Answer')

class AnswerInlineOptions(admin.TabularInline):
    model = Answer
    extra = 2

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'content':
            kwargs['widget'] = widgets.RichTextAreaWidget
        return super(self.__class__, self).formfield_for_dbfield(db_field, **kwargs)

class QuestionOptions(admin.ModelAdmin):
    list_display = ('interview', 'author', 'submit_date',)
    list_filter = ('submit_date',)
    search_fields = ('content', 'nickname', 'email',)
    inlines = (AnswerInlineOptions,)

class IntervieweeOptions(admin.ModelAdmin):
    list_display = ('__str__', 'user', 'author',)
    search_fields = ('user__first_name', 'user__last_name', 'name', 'description', 'slug', 'author__name',)
    prepopulated_fields = {'slug' : ('name',)}

from ella.core.admin.models import ListingInlineOptions, HitCountInlineOptions
from tagging.models import TaggingInlineOptions
class InterviewOptions(admin.ModelAdmin):
    list_display = ('title', 'category', 'ask_from', 'full_url',)
    list_filter = ('category__site', 'ask_from', 'category', 'authors',)
    date_hierarchy = 'ask_from'
    raw_id_fields = ('photo', 'interviewees',)
    search_fields = ('title', 'perex',)
    prepopulated_fields = {'slug' : ('title',)}
#    inlines = (ListingInlineOptions, TaggingInlineOptions, HitCountInlineOptions)
    inlines = (ListingInlineOptions, TaggingInlineOptions,)

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name in ('perex', 'content'):
            kwargs['widget'] = widgets.RichTextAreaWidget
        return super(self.__class__, self).formfield_for_dbfield(db_field, **kwargs)

admin.site.register(Interviewee, IntervieweeOptions)
admin.site.register(Interview, InterviewOptions)
admin.site.register(Question, QuestionOptions)

from ella.interviews import views
views.register_views()
<commit_msg>has_replies and replying started added<commit_after>from datetime import datetime

from django.db import models
from django.contrib import admin
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django.contrib.contenttypes.models import ContentType

from ella.ellaadmin import widgets
from ella.photos.models import Photo
from ella.core.managers import RelatedManager
from ella.core.cache import get_cached_object, get_cached_list
from ella.core.models import Listing, Category, Author, Source

class Interviewee(models.Model):
    user = models.ForeignKey(User, null=True, blank=True)
    author = models.ForeignKey(Author, null=True, blank=True)
    name = models.CharField(_('Name'), maxlength=200, blank=True)
    slug = models.CharField(_('Slug'), maxlength=200)
    description = models.TextField(_('Description'), blank=True)

    class Meta:
        verbose_name = _('Interviewee')
        verbose_name_plural = _('Interviewees')
        ordering = ('name',)

    def __unicode__(self):
        if self.author_id:
            return unicode(get_cached_object(Author, pk=self.author_id))
        elif self.user_id:
            return unicode(get_cached_object(User, pk=self.user_id))
        return self.name


class Interview(models.Model):
    # Titles
    title = models.CharField(_('Title'), maxlength=255)
    upper_title = models.CharField(_('Upper title'), maxlength=255, blank=True)
    slug = models.CharField(_('Slug'), db_index=True, maxlength=255)

    # Contents
    perex = models.TextField(_('Perex'))
    content = models.TextField(_('Text'))

    reply_from = models.DateTimeField(_('Reply from'))
    reply_to = models.DateTimeField(_('Reply to'))

    ask_from = models.DateTimeField(_('Ask from'))
    ask_to = models.DateTimeField(_('Ask to'))

    # Authors and Sources
    authors = models.ManyToManyField(Author, verbose_name=_('Authors'))
    source = models.ForeignKey(Source, blank=True, null=True, verbose_name=_('Source'))
    interviewees = models.ManyToManyField(Interviewee, verbose_name=_('Interviewees'))

    category = models.ForeignKey(Category, verbose_name=_('Category'))

    # Main Photo
    photo = models.ForeignKey(Photo, blank=True, null=True, verbose_name=_('Photo'))

    objects = RelatedManager()


    def asking_started(self):
        now = datetime.now()
        return  self.ask_from <= now

    def asking_ended(self):
        now = datetime.now()
        return  self.ask_to > now

    def replying_started(self):
        now = datetime.now()
        return  self.reply_from <= now

    def replying_ended(self):
        now = datetime.now()
        return  self.reply_to > now

    def has_replies(self):
        answers = Answer.objects.filter(question__interview=self).count()
        return answers > 0

    def can_reply(self):
        now = datetime.now()
        return self.reply_from <= now < self.reply_to

    def can_ask(self):
        return self.asking_started() and not self.asking_ended()

    def get_questions(self):
        now = datetime.now()

        q = self.question_set.all()

        if now >= self.ask_to:
            q = q.order_by('submit_date')
        else:
            q = q.order_by('-submit_date')

        if now >= self.reply_from:
            # only answered questions
            q = q.filter(answer__pk__isnull=False).distinct()

        # TODO: caching
        return q

    def unanswered_questions(self):
        # TODO: caching
        q = self.question_set.all().order_by('submit_date').exclude(pk__in=[ q['id'] for q in self.question_set.filter(answer__pk__isnull=False).values('id') ])
        return q

    def get_interviewees(self, user=None):
        if not user:
            from ella.core.middleware import get_current_request
            request = get_current_request()
            user = request.user
        if not hasattr(self, '_interviewees'):
            if not user.is_authenticated() or not self.can_reply():
                self._interviewees = []
            else:
                # TODO: filter only those interviewees that can be replying now (permission-wise)
                self._interviewees = get_cached_list(Interviewee, interview__pk=self.pk)
        return self._interviewees

    def get_photo(self):
        if not hasattr(self, '_photo'):
            try:
                self._photo = get_cached_object(Photo, pk=self.photo_id)
            except Photo.DoesNotExist:
                self._photo = None
        return self._photo

    @property
    def main_listing(self):
        try:
            return get_cached_object(
                    Listing,
                    target_ct=ContentType.objects.get_for_model(self.__class__),
                    target_id=self.id,
                    category=self.category_id
)
        except Listing.DoesNotExist:
            return None

    def get_absolute_url(self):
        listing = self.main_listing
        if listing:
            return listing.get_absolute_url()

    def full_url(self):
        absolute_url = self.get_absolute_url()
        if absolute_url:
            return '<a href="%s">url</a>' % absolute_url
        return 'no url'
    full_url.allow_tags = True


    class Meta:
        verbose_name = _('Interview')
        verbose_name_plural = _('Interviews')
        ordering = ('-ask_from',)

    def __unicode__(self):
        return self.title


class Question(models.Model):
    interview = models.ForeignKey(Interview)
    content = models.TextField(_('Question text'))

    # author if is authorized
    user = models.ForeignKey(User, verbose_name=_('authorized author'), blank=True, null=True, related_name='interview_question_set')
    # author otherwise
    nickname = models.CharField(_("anonymous author's nickname"), maxlength=200, blank=True)
    email = models.EmailField(_('authors email (optional)'), blank=True)

    # authors ip address
    ip_address = models.IPAddressField(_('ip address'), blank=True, null=True)

    # comment metadata
    submit_date = models.DateTimeField(_('date/time submitted'), default=datetime.now, editable=True)
    is_public = models.BooleanField(_('is public'), default=True)

    def is_authorized(self):
        if self.user_id:
            return True
        return False

    @property
    def author(self):
        if self.is_authorized():
            user = get_cached_object(User, pk=self.user_id)
            return user.username
        return self.nickname

    @property
    def answers(self):
        if not hasattr(self, '_answers'):
            # TODO: caching
            self._answers = list(self.answer_set.all())
        return self._answers

    def answered(self):
        return bool(self.answers)

    class Meta:
        ordering = ('-submit_date',)
        verbose_name = _('Question')
        verbose_name_plural = _('Questions')


class Answer(models.Model):
    question = models.ForeignKey(Question)
    interviewee = models.ForeignKey(Interviewee)

    submit_date = models.DateTimeField(_('date/time submitted'), default=datetime.now)
    content = models.TextField(_('Answer text'))

    class Meta:
        ordering = ('-submit_date',)
        verbose_name = _('Answer')
        verbose_name_plural = _('Answer')

class AnswerInlineOptions(admin.TabularInline):
    model = Answer
    extra = 2

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'content':
            kwargs['widget'] = widgets.RichTextAreaWidget
        return super(self.__class__, self).formfield_for_dbfield(db_field, **kwargs)

class QuestionOptions(admin.ModelAdmin):
    list_display = ('interview', 'author', 'submit_date',)
    list_filter = ('submit_date',)
    search_fields = ('content', 'nickname', 'email',)
    inlines = (AnswerInlineOptions,)

class IntervieweeOptions(admin.ModelAdmin):
    list_display = ('__str__', 'user', 'author',)
    search_fields = ('user__first_name', 'user__last_name', 'name', 'description', 'slug', 'author__name',)
    prepopulated_fields = {'slug' : ('name',)}

from ella.core.admin.models import ListingInlineOptions, HitCountInlineOptions
from tagging.models import TaggingInlineOptions
class InterviewOptions(admin.ModelAdmin):
    list_display = ('title', 'category', 'ask_from', 'full_url',)
    list_filter = ('category__site', 'ask_from', 'category', 'authors',)
    date_hierarchy = 'ask_from'
    raw_id_fields = ('photo', 'interviewees',)
    search_fields = ('title', 'perex',)
    prepopulated_fields = {'slug' : ('title',)}
#    inlines = (ListingInlineOptions, TaggingInlineOptions, HitCountInlineOptions)
    inlines = (ListingInlineOptions, TaggingInlineOptions,)

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name in ('perex', 'content'):
            kwargs['widget'] = widgets.RichTextAreaWidget
        return super(self.__class__, self).formfield_for_dbfield(db_field, **kwargs)

admin.site.register(Interviewee, IntervieweeOptions)
admin.site.register(Interview, InterviewOptions)
admin.site.register(Question, QuestionOptions)

from ella.interviews import views
views.register_views()

{'fraction_non_alphanumeric': 0.11339918522238965, 'fraction_numerical': 0.0021764607399966515, 'mean_word_length': 3.1519925857275255, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7358736', 'n_tokens_mistral': 5469, 'n_tokens_neox': 5220, 'n_words': 1133}