models.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import datetime
  2. from django.db import models
  3. from django.db.models.fields.related import \
  4. ReverseSingleRelatedObjectDescriptor
  5. from django.utils.encoding import python_2_unicode_compatible
  6. from django.utils.translation import get_language
  7. @python_2_unicode_compatible
  8. class Country(models.Model):
  9. # Table Column Fields
  10. name = models.CharField(max_length=50)
  11. def __str__(self):
  12. return self.name
  13. @python_2_unicode_compatible
  14. class Person(models.Model):
  15. # Table Column Fields
  16. name = models.CharField(max_length=128)
  17. person_country_id = models.IntegerField()
  18. # Relation Fields
  19. person_country = models.ForeignObject(
  20. Country,
  21. from_fields=['person_country_id'],
  22. to_fields=['id'],
  23. on_delete=models.CASCADE,
  24. )
  25. friends = models.ManyToManyField('self', through='Friendship', symmetrical=False)
  26. class Meta:
  27. ordering = ('name',)
  28. def __str__(self):
  29. return self.name
  30. @python_2_unicode_compatible
  31. class Group(models.Model):
  32. # Table Column Fields
  33. name = models.CharField(max_length=128)
  34. group_country = models.ForeignKey(Country, models.CASCADE)
  35. members = models.ManyToManyField(Person, related_name='groups', through='Membership')
  36. class Meta:
  37. ordering = ('name',)
  38. def __str__(self):
  39. return self.name
  40. @python_2_unicode_compatible
  41. class Membership(models.Model):
  42. # Table Column Fields
  43. membership_country = models.ForeignKey(Country, models.CASCADE)
  44. date_joined = models.DateTimeField(default=datetime.datetime.now)
  45. invite_reason = models.CharField(max_length=64, null=True)
  46. person_id = models.IntegerField()
  47. group_id = models.IntegerField()
  48. # Relation Fields
  49. person = models.ForeignObject(
  50. Person,
  51. from_fields=['membership_country', 'person_id'],
  52. to_fields=['person_country_id', 'id'],
  53. on_delete=models.CASCADE,
  54. )
  55. group = models.ForeignObject(
  56. Group,
  57. from_fields=['membership_country', 'group_id'],
  58. to_fields=['group_country', 'id'],
  59. on_delete=models.CASCADE,
  60. )
  61. class Meta:
  62. ordering = ('date_joined', 'invite_reason')
  63. def __str__(self):
  64. return "%s is a member of %s" % (self.person.name, self.group.name)
  65. class Friendship(models.Model):
  66. # Table Column Fields
  67. from_friend_country = models.ForeignKey(Country, models.CASCADE, related_name="from_friend_country")
  68. from_friend_id = models.IntegerField()
  69. to_friend_country_id = models.IntegerField()
  70. to_friend_id = models.IntegerField()
  71. # Relation Fields
  72. from_friend = models.ForeignObject(
  73. Person,
  74. on_delete=models.CASCADE,
  75. from_fields=['from_friend_country', 'from_friend_id'],
  76. to_fields=['person_country_id', 'id'],
  77. related_name='from_friend')
  78. to_friend_country = models.ForeignObject(
  79. Country,
  80. from_fields=['to_friend_country_id'],
  81. to_fields=['id'],
  82. related_name='to_friend_country',
  83. on_delete=models.CASCADE,
  84. )
  85. to_friend = models.ForeignObject(
  86. Person,
  87. from_fields=['to_friend_country_id', 'to_friend_id'],
  88. to_fields=['person_country_id', 'id'],
  89. related_name='to_friend',
  90. on_delete=models.CASCADE,
  91. )
  92. class ArticleTranslationDescriptor(ReverseSingleRelatedObjectDescriptor):
  93. """
  94. The set of articletranslation should not set any local fields.
  95. """
  96. def __set__(self, instance, value):
  97. if instance is None:
  98. raise AttributeError("%s must be accessed via instance" % self.field.name)
  99. setattr(instance, self.cache_name, value)
  100. if value is not None and not self.field.remote_field.multiple:
  101. setattr(value, self.field.related.get_cache_name(), instance)
  102. class ColConstraint(object):
  103. # Anything with as_sql() method works in get_extra_restriction().
  104. def __init__(self, alias, col, value):
  105. self.alias, self.col, self.value = alias, col, value
  106. def as_sql(self, compiler, connection):
  107. qn = compiler.quote_name_unless_alias
  108. return '%s.%s = %%s' % (qn(self.alias), qn(self.col)), [self.value]
  109. class ActiveTranslationField(models.ForeignObject):
  110. """
  111. This field will allow querying and fetching the currently active translation
  112. for Article from ArticleTranslation.
  113. """
  114. requires_unique_target = False
  115. def get_extra_restriction(self, where_class, alias, related_alias):
  116. return ColConstraint(alias, 'lang', get_language())
  117. def get_extra_descriptor_filter(self, instance):
  118. return {'lang': get_language()}
  119. def contribute_to_class(self, cls, name):
  120. super(ActiveTranslationField, self).contribute_to_class(cls, name)
  121. setattr(cls, self.name, ArticleTranslationDescriptor(self))
  122. @python_2_unicode_compatible
  123. class Article(models.Model):
  124. active_translation = ActiveTranslationField(
  125. 'ArticleTranslation',
  126. from_fields=['id'],
  127. to_fields=['article'],
  128. related_name='+',
  129. on_delete=models.CASCADE,
  130. null=True,
  131. )
  132. pub_date = models.DateField()
  133. def __str__(self):
  134. try:
  135. return self.active_translation.title
  136. except ArticleTranslation.DoesNotExist:
  137. return '[No translation found]'
  138. class NewsArticle(Article):
  139. pass
  140. class ArticleTranslation(models.Model):
  141. article = models.ForeignKey(Article, models.CASCADE)
  142. lang = models.CharField(max_length=2)
  143. title = models.CharField(max_length=100)
  144. body = models.TextField()
  145. abstract = models.CharField(max_length=400, null=True)
  146. class Meta:
  147. unique_together = ('article', 'lang')
  148. ordering = ('active_translation__title',)
  149. class ArticleTag(models.Model):
  150. article = models.ForeignKey(Article, models.CASCADE, related_name="tags", related_query_name="tag")
  151. name = models.CharField(max_length=255)
  152. class ArticleIdea(models.Model):
  153. articles = models.ManyToManyField(Article, related_name="ideas",
  154. related_query_name="idea_things")
  155. name = models.CharField(max_length=255)