|
@@ -0,0 +1,173 @@
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+from __future__ import unicode_literals
|
|
|
+
|
|
|
+from django.db import models
|
|
|
+from django.core.validators import MaxValueValidator
|
|
|
+from django.core.exceptions import ValidationError
|
|
|
+
|
|
|
+from coin.members.models import count_active_members
|
|
|
+from coin.offers.models import count_active_subscriptions
|
|
|
+
|
|
|
+# API version, see http://db.ffdn.org/format
|
|
|
+API_VERSION = "0.1"
|
|
|
+
|
|
|
+TECHNOLOGIES = (('ftth', 'FTTH'),
|
|
|
+ ('dsl', '*DSL'),
|
|
|
+ ('wifi', 'WiFi'))
|
|
|
+
|
|
|
+
|
|
|
+class SingleInstanceMixin(object):
|
|
|
+ """Makes sure that no more than one instance of a given model is created."""
|
|
|
+
|
|
|
+ def clean(self):
|
|
|
+ model = self.__class__
|
|
|
+ if (model.objects.count() > 0 and self.id != model.objects.get().id):
|
|
|
+ raise ValidationError("Can only create 1 instance of %s" % model.__name__)
|
|
|
+ super(SingleInstanceMixin, self).clean()
|
|
|
+
|
|
|
+
|
|
|
+class ISPInfo(SingleInstanceMixin, models.Model):
|
|
|
+ """http://db.ffdn.org/format
|
|
|
+
|
|
|
+ The naming convention is different from Python/django so that it
|
|
|
+ matches exactly the format (which uses CamelCase...)
|
|
|
+ """
|
|
|
+ name = models.CharField(max_length=512,
|
|
|
+ help_text="The ISP's name")
|
|
|
+ # Length required by the spec
|
|
|
+ shortname = models.CharField(max_length=15, blank=True,
|
|
|
+ help_text="Shorter name")
|
|
|
+ description = models.TextField(blank=True,
|
|
|
+ help_text="Short text describing the project")
|
|
|
+ logoURL = models.URLField(blank=True,
|
|
|
+ verbose_name="logo URL",
|
|
|
+ help_text="HTTP(S) URL of the ISP's logo")
|
|
|
+ website = models.URLField(blank=True,
|
|
|
+ help_text='URL to the official website')
|
|
|
+ email = models.EmailField(max_length=254,
|
|
|
+ help_text="Contact email address")
|
|
|
+ mainMailingList = models.EmailField(max_length=254, blank=True,
|
|
|
+ verbose_name="main mailing list",
|
|
|
+ help_text="Main public mailing-list")
|
|
|
+ creationDate = models.DateField(blank=True, null=True,
|
|
|
+ verbose_name="creation date",
|
|
|
+ help_text="Date of creation for legal structure")
|
|
|
+ ffdnMemberSince = models.DateField(blank=True, null=True,
|
|
|
+ verbose_name="FFDN member since",
|
|
|
+ help_text="Date at wich the ISP joined the Federation")
|
|
|
+ # TODO: choice field
|
|
|
+ progressStatus = models.PositiveSmallIntegerField(
|
|
|
+ validators=[MaxValueValidator(7)],
|
|
|
+ blank=True, null=True, verbose_name='progress status',
|
|
|
+ help_text="Progression status of the ISP")
|
|
|
+ # TODO: better model for coordinates
|
|
|
+ latitude = models.FloatField(blank=True, null=True,
|
|
|
+ help_text="Coordinates of the registered office (latitude)")
|
|
|
+ longitude = models.FloatField(blank=True, null=True,
|
|
|
+ help_text="Coordinates of the registered office (longitude)")
|
|
|
+
|
|
|
+ # Uncomment this if you want to manage these counters by hand.
|
|
|
+ #member_count = models.PositiveIntegerField(help_text="Number of members")
|
|
|
+ #subscriber_count = models.PositiveIntegerField(
|
|
|
+ # help_text="Number of subscribers to an internet access")
|
|
|
+
|
|
|
+ @property
|
|
|
+ def memberCount(self):
|
|
|
+ """Number of members"""
|
|
|
+ return count_active_members()
|
|
|
+
|
|
|
+ @property
|
|
|
+ def subscriberCount(self):
|
|
|
+ """Number of subscribers to an internet access"""
|
|
|
+ return count_active_subscriptions()
|
|
|
+
|
|
|
+ @property
|
|
|
+ def version(self):
|
|
|
+ """Version of the API"""
|
|
|
+ return API_VERSION
|
|
|
+
|
|
|
+ def get_absolute_url(self):
|
|
|
+ return '/isp.json'
|
|
|
+
|
|
|
+ def to_dict(self):
|
|
|
+ data = dict()
|
|
|
+ # These are required
|
|
|
+ for f in ('version', 'name', 'email', 'memberCount', 'subscriberCount'):
|
|
|
+ data[f] = getattr(self, f)
|
|
|
+
|
|
|
+ # These are optional
|
|
|
+ for f in ('shortname', 'description', 'logoURL', 'website',
|
|
|
+ 'mainMailingList', 'progressStatus'):
|
|
|
+ if getattr(self, f):
|
|
|
+ data[f] = getattr(self, f)
|
|
|
+
|
|
|
+ # Dates
|
|
|
+ for d in ('creationDate', 'ffdnMemberSince'):
|
|
|
+ if getattr(self, d):
|
|
|
+ data[d] = getattr(self, d).isoformat()
|
|
|
+
|
|
|
+ # Hackish for now
|
|
|
+ if self.latitude or self.longitude:
|
|
|
+ data['coordinates'] = { "latitude": self.latitude,
|
|
|
+ "longitude": self.longitude }
|
|
|
+
|
|
|
+ # Related objects
|
|
|
+ data['coveredAreas'] = [c.to_dict() for c in self.coveredarea_set.all()]
|
|
|
+ otherwebsites = self.otherwebsite_set.all()
|
|
|
+ if otherwebsites:
|
|
|
+ data['otherWebsites'] = { site.name: site.url for site in otherwebsites }
|
|
|
+ chatrooms = self.chatroom_set.all()
|
|
|
+ if chatrooms:
|
|
|
+ data['chatrooms'] = [chatroom.url for chatroom in chatrooms]
|
|
|
+ if hasattr(self, 'registeredoffice'):
|
|
|
+ data['registeredOffice'] = self.registeredoffice.to_dict()
|
|
|
+
|
|
|
+ return data
|
|
|
+
|
|
|
+ def __unicode__(self):
|
|
|
+ return self.name
|
|
|
+
|
|
|
+
|
|
|
+class OtherWebsite(models.Model):
|
|
|
+ name = models.CharField(max_length=512)
|
|
|
+ url = models.URLField(verbose_name="URL")
|
|
|
+ isp = models.ForeignKey(ISPInfo)
|
|
|
+
|
|
|
+
|
|
|
+class RegisteredOffice(models.Model):
|
|
|
+ """ http://json-schema.org/address """
|
|
|
+ post_office_box = models.CharField(max_length=512, blank=True)
|
|
|
+ extended_address = models.CharField(max_length=512, blank=True)
|
|
|
+ street_address = models.CharField(max_length=512, blank=True)
|
|
|
+ locality = models.CharField(max_length=512)
|
|
|
+ region = models.CharField(max_length=512)
|
|
|
+ postal_code = models.CharField(max_length=512, blank=True)
|
|
|
+ country_name = models.CharField(max_length=512)
|
|
|
+ isp = models.OneToOneField(ISPInfo)
|
|
|
+
|
|
|
+ def to_dict(self):
|
|
|
+ d = dict()
|
|
|
+ for field in ('post_office_box', 'extended_address', 'street_address',
|
|
|
+ 'locality', 'region', 'postal_code', 'country_name'):
|
|
|
+ if getattr(self, field):
|
|
|
+ key = field.replace('_', '-')
|
|
|
+ d[key] = getattr(self, field)
|
|
|
+ return d
|
|
|
+
|
|
|
+
|
|
|
+class ChatRoom(models.Model):
|
|
|
+ url = models.CharField(verbose_name="URL", max_length=256)
|
|
|
+ isp = models.ForeignKey(ISPInfo)
|
|
|
+
|
|
|
+
|
|
|
+class CoveredArea(models.Model):
|
|
|
+ name = models.CharField(max_length=512)
|
|
|
+ # TODO: we must allow multiple values
|
|
|
+ technologies = models.CharField(choices=TECHNOLOGIES, max_length=16)
|
|
|
+ # TODO: find a geojson library
|
|
|
+ #area =
|
|
|
+ isp = models.ForeignKey(ISPInfo)
|
|
|
+
|
|
|
+ def to_dict(self):
|
|
|
+ return {"name": self.name,
|
|
|
+ "technologies": [self.technologies]}
|