You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

abstract_models.py 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import hashlib
  2. import random
  3. from django.utils import six
  4. from django.db import models
  5. from django.utils.encoding import python_2_unicode_compatible
  6. from django.utils.translation import ugettext_lazy as _, pgettext_lazy
  7. from django.core.urlresolvers import reverse
  8. from oscar.core.compat import AUTH_USER_MODEL
  9. @python_2_unicode_compatible
  10. class AbstractWishList(models.Model):
  11. """
  12. Represents a user's wish lists of products.
  13. A user can have multiple wish lists, move products between them, etc.
  14. """
  15. # Only authenticated users can have wishlists
  16. owner = models.ForeignKey(AUTH_USER_MODEL, related_name='wishlists',
  17. verbose_name=_('Owner'))
  18. name = models.CharField(verbose_name=_('Name'), default=_('Default'),
  19. max_length=255)
  20. #: This key acts as primary key and is used instead of an int to make it
  21. #: harder to guess
  22. key = models.CharField(_('Key'), max_length=6, db_index=True, unique=True,
  23. editable=False)
  24. # Oscar core does not support public or shared wishlists at the moment, but
  25. # all the right hooks should be there
  26. PUBLIC, PRIVATE, SHARED = ('Public', 'Private', 'Shared')
  27. VISIBILITY_CHOICES = (
  28. (PRIVATE, _('Private - Only the owner can see the wish list')),
  29. (SHARED, _('Shared - Only the owner and people with access to the'
  30. ' obfuscated link can see the wish list')),
  31. (PUBLIC, _('Public - Everybody can see the wish list')),
  32. )
  33. visibility = models.CharField(_('Visibility'), max_length=20,
  34. default=PRIVATE, choices=VISIBILITY_CHOICES)
  35. # Convention: A user can have multiple wish lists. The last created wish
  36. # list for a user shall be her "default" wish list.
  37. # If an UI element only allows adding to wish list without
  38. # specifying which one , one shall use the default one.
  39. # That is a rare enough case to handle it by convention instead of a
  40. # BooleanField.
  41. date_created = models.DateTimeField(
  42. _('Date created'), auto_now_add=True, editable=False)
  43. def __str__(self):
  44. return u"%s's Wish List '%s'" % (self.owner, self.name)
  45. def save(self, *args, **kwargs):
  46. if not self.pk or kwargs.get('force_insert', False):
  47. self.key = self.__class__.random_key()
  48. super(AbstractWishList, self).save(*args, **kwargs)
  49. @classmethod
  50. def random_key(cls, length=6):
  51. """
  52. Get a unique random generated key based on SHA-1 and owner
  53. """
  54. while True:
  55. rand = six.text_type(random.random()).encode('utf8')
  56. key = hashlib.sha1(rand).hexdigest()[:length]
  57. if not cls._default_manager.filter(key=key).exists():
  58. return key
  59. def is_allowed_to_see(self, user):
  60. if self.visibility in (self.PUBLIC, self.SHARED):
  61. return True
  62. else:
  63. return user == self.owner
  64. def is_allowed_to_edit(self, user):
  65. # currently only the owner can edit her wish list
  66. return user == self.owner
  67. class Meta:
  68. abstract = True
  69. app_label = 'wishlists'
  70. ordering = ('owner', 'date_created', )
  71. verbose_name = _('Wish List')
  72. def get_absolute_url(self):
  73. return reverse('customer:wishlists-detail', kwargs={
  74. 'key': self.key})
  75. def add(self, product):
  76. """
  77. Add a product to this wishlist
  78. """
  79. lines = self.lines.filter(product=product)
  80. if len(lines) == 0:
  81. self.lines.create(
  82. product=product, title=product.get_title())
  83. else:
  84. line = lines[0]
  85. line.quantity += 1
  86. line.save()
  87. @python_2_unicode_compatible
  88. class AbstractLine(models.Model):
  89. """
  90. One entry in a wish list. Similar to order lines or basket lines.
  91. """
  92. wishlist = models.ForeignKey('wishlists.WishList', related_name='lines',
  93. verbose_name=_('Wish List'))
  94. product = models.ForeignKey(
  95. 'catalogue.Product', verbose_name=_('Product'),
  96. related_name='wishlists_lines', on_delete=models.SET_NULL,
  97. blank=True, null=True)
  98. quantity = models.PositiveIntegerField(_('Quantity'), default=1)
  99. #: Store the title in case product gets deleted
  100. title = models.CharField(
  101. pgettext_lazy(u"Product title", u"Title"), max_length=255)
  102. def __str__(self):
  103. return u'%sx %s on %s' % (self.quantity, self.title,
  104. self.wishlist.name)
  105. def get_title(self):
  106. if self.product:
  107. return self.product.get_title()
  108. else:
  109. return self.title
  110. class Meta:
  111. abstract = True
  112. app_label = 'wishlists'
  113. unique_together = (('wishlist', 'product'), )
  114. verbose_name = _('Wish list line')