Add basic geo modeling
parent
47a0b255ae
commit
2f4c614e3a
|
@ -1,5 +1,6 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Supporter, SupporterPromo, PromoImpressions
|
from .models import (Supporter, SupporterPromo,
|
||||||
|
PromoImpressions, GeoFilter)
|
||||||
|
|
||||||
|
|
||||||
class SupporterAdmin(admin.ModelAdmin):
|
class SupporterAdmin(admin.ModelAdmin):
|
||||||
|
@ -11,7 +12,7 @@ class SupporterAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
class ImpressionInline(admin.TabularInline):
|
class ImpressionInline(admin.TabularInline):
|
||||||
model = PromoImpressions
|
model = PromoImpressions
|
||||||
readonly_fields = ('date', 'offers', 'views', 'clicks', 'view_ratio', 'click_ratio')
|
readonly_fields = ('date', 'promo', 'offers', 'views', 'clicks', 'view_ratio', 'click_ratio')
|
||||||
extra = 0
|
extra = 0
|
||||||
can_delete = False
|
can_delete = False
|
||||||
max_num = 15
|
max_num = 15
|
||||||
|
@ -37,3 +38,4 @@ class SupporterPromoAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
admin.site.register(Supporter, SupporterAdmin)
|
admin.site.register(Supporter, SupporterAdmin)
|
||||||
admin.site.register(SupporterPromo, SupporterPromoAdmin)
|
admin.site.register(SupporterPromo, SupporterPromoAdmin)
|
||||||
|
admin.site.register(GeoFilter)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
import django_countries.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('donate', '0004_rebase-impressions-on-base'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Country',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('country', django_countries.fields.CountryField(unique=True, max_length=2)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='GeoFilter',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
|
('filter_type', models.CharField(default=b'', max_length=20, verbose_name='Filter Type', choices=[(b'exclude', b'Exclude'), (b'include', b'Include')])),
|
||||||
|
('countries', models.ManyToManyField(related_name='filters', null=True, to='donate.Country', blank=True)),
|
||||||
|
('promo', models.ForeignKey(related_name='geo_filters', blank=True, to='donate.SupporterPromo', null=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,25 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
from django_countries import countries
|
||||||
|
|
||||||
|
|
||||||
|
def add_data(apps, schema_editor):
|
||||||
|
# We can't import the Person model directly as it may be a newer
|
||||||
|
# version than this migration expects. We use the historical version.
|
||||||
|
Country = apps.get_model("donate", "Country")
|
||||||
|
for code, name in list(countries):
|
||||||
|
Country.objects.get_or_create(country=code)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('donate', '0005_add-geo-filters'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(add_data),
|
||||||
|
]
|
|
@ -4,6 +4,8 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
from django_countries.fields import CountryField
|
||||||
|
|
||||||
from readthedocs.donate.utils import get_ad_day
|
from readthedocs.donate.utils import get_ad_day
|
||||||
from readthedocs.projects.models import Project
|
from readthedocs.projects.models import Project
|
||||||
|
|
||||||
|
@ -14,6 +16,11 @@ DISPLAY_CHOICES = (
|
||||||
('search', 'Search Pages'),
|
('search', 'Search Pages'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FILTER_CHOICES = (
|
||||||
|
('exclude', 'Exclude'),
|
||||||
|
('include', 'Include'),
|
||||||
|
)
|
||||||
|
|
||||||
OFFERS = 'offers'
|
OFFERS = 'offers'
|
||||||
VIEWS = 'views'
|
VIEWS = 'views'
|
||||||
CLICKS = 'clicks'
|
CLICKS = 'clicks'
|
||||||
|
@ -167,3 +174,26 @@ class ProjectImpressions(BaseImpression):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('project', 'promo', 'date')
|
unique_together = ('project', 'promo', 'date')
|
||||||
|
|
||||||
|
|
||||||
|
class Country(models.Model):
|
||||||
|
country = CountryField(unique=True)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return unicode(self.country.name)
|
||||||
|
|
||||||
|
|
||||||
|
class GeoFilter(models.Model):
|
||||||
|
promo = models.ForeignKey(SupporterPromo, related_name='geo_filters',
|
||||||
|
blank=True, null=True)
|
||||||
|
filter_type = models.CharField(_('Filter Type'), max_length=20,
|
||||||
|
choices=FILTER_CHOICES, default='')
|
||||||
|
countries = models.ManyToManyField(Country, related_name='filters',
|
||||||
|
blank=True, null=True)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
codes = []
|
||||||
|
for code in self.countries.values_list('country'):
|
||||||
|
codes.append(code[0])
|
||||||
|
return "Filter for {promo} that {type}s: {countries}".format(
|
||||||
|
promo=self.promo.name, type=self.filter_type, countries=','.join(codes))
|
||||||
|
|
|
@ -39,7 +39,7 @@ class DomainInline(admin.TabularInline):
|
||||||
|
|
||||||
class ImpressionInline(admin.TabularInline):
|
class ImpressionInline(admin.TabularInline):
|
||||||
model = ProjectImpressions
|
model = ProjectImpressions
|
||||||
readonly_fields = ('date', 'offers', 'views', 'clicks', 'view_ratio', 'click_ratio')
|
readonly_fields = ('date', 'promo', 'offers', 'views', 'clicks', 'view_ratio', 'click_ratio')
|
||||||
extra = 0
|
extra = 0
|
||||||
can_delete = False
|
can_delete = False
|
||||||
max_num = 15
|
max_num = 15
|
||||||
|
|
|
@ -189,6 +189,7 @@ INSTALLED_APPS = [
|
||||||
'copyright',
|
'copyright',
|
||||||
'textclassifier',
|
'textclassifier',
|
||||||
'annoying',
|
'annoying',
|
||||||
|
'django_countries',
|
||||||
|
|
||||||
# Celery bits
|
# Celery bits
|
||||||
'djcelery',
|
'djcelery',
|
||||||
|
|
|
@ -21,6 +21,8 @@ requests==2.3.0
|
||||||
slumber==0.6.0
|
slumber==0.6.0
|
||||||
lxml==3.3.5
|
lxml==3.3.5
|
||||||
|
|
||||||
|
django-countries==3.4.1
|
||||||
|
|
||||||
# Basic tools
|
# Basic tools
|
||||||
redis==2.10.3
|
redis==2.10.3
|
||||||
celery==3.1.18
|
celery==3.1.18
|
||||||
|
|
Loading…
Reference in New Issue