class Subcategory(UUIDPrimaryKey): parent = models.ForeignKey(Category, blank=True, null=True, default=None) name = models.CharField(max_length=96, blank=False, null=False) description = BBCodeTextField(max_length=256, blank=True, null=True) order = models.IntegerField() admin_req = models.BooleanField( default=False, help_text='Can only admin users create threads in this subcategory?') auth_req = models.BooleanField( default=False, help_text='Can only logged in users view this subcategory?') class Meta: verbose_name = 'subcategory' verbose_name_plural = 'subcategories' ordering = ( 'parent__order', 'order', ) def __str__(self): return "{} > {}. {}".format(self.parent, self.order, self.name) def can_view(self, user): if user.is_authenticated and user.is_banned: return False if not user.is_authenticated and self.auth_req: return False if not user.is_authenticated and self.parent.auth_req: return False return True def can_post(self, user): if user.is_authenticated and user.is_banned: return False if self.admin_req and user.is_authenticated and user.is_staff: return True if not self.admin_req and user.is_authenticated: return True return False @property def threads(self): return Thread.objects.filter(category__id=self.id) @property def thread_count(self): return len(self.threads) @property def posts(self): return Post.objects.filter(thread__category__id=self.id) @property def post_count(self): return len(self.posts) @property def last_thread(self): return self.threads.order_by('-created').first() def get_absolute_url(self): return reverse('board:subcategory', kwargs={'pk': self.id})
class EmailUser(AbstractBaseUser, UUIDPrimaryKey, CreatedModifiedMixin, PermissionsMixin, AvatarImagesMixin): GENDER_CHOICES = [ ('f', 'Female'), ('m', 'Male'), ] email = models.EmailField(unique=True, blank=False) username = models.CharField(max_length=16, unique=True, blank=False) image = ThumbnailerImageField(upload_to=user_image_file_name, null=True, blank=True) signature = BBCodeTextField(max_length=1024, blank=True, null=True) gender = models.CharField(null=True, blank=True, max_length=1, choices=GENDER_CHOICES, default=None) birthday = models.DateField(null=True, blank=True, verbose_name='Birth date') is_banned = models.BooleanField(default=False) rank = models.ForeignKey('UserRank', blank=True, null=True) username_modifier = models.TextField( max_length=250, blank=True, null=True, help_text="BBCode. Just add {USER} where " \ "you want the username to be placed at. " \ "Setting this will override the UserRank modification") USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username'] class Meta: verbose_name = 'user' verbose_name_plural = 'users' objects = EmailUserManager() def __str__(self): return self.username def get_full_name(self): return self.username def get_short_name(self): return self.username @property def is_staff(self): return self.is_superuser @property def post_count(self): return len(self.threads.all()) + len(self.posts.all()) @property def age(self): # Ugly but hey, it works. if not self.birthday: return 0 today = datetime.date.today() return (today.year - self.birthday.year - ((today.month, today.day) < (self.birthday.month, self.birthday.day))) @property def birthday_today(self): if self.birthday is None: return False today = datetime.date.today() match = self.birthday.day == today.day and \ self.birthday.month == today.month if match: return True return False @property def can_shout(self): if not BOARD_SETTINGS.SHOUTBOX_ENABLED: return False if BOARD_SETTINGS.SHOUTBOX_MINIMUM_POSTS: has_post_req = self.post_count >= BOARD_SETTINGS.SHOUTBOX_MINIMUM_POSTS_REQ if not has_post_req: return False return True @property def rendered_username(self): return utils.render_username(self) @property def rendered_signature(self): """Used on admin page""" return mark_safe(self.signature.rendered) @property def avatar_thumbnail(self): """Returns html tag with user image. Used on admin page""" return mark_safe('<img src="{}" />'.format(self.avatar_small)) def get_absolute_url(self): return reverse('board:profile', self.username)