# Path: newsarticles/models.py
# class Article(models.Model):
#     """
#     Base article contents. Should never change after initial scraping
#     """
#     news_source = models.ForeignKey(NewsSource, null=True, db_index=True)
#     url = models.CharField(max_length=1024, unique=True, db_index=True)
#     title = models.TextField()
#     author = models.CharField(max_length=1024, default="", blank=True)
#     bodytext = models.TextField()
#     orig_html = models.TextField(blank=True)
#     created = models.DateTimeField(auto_now_add=True, db_index=True)
#     last_modified = models.DateTimeField(auto_now=True)
# 
#     objects = ArticleQuerySet.as_manager()
# 
#     # Fields from classification/coding- move to UserCoding
#     relevant = models.NullBooleanField(db_index=True)
#     categories = models.ManyToManyField(Category, blank=True)
# 
#     def __str__(self):
#         return self.url[:90]
# 
#     def is_coded(self):
#         return hasattr(self, 'usercoding')
# 
#     def current_coding(self):
#         return getattr(self, 'usercoding', None)
# 
#     def is_relevant(self):
#         coding = self.current_coding()
#         return coding and coding.relevant
# 
#     def get_categories(self):
#         coding = self.current_coding()
#         if coding:
#             return coding.categories.all()
#         else:
#             return []
# 
#     # Deprecated, use news_source instead.
#     feedname = models.CharField(
#         max_length=1, editable=False, null=True, db_index=True)
# 
# class Category(models.Model):
# 
#     KINDS = OrderedDict([
#         ('crimes', 'Crimes'),
#         ('orgs', 'Justice Agencies / Agencies'),
#         ('policing', 'Policing'),
#         ('other', 'Misc.'),
#     ])
#     DEFAULT_KIND = 'other'
# 
#     title = models.CharField(max_length=256)
#     abbreviation = models.CharField(max_length=5)
#     active = models.BooleanField(default=True)
#     kind = models.CharField(
#         max_length=50, choices=KINDS.items(), default=DEFAULT_KIND)
#     created = models.DateTimeField(auto_now=False, auto_now_add=True)
# 
#     objects = CategoryQuerySet.as_manager()
# 
#     def __str__(self):
#         return '{} ({})'.format(self.title, self.abbreviation)
# 
#     class Meta:
#         ordering = ['kind', 'abbreviation']
# 
# class NewsSource(models.Model):
#     name = models.CharField(max_length=256)
#     short_name = models.CharField(max_length=256, db_index=True)
#     legacy_feed_id = models.CharField(max_length=8, blank=True, db_index=True)
# 
#     def __str__(self):
#         return self.name
# 
#     class Meta:
#         ordering = ['name']
# 
# class UserCoding(models.Model):
#     article = models.OneToOneField(Article, db_index=True)
#     date = models.DateTimeField(auto_now=True)
#     user = models.ForeignKey(User, db_index=True, null=True, blank=True,
#                              on_delete=models.SET_NULL)
# 
#     # Fields from classification/coding
#     relevant = models.BooleanField()
#     categories = models.ManyToManyField(Category, blank=True)
#     locations = models.TextField(default='[]', blank=True)
#     sentiment = models.IntegerField(
#         blank=True, null=True, choices=SENTIMENT_CHOICES)
# 
#     class Meta:
#         unique_together = (("article", "user"),)
# 
# SENTIMENT_CHOICES = (
#     (None, 'Not coded'),
#     (1, 'Positive'),
#     (0, 'Neutral'),
#     (-1, 'Negative'),
# )
# 
# Path: newsarticles/forms.py
# class GroupedMultModelChoiceField(ModelMultipleChoiceField):
#     def __init__(self, queryset, group_by_field, group_label=None, *args, **kwargs):
#         """
#         group_by_field is the name of a field on the model
#         group_label is a function to return a label for each choice group
#         """
#         super(GroupedMultModelChoiceField, self).__init__(queryset, *args, **kwargs)
#         self.group_by_field = group_by_field
#         if group_label is None:
#             self.group_label = lambda group: group
#         else:
#             self.group_label = group_label
# 
#     def _get_choices(self):
#         """
#         Exactly as per ModelChoiceField except returns new iterator class
#         """
#         if hasattr(self, '_choices'):
#             return self._choices
#         return GroupedModelChoiceIterator(self)
#     choices = property(_get_choices, ModelMultipleChoiceField._set_choices)


import json
import random
from datetime import datetime
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.db.models import Q, Max, Min
from django.shortcuts import render, get_object_or_404
from django import forms
from newsarticles.models import Article, Category, NewsSource, UserCoding, SENTIMENT_CHOICES
from newsarticles.forms import GroupedMultModelChoiceField

    dateRange = Article.objects.all().aggregate(minDate=Min('created'),
                                                maxDate=Max('created'))

    data = {
        'articles': _paginate(article_list, 20, page),
        'form': form,
        'dateRange': dateRange,
    }

    return render(request, 'newsarticles/articleList.html', data)

class CrosstabSearchForm(forms.Form):
    news_source = forms.ModelMultipleChoiceField(label='News Source',
                                         required=False,
                                         widget=forms.SelectMultiple(attrs={'class':'form-control', 'size':'10'}),
                                         queryset=NewsSource.objects.all())

    startDate = forms.DateField(label='Start Date',
                                widget=forms.DateInput(format="%m/%d/%Y", attrs={'class':'form-control'}),
                                required=False)

    endDate = forms.DateField(label='End Date',
                              widget=forms.DateInput(format="%m/%d/%Y", attrs={'class':'form-control'}),
                              required=False)

    category = GroupedMultModelChoiceField(label='Categories',
                                           required=False,
                                           queryset=Category.objects.active(),
                                           group_by_field='kind',

# Path: newsarticles/models.py
# class Article(models.Model):
#     """
#     Base article contents. Should never change after initial scraping
#     """
#     news_source = models.ForeignKey(NewsSource, null=True, db_index=True)
#     url = models.CharField(max_length=1024, unique=True, db_index=True)
#     title = models.TextField()
#     author = models.CharField(max_length=1024, default="", blank=True)
#     bodytext = models.TextField()
#     orig_html = models.TextField(blank=True)
#     created = models.DateTimeField(auto_now_add=True, db_index=True)
#     last_modified = models.DateTimeField(auto_now=True)
# 
#     objects = ArticleQuerySet.as_manager()
# 
#     # Fields from classification/coding- move to UserCoding
#     relevant = models.NullBooleanField(db_index=True)
#     categories = models.ManyToManyField(Category, blank=True)
# 
#     def __str__(self):
#         return self.url[:90]
# 
#     def is_coded(self):
#         return hasattr(self, 'usercoding')
# 
#     def current_coding(self):
#         return getattr(self, 'usercoding', None)
# 
#     def is_relevant(self):
#         coding = self.current_coding()
#         return coding and coding.relevant
# 
#     def get_categories(self):
#         coding = self.current_coding()
#         if coding:
#             return coding.categories.all()
#         else:
#             return []
# 
#     # Deprecated, use news_source instead.
#     feedname = models.CharField(
#         max_length=1, editable=False, null=True, db_index=True)
# 
# class Category(models.Model):
# 
#     KINDS = OrderedDict([
#         ('crimes', 'Crimes'),
#         ('orgs', 'Justice Agencies / Agencies'),
#         ('policing', 'Policing'),
#         ('other', 'Misc.'),
#     ])
#     DEFAULT_KIND = 'other'
# 
#     title = models.CharField(max_length=256)
#     abbreviation = models.CharField(max_length=5)
#     active = models.BooleanField(default=True)
#     kind = models.CharField(
#         max_length=50, choices=KINDS.items(), default=DEFAULT_KIND)
#     created = models.DateTimeField(auto_now=False, auto_now_add=True)
# 
#     objects = CategoryQuerySet.as_manager()
# 
#     def __str__(self):
#         return '{} ({})'.format(self.title, self.abbreviation)
# 
#     class Meta:
#         ordering = ['kind', 'abbreviation']
# 
# class NewsSource(models.Model):
#     name = models.CharField(max_length=256)
#     short_name = models.CharField(max_length=256, db_index=True)
#     legacy_feed_id = models.CharField(max_length=8, blank=True, db_index=True)
# 
#     def __str__(self):
#         return self.name
# 
#     class Meta:
#         ordering = ['name']
# 
# class UserCoding(models.Model):
#     article = models.OneToOneField(Article, db_index=True)
#     date = models.DateTimeField(auto_now=True)
#     user = models.ForeignKey(User, db_index=True, null=True, blank=True,
#                              on_delete=models.SET_NULL)
# 
#     # Fields from classification/coding
#     relevant = models.BooleanField()
#     categories = models.ManyToManyField(Category, blank=True)
#     locations = models.TextField(default='[]', blank=True)
#     sentiment = models.IntegerField(
#         blank=True, null=True, choices=SENTIMENT_CHOICES)
# 
#     class Meta:
#         unique_together = (("article", "user"),)
# 
# SENTIMENT_CHOICES = (
#     (None, 'Not coded'),
#     (1, 'Positive'),
#     (0, 'Neutral'),
#     (-1, 'Negative'),
# )
# 
# Path: newsarticles/forms.py
# class GroupedMultModelChoiceField(ModelMultipleChoiceField):
#     def __init__(self, queryset, group_by_field, group_label=None, *args, **kwargs):
#         """
#         group_by_field is the name of a field on the model
#         group_label is a function to return a label for each choice group
#         """
#         super(GroupedMultModelChoiceField, self).__init__(queryset, *args, **kwargs)
#         self.group_by_field = group_by_field
#         if group_label is None:
#             self.group_label = lambda group: group
#         else:
#             self.group_label = group_label
# 
#     def _get_choices(self):
#         """
#         Exactly as per ModelChoiceField except returns new iterator class
#         """
#         if hasattr(self, '_choices'):
#             return self._choices
#         return GroupedModelChoiceIterator(self)
#     choices = property(_get_choices, ModelMultipleChoiceField._set_choices)


# Path: newsarticles/views.py
import json
import random
from datetime import datetime
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.db.models import Q, Max, Min
from django.shortcuts import render, get_object_or_404
from django import forms
from newsarticles.models import Article, Category, NewsSource, UserCoding, SENTIMENT_CHOICES
from newsarticles.forms import GroupedMultModelChoiceField


    dateRange = Article.objects.all().aggregate(minDate=Min('created'),
                                                maxDate=Max('created'))

    data = {
        'articles': _paginate(article_list, 20, page),
        'form': form,
        'dateRange': dateRange,
    }

    return render(request, 'newsarticles/articleList.html', data)

class CrosstabSearchForm(forms.Form):
    news_source = forms.ModelMultipleChoiceField(label='News Source',
                                         required=False,
                                         widget=forms.SelectMultiple(attrs={'class':'form-control', 'size':'10'}),
                                         queryset=NewsSource.objects.all())

    startDate = forms.DateField(label='Start Date',
                                widget=forms.DateInput(format="%m/%d/%Y", attrs={'class':'form-control'}),
                                required=False)

    endDate = forms.DateField(label='End Date',
                              widget=forms.DateInput(format="%m/%d/%Y", attrs={'class':'form-control'}),
                              required=False)

    category = GroupedMultModelChoiceField(label='Categories',
                                           required=False,
                                           queryset=Category.objects.active(),
                                           group_by_field='kind',

                                           group_label=Category.KINDS.get,