Source code for oscar.apps.wishlists.abstract_models

from django.db import models
from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.translation import gettext_lazy as _
from django.utils.translation import pgettext_lazy

from oscar.core.compat import AUTH_USER_MODEL


[docs]class AbstractWishList(models.Model): """ Represents a user's wish lists of products. A user can have multiple wish lists, move products between them, etc. """ # Only authenticated users can have wishlists owner = models.ForeignKey( AUTH_USER_MODEL, related_name="wishlists", on_delete=models.CASCADE, verbose_name=_("Owner"), ) name = models.CharField( verbose_name=_("Name"), default=_("Default"), max_length=255 ) #: This key acts as primary key and is used instead of an int to make it #: harder to guess key = models.CharField( _("Key"), max_length=6, db_index=True, unique=True, editable=False ) # Oscar core does not support public or shared wishlists at the moment, but # all the right hooks should be there PUBLIC, PRIVATE, SHARED = ("Public", "Private", "Shared") VISIBILITY_CHOICES = ( (PRIVATE, _("Private - Only the owner can see the wish list")), ( SHARED, _( "Shared - Only the owner and people with access to the" " obfuscated link can see the wish list" ), ), (PUBLIC, _("Public - Everybody can see the wish list")), ) visibility = models.CharField( _("Visibility"), max_length=20, default=PRIVATE, choices=VISIBILITY_CHOICES ) # Convention: A user can have multiple wish lists. The last created wish # list for a user shall be their "default" wish list. # If an UI element only allows adding to wish list without # specifying which one , one shall use the default one. # That is a rare enough case to handle it by convention instead of a # BooleanField. date_created = models.DateTimeField( _("Date created"), auto_now_add=True, editable=False, db_index=True ) def __str__(self): return "%s's Wish List '%s'" % (self.owner, self.name)
[docs] def save(self, *args, **kwargs): if not self.pk or kwargs.get("force_insert", False): self.key = self.__class__.random_key() super().save(*args, **kwargs)
[docs] @classmethod def random_key(cls, length=6): """ Get a unique random generated key """ while True: key = get_random_string( length=length, allowed_chars="abcdefghijklmnopqrstuvwxyz0123456789" ) if not cls._default_manager.filter(key=key).exists(): return key
def is_allowed_to_see(self, user): if user == self.owner: return True elif self.visibility == self.PUBLIC: return True elif self.visibility == self.SHARED and user.is_authenticated: return self.shared_emails.filter(email=user.email).exists() return False def is_allowed_to_edit(self, user): # currently only the owner can edit their wish list return user == self.owner class Meta: abstract = True app_label = "wishlists" ordering = ( "owner", "date_created", ) verbose_name = _("Wish List") def get_absolute_url(self): return reverse("customer:wishlists-detail", kwargs={"key": self.key})
[docs] def add(self, product): """ Add a product to this wishlist """ lines = self.lines.filter(product=product) if len(lines) == 0: self.lines.create(product=product, title=product.get_title()) else: line = lines[0] line.quantity += 1 line.save()
def get_shared_url(self): return reverse("wishlists:detail", kwargs={"key": self.key}) @property def is_shareable(self): return self.visibility in [self.PUBLIC, self.SHARED]
[docs]class AbstractLine(models.Model): """ One entry in a wish list. Similar to order lines or basket lines. """ wishlist = models.ForeignKey( "wishlists.WishList", on_delete=models.CASCADE, related_name="lines", verbose_name=_("Wish List"), ) product = models.ForeignKey( "catalogue.Product", verbose_name=_("Product"), related_name="wishlists_lines", on_delete=models.SET_NULL, blank=True, null=True, ) quantity = models.PositiveIntegerField(_("Quantity"), default=1) #: Store the title in case product gets deleted title = models.CharField(pgettext_lazy("Product title", "Title"), max_length=255) def __str__(self): return "%sx %s on %s" % (self.quantity, self.title, self.wishlist.name) def get_title(self): if self.product: return self.product.get_title() else: return self.title class Meta: abstract = True app_label = "wishlists" # Enforce sorting by order of creation. ordering = ["pk"] unique_together = (("wishlist", "product"),) verbose_name = _("Wish list line")
[docs]class AbstractWishListSharedEmail(models.Model): """ An email which is allowed to view and possibly edit the wishlist, if shared. The user will have to login/create an account with this email in order to view it. """ wishlist = models.ForeignKey( "wishlists.WishList", on_delete=models.CASCADE, related_name="shared_emails", verbose_name=_("Wish List"), ) email = models.EmailField(verbose_name=_("Email")) def __str__(self): return "%s - %s" % (self.wishlist.name, self.email) class Meta: abstract = True app_label = "wishlists" verbose_name = _("Wish list shared email")