models.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. from django.db import models
  4. from .fields import CommaSeparatedCharField
  5. from .utils import ANGLES, merge_intervals
  6. from phonenumber_field.modelfields import PhoneNumberField
  7. class Contrib(models.Model):
  8. CONTRIB_CONNECT = 'connect'
  9. CONTRIB_SHARE = 'share'
  10. id = models.AutoField(primary_key=True, blank=False, null=False)
  11. name = models.CharField(
  12. 'Nom / Pseudo',
  13. max_length=30)
  14. contrib_type = models.CharField(
  15. 'Type de contribution',
  16. max_length=10, choices=(
  17. (CONTRIB_CONNECT, 'Me raccorder à internet'),
  18. (CONTRIB_SHARE, 'Partager une partie de ma connexion')
  19. ), default=None)
  20. latitude = models.FloatField()
  21. longitude = models.FloatField()
  22. phone = PhoneNumberField()
  23. email = models.EmailField(blank=True)
  24. access_type = models.CharField(
  25. 'Type de connexion',
  26. max_length=10, blank=True, choices=(
  27. ('vdsl', 'ADSL'),
  28. ('vdsl', 'VDSL'),
  29. ('fiber', 'Fibre optique'),
  30. ('cable', 'Coaxial (FTTLA)'),
  31. ))
  32. floor = models.PositiveIntegerField(
  33. 'étage',
  34. blank=True, null=True)
  35. floor_total = models.PositiveIntegerField(
  36. "mombre d'étages",
  37. blank=True, null=True)
  38. orientations = CommaSeparatedCharField(
  39. blank=True, null=True, max_length=100)
  40. roof = models.BooleanField(
  41. 'accès au toît',
  42. default=False)
  43. comment = models.TextField(
  44. 'commentaire',
  45. blank=True, null=True)
  46. privacy_name = models.BooleanField(
  47. 'nom/pseudo public',
  48. default=False)
  49. privacy_email = models.BooleanField(
  50. 'email public',
  51. default=False)
  52. privacy_coordinates = models.BooleanField(
  53. 'coordonnées GPS publiques',
  54. default=True)
  55. privacy_place_details = models.BooleanField(
  56. 'étage/orientations publiques',
  57. default=True)
  58. privacy_comment = models.BooleanField(
  59. 'commentaire public',
  60. default=False)
  61. date = models.DateTimeField(auto_now_add=True)
  62. STATUS_TOSTUDY = 'TOSTUDY'
  63. STATUS_TOCONNECT = 'TOCONNECT'
  64. STATUS_CONNECTED = 'CONNECTED'
  65. STATUS_WONTCONNECT = 'WONTCONNECT'
  66. CONNECTABILITY = (
  67. (STATUS_TOSTUDY, 'à étudier'),
  68. (STATUS_TOCONNECT, 'à connecter'),
  69. (STATUS_CONNECTED, 'connecté'),
  70. (STATUS_WONTCONNECT, 'pas connectable'),
  71. )
  72. status = models.CharField(
  73. blank=True,
  74. null=True,
  75. max_length=250,
  76. choices=CONNECTABILITY,
  77. default=STATUS_TOSTUDY)
  78. class Meta:
  79. managed = True
  80. db_table = 'contribs'
  81. verbose_name = 'contribution'
  82. PRIVACY_MAP = {
  83. 'name': 'privacy_name',
  84. 'comment': 'privacy_comment',
  85. 'floor': 'privacy_place_details',
  86. 'floor_total': 'privacy_place_details',
  87. 'orientations': 'privacy_place_details',
  88. 'roof': 'privacy_place_details',
  89. 'angles': 'privacy_place_details',
  90. }
  91. PUBLIC_FIELDS = set(PRIVACY_MAP.keys())
  92. def __str__(self):
  93. return '#{} {}'.format(self.pk, self.name)
  94. @property
  95. def angles(self):
  96. """Return a list of (start, stop) angles from cardinal orientations
  97. """
  98. # Cleanup
  99. if self.orientations is None:
  100. return []
  101. orientations = [o for o in self.orientations if o in ANGLES.keys()]
  102. # Hack to make leaflet-semicircle happy (drawing a full circle only
  103. # works with (0, 360))
  104. if len(orientations) == 8:
  105. return [[0, 360]]
  106. angles = [ANGLES[orientation] for orientation in self.orientations]
  107. angles.sort(key=lambda i: i[0]) # sort by x
  108. return merge_intervals(angles)
  109. def is_public(self):
  110. return self.privacy_coordinates
  111. def _may_be_public(self, field):
  112. return field in self.PUBLIC_FIELDS
  113. def _is_public(self, field):
  114. return getattr(self, self.PRIVACY_MAP[field])
  115. def get_public_field(self, field):
  116. """ Gets safely an attribute in its public form (if any)
  117. :param field: The field name
  118. :return: the field value, or None, if the field is private
  119. """
  120. if self._may_be_public(field) and self._is_public(field):
  121. v = getattr(self, field)
  122. if hasattr(v, '__call__'):
  123. return v()
  124. else:
  125. return v
  126. else:
  127. return None