models.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. from datetime import *
  2. from dateutil import relativedelta
  3. from django.db import models
  4. from django.db.models import permalink
  5. from django.utils.translation import ugettext_lazy as _
  6. from django.core.urlresolvers import reverse
  7. from django.contrib.auth.models import User
  8. from django.contrib.localflavor.us.models import PhoneNumberField, USStateField
  9. from fields import ZipCodeField
  10. from django_extensions.db.models import TimeStampedModel
  11. import os
  12. import csv
  13. import urllib
  14. # import pbp_com.settings as settings
  15. from django.conf import settings
  16. def get_lat_long(location):
  17. key = settings.GOOGLE_API_KEY
  18. output = "csv"
  19. location = urllib.quote_plus(location)
  20. request = "http://maps.google.com/maps/geo?q=%s&output=%s&key=%s" % (
  21. location,
  22. output,
  23. key,
  24. )
  25. data = urllib.urlopen(request).read()
  26. dlist = data.split(",")
  27. if dlist[0] == "200":
  28. return "%s, %s" % (dlist[2], dlist[3])
  29. else:
  30. return ""
  31. class Person(TimeStampedModel):
  32. """Person model."""
  33. GENDER_CHOICES = (
  34. (1, "Male"),
  35. (2, "Female"),
  36. )
  37. title = models.CharField(_("title"), blank=True, null=True, max_length=20)
  38. first_name = models.CharField(_("first name"), blank=True, max_length=100)
  39. middle_name = models.CharField(
  40. _("middle name"), blank=True, null=True, max_length=100
  41. )
  42. last_name = models.CharField(_("last name"), blank=True, max_length=100)
  43. nickname = models.CharField(_("nickname"), blank=True, null=True, max_length=100)
  44. suffix = models.CharField(_("suffix"), blank=True, null=True, max_length=20)
  45. slug = models.SlugField(_("slug"), unique=True)
  46. user = models.ForeignKey(
  47. User,
  48. blank=True,
  49. null=True,
  50. help_text="If the person is an existing user of your site.",
  51. )
  52. gender = models.PositiveSmallIntegerField(
  53. _("gender"), choices=GENDER_CHOICES, blank=True, null=True
  54. )
  55. birth_date = models.DateField(_("birth date"), blank=True, null=True)
  56. death_date = models.DateField(_("death date"), blank=True, null=True)
  57. phone = PhoneNumberField(blank=True)
  58. email = models.EmailField(blank=True)
  59. town = models.ForeignKey("Town", blank=True, null=True)
  60. class Meta:
  61. verbose_name = _("person")
  62. verbose_name_plural = _("people")
  63. ordering = ("last_name", "first_name")
  64. def __unicode__(self):
  65. return u"%s" % self.full_name
  66. @property
  67. def full_name(self):
  68. return u"%s %s" % (self.first_name, self.last_name)
  69. @property
  70. def age(self):
  71. if self.death_date:
  72. DELTA = self.death_date
  73. else:
  74. DELTA = datetime.today()
  75. return u"%s" % relativedelta.relativedelta(DELTA, self.birth_date).years
  76. @permalink
  77. def get_absolute_url(self):
  78. return ("di-person-detail", None, {"slug": self.slug})
  79. class Town(TimeStampedModel):
  80. """Town model."""
  81. name = models.CharField(_("name"), max_length=100)
  82. state = USStateField(_("state"))
  83. slug = models.SlugField(_("slug"), unique=True)
  84. in_coverage = models.BooleanField(_("in coverage"), default=False)
  85. zipcode = ZipCodeField(
  86. _("Zipcode"),
  87. blank=True,
  88. null=True,
  89. help_text="Use for a primary zipcode when town has multiple.",
  90. max_length=5,
  91. )
  92. class Meta:
  93. unique_together = (("name", "state",),)
  94. ordering = (
  95. "state",
  96. "name",
  97. )
  98. def __unicode__(self):
  99. return u"%s, %s" % (self.name, self.state)
  100. @permalink
  101. def get_absolute_url(self):
  102. return ("di-town-detail", None, {"slug": self.slug})
  103. class PopulationYear(TimeStampedModel):
  104. """ Population yaer model.
  105. Keeps track of a population count for a town in a given (usually census) year.
  106. """
  107. town = models.ForeignKey(Town)
  108. year = models.IntegerField(_("year"), max_length=4)
  109. population = models.IntegerField(_("population"), max_length=7)
  110. def __unicode__(self):
  111. return u"%s %s population" % (self.town, self.year)
  112. class TownInfo(TimeStampedModel):
  113. """ Town info model.
  114. Keeps track of various pieces of town info for our register.
  115. We create a separate model so that we can use a really simple
  116. setup for our legacy website and just rewrite this whole class
  117. when we're ready to implement some higher-level town info stuff.
  118. This way we do not have to delete town ids and mess up all related_name
  119. applications.
  120. """
  121. town = models.ForeignKey(Town)
  122. office = models.ForeignKey("Place")
  123. po_box = models.IntegerField(_("PO Box"))
  124. map = models.FileField(
  125. _("Town map"), blank=True, null=True, upload_to="directory/maps/"
  126. )
  127. time_info = models.TextField(_("Contact info"))
  128. description = models.TextField(_("Description"))
  129. officials = models.TextField(_("Officials"))
  130. tax_info = models.TextField(_("Tax info"))
  131. permits = models.TextField(_("Permits"))
  132. town_ordinances = models.TextField(_("Town ordinances"))
  133. post_offices = models.TextField(_("Post offices"))
  134. total_area = models.IntegerField(_("Total area"), help_text="In acres")
  135. land_area = models.IntegerField(_("Land"), help_text="In acres")
  136. bog_area = models.IntegerField(_("Bog"), help_text="In acres", default=0)
  137. flood_plain_area = models.IntegerField(
  138. _("Flood plain"), help_text="In acres", default=0
  139. )
  140. inland_water_area = models.IntegerField(
  141. _("Inland water"), help_text="In acres", default=0
  142. )
  143. shoreline = models.IntegerField(_("Shoreline"), help_text="In miles", default=0)
  144. populations = models.ManyToManyField(PopulationYear, blank=True, null=True)
  145. edu_contact = models.TextField(_("Education contact"))
  146. enrollment = models.TextField(_("Enrollment numbers"))
  147. fire_dept_info = models.TextField(_("Fire department"))
  148. cemetery_info = models.TextField(_("Cemeteries"), blank=True, null=True)
  149. trash_recycle_info = models.TextField(_("Trash & recycling"), blank=True, null=True)
  150. public_restrooms = models.TextField(_("Public restrooms"), blank=True, null=True)
  151. walking_trails = models.TextField(_("Walking trails"), blank=True, null=True)
  152. public_landings = models.TextField(_("Public landings"), blank=True, null=True)
  153. def __unicode__(self):
  154. return u"%s information" % (self.town)
  155. @permalink
  156. def get_absolute_url(self):
  157. return ("di-town-info", None, {"slug": self.town.slug})
  158. class Committee(TimeStampedModel):
  159. """Committee model."""
  160. title = models.CharField(_("title"), max_length=100)
  161. slug = models.SlugField(_("slug"), unique=True)
  162. town = models.ForeignKey(Town, related_name="town_committee")
  163. members = models.ManyToManyField(Person, blank=True, null=True)
  164. def __unicode__(self):
  165. return u"%s %s" % (self.town, self.title)
  166. def get_absolute_url(self):
  167. args = self.slug
  168. return reverse("di-committee-detail", args=args)
  169. class Point(TimeStampedModel):
  170. lat_lon = models.CharField(_("coordinates"), blank=True, null=True, max_length=255)
  171. address = models.CharField(_("address"), max_length=255)
  172. town = models.ForeignKey(Town)
  173. zipcode = models.CharField(_("zip"), max_length=10, blank=True)
  174. def __unicode__(self):
  175. return u"%s, %s" % (self.address, self.town)
  176. class Meta:
  177. verbose_name = _("point")
  178. verbose_name_plural = _("points")
  179. def save(self, *args, **kwargs):
  180. if not self.lat_lon:
  181. location = "%s +%s +%s +%s" % (
  182. self.address,
  183. self.town,
  184. self.town.state,
  185. self.zipcode,
  186. )
  187. self.lat_lon = get_lat_long(location)
  188. if not self.lat_lon:
  189. location = "%s +%s +%s" % (self.town, self.town.state, self.zipcode)
  190. self.lat_lon = get_lat_long(location)
  191. super(Point, self).save(*args, **kwargs)
  192. class Place(TimeStampedModel):
  193. """Place model for Directory application."""
  194. STATUS_CHOICES = (
  195. (0, "Inactive"),
  196. (1, "Active"),
  197. )
  198. point = models.ForeignKey(Point, blank=True, null=True)
  199. title = models.CharField(_("Title"), max_length=255)
  200. slug = models.SlugField(_("Slug"))
  201. description = models.TextField(_("Description"), blank=True, null=True)
  202. status = models.IntegerField(_("Status"), choices=STATUS_CHOICES, default=1)
  203. po_box = models.IntegerField(_("P.O. Box"), blank=True, null=True, max_length=5)
  204. po_box_town = models.ForeignKey(Town, blank=True, null=True)
  205. phone = PhoneNumberField(_("Phone"), blank=True, null=True)
  206. fax = PhoneNumberField(_("Fax"), blank=True, null=True)
  207. email = models.EmailField(_("Email"), blank=True, null=True)
  208. website = models.URLField(_("Website"), blank=True, null=True, verify_exists=False)
  209. def __unicode__(self):
  210. return self.title
  211. @permalink
  212. def get_absolute_url(self):
  213. return ("di-place-detail", None, {"slug": self.slug})
  214. class SchoolAdministrativeUnit(TimeStampedModel):
  215. """
  216. An SAU, as defined by the state of Maine.
  217. """
  218. name = models.CharField(_("name"), max_length=100)
  219. slug = models.SlugField(_("slug"), unique=True)
  220. union = models.IntegerField(_("union"), max_length=2, blank=True, null=True)
  221. # governor=models.ForeignKey(Board, blank=True, null=True)
  222. def __unicode__(self):
  223. return self.name
  224. @permalink
  225. def get_absolute_url(self):
  226. return ("di-sau-detail", None, {"slug": self.slug})
  227. class School(Place):
  228. """
  229. School model.
  230. A school derives from the Place model, adding a few school-specific fields
  231. """
  232. TYPE_CHOICES = (
  233. ("E", "Elementary School"),
  234. ("H", "High School"),
  235. ("C", "Combined School"),
  236. ("U", "College/University"),
  237. ("O", "Other"),
  238. )
  239. CLASS_CHOICES = (
  240. ("N", "None"),
  241. ("A", "A"),
  242. ("B", "B"),
  243. ("C", "C"),
  244. ("D", "D"),
  245. )
  246. REGION_CHOICES = (
  247. ("N", "None"),
  248. ("W", "West"),
  249. ("E", "East"),
  250. )
  251. short_title = models.CharField(_("short title"), max_length=30)
  252. type = models.CharField(_("type"), choices=TYPE_CHOICES, default="O", max_length=1)
  253. # enrollment=models.ManyToMany(Enrollment?)
  254. administration = models.ForeignKey(SchoolAdministrativeUnit)
  255. title_one_eligible = models.BooleanField(_("title one eligible"), default=False)
  256. title_one_recipient = models.BooleanField(_("title one recipient"), default=False)
  257. school_class = models.CharField(
  258. _("class"), max_length=1, choices=CLASS_CHOICES, default="N"
  259. )
  260. region = models.CharField(
  261. _("region"), max_length=2, choices=REGION_CHOICES, default="N"
  262. )
  263. mascot = models.CharField(_("mascot"), max_length=50, blank=True, null=True)
  264. athletic_director = models.ForeignKey(
  265. Person, related_name="athletic_director", blank=True, null=True
  266. )
  267. principal = models.ForeignKey(
  268. Person, related_name="principal", blank=True, null=True
  269. )
  270. @permalink
  271. def get_absolute_url(self):
  272. return ("di-school-detail", None, {"slug": self.slug})
  273. class PhoneBookEntry(TimeStampedModel):
  274. entry = models.CharField(_("entry"), max_length=100)
  275. phone = PhoneNumberField()
  276. town = models.ForeignKey(Town)
  277. owner = models.ForeignKey(Person, blank=True, null=True)
  278. related_place = models.ForeignKey(Place, blank=True, null=True)
  279. def __unicode__(self):
  280. return u"%s: %s" % (self.entry, self.phone)
  281. class Meta:
  282. verbose_name = _("phone book entry")
  283. verbose_name_plural = _("phone book entries")
  284. class PhoneBookEntryUpload(models.Model):
  285. data_file = models.FileField(
  286. _("data file (.csv)"),
  287. upload_to="temp",
  288. help_text=_("Select a .csv file of phone book data to upload."),
  289. )
  290. town = models.ForeignKey(Town)
  291. class Meta:
  292. verbose_name = _("phone book entry upload")
  293. verbose_name_plural = _("phone book entry uploads")
  294. def save(self):
  295. super(PhoneBookEntryUpload, self).save()
  296. self.process_datafile()
  297. super(PhoneBookEntryUpload, self).delete()
  298. def process_datafile(self):
  299. if os.path.isfile(self.data_file.path):
  300. entry_data = csv.reader(open(self.data_file.path), delimiter="\t")
  301. for row in entry_data:
  302. args = {}
  303. args["town"] = self.town
  304. args["entry"] = row[0]
  305. if len(row[1]) > 8 or len(row[1]) < 4:
  306. args["phone"] = row[1]
  307. else:
  308. args["phone"] = "207-" + row[1]
  309. entry = PhoneBookEntry.objects.create(**args)
  310. try:
  311. entry.save()
  312. except:
  313. pass