class Event(models.Model): NOW = datetime.datetime.now() YEAR = NOW.year if NOW.month > 7: YEAR += 1 YEAR_CHOICES = [(5000, 'Alle (inkludert alumni)'), (YEAR + 4, '1. - 5. klasse'), (YEAR + 3, '2. - 5. klasse'), (YEAR + 2, '3. - 5. klasse'), (YEAR + 1, '4. og 5. klasse'), (YEAR, '5. klasse')] def get_class_year(self, graduation_year): return graduation_year - self.YEAR title = models.CharField(max_length=200, unique=True) short_description = models.TextField(blank=True, null=True) description = models.TextField() location = models.CharField(max_length=50, blank=True, null=True) event_start_time = models.DateTimeField() event_end_time = models.DateTimeField(blank=True, null=True) registration_required = models.BooleanField(default=False) registration_start_time = models.DateTimeField(blank=True, null=True) alumni = models.BooleanField(default=False) class_1 = models.BooleanField(default=False) class_2 = models.BooleanField(default=False) class_3 = models.BooleanField(default=False) class_4 = models.BooleanField(default=False) class_5 = models.BooleanField(default=False) only_komite = models.BooleanField(default=False) available_spots = models.IntegerField(blank=True, null=True) registered_users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='registerd_users') waiting_list = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, related_name='waiting_list_users') external_link = models.CharField(blank=True, null=True, max_length=150) link_text = models.CharField(blank=True, null=True, max_length=150) slug = models.SlugField(max_length=60, blank=True) image = ProcessedImageField(upload_to='events/', processors=[ResizeToFit(2000, 2000, False)], format='JPEG', options={'quality': 85}) thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(300, 300, False)], format='JPEG', options={'quality': 100}) def __str__(self): return self.title def save(self, *args, **kwargs): if not self.id: # Only set the slug when the object is created. # Or whatever you want the slug to use self.slug = slugify(self.title) if not self.registration_start_time: self.registration_start_time = self.event_start_time super(Event, self).save(*args, **kwargs) def is_now(self, month): if month == datetime.datetime.now().month: return True else: return True class Meta: # ordering = ['event_start_date'] verbose_name = 'Arrangement' verbose_name_plural = 'Arrangementer' ordering = ['event_start_time', 'title']
class AutoCrop(ImageSpec): processors = [ResizeToFill(500, 500)] format = 'JPEG' options = {'quality': 100}
class MainPhoto(models.Model): photo = ProcessedImageField(verbose_name='ФОТО | JPEG | 1920х500', upload_to='media/', format='JPEG', options={'quality': 90}) photo_low = ImageSpecField(source='photo', format='JPEG', options={'quality': 1}) photo_webp = models.CharField(verbose_name='ФОТО | WEBP | 1920х500', max_length=600, null=True, blank=True) photo_jp2 = models.CharField(verbose_name='ФОТО | JPEG 2000 | 1920х500', max_length=600, null=True, blank=True) photo768 = ProcessedImageField(verbose_name='ФОТО | JPEG | 768х', upload_to='media/', format='JPEG', options={'quality': 90}, null=True, blank=True) photo_768_low = ImageSpecField(source='photo768', format='JPEG', options={'quality': 1}) photo_768_webp = models.CharField(verbose_name='ФОТО | WEBP | 768х', max_length=600, null=True, blank=True) photo_768_jp2 = models.CharField(verbose_name='ФОТО | JPEG 2000 | 768х', max_length=600, null=True, blank=True) photo576 = ProcessedImageField( verbose_name='Фото для главного слайдера(576px)', upload_to='media/', format='JPEG', options={'quality': 90}, null=True, blank=True) photo_576_low = ImageSpecField(source='photo576', format='JPEG', options={'quality': 1}) photo_576_webp = models.CharField(verbose_name='ФОТО | WEBP | 576х', max_length=600, null=True, blank=True) photo_576_jp2 = models.CharField(verbose_name='ФОТО | JPEG 2000 | 576х', max_length=600, null=True, blank=True) avatarphoto = ImageSpecField(source='photo', processors=[ResizeToFill(150, 100)], format='JPEG', options={'quality': 50}) class Meta: verbose_name = ('ГЛАВНЫЙ СЛАЙДЕР | ФОТО') verbose_name_plural = ('ГЛАВНЫЙ СЛАЙДЕР | ФОТО') def __str__(self): self.title = "Изображение" return u'%s' % self.title
class Episode(models.Model): """ An individual podcast episode and it's unique attributes. """ SIXTY_CHOICES = tuple((x, x) for x in range(60)) uuid = UUIDField("ID", unique=True) created = models.DateTimeField(_("created"), auto_now_add=True, editable=False) updated = models.DateTimeField(_("updated"), auto_now=True, editable=False) published = models.DateTimeField(_("published"), null=True, blank=True, editable=False) shows = models.ManyToManyField(Show, verbose_name=_("Podcasts")) enable_comments = models.BooleanField(default=True) author_text = models.CharField(_("author text"), max_length=255, blank=True, help_text=_(""" The person or musician name(s) featured on this specific episode. The suggested format is: '[email protected] (Full Name)' but 'Full Name' only, is acceptable. Multiple authors should be comma separated.""")) title = models.CharField(_("title"), max_length=255) slug = AutoSlugField(_("slug"), populate_from="title", unique="True") subtitle = models.CharField( _("subtitle"), max_length=255, blank=True, help_text=_("Looks best if only a few words like a tagline.")) description_pretty = models.TextField( _("pretty description"), blank=True, help_text="May be longer than 4000 characters and contain HTML tags and styling.") description = models.TextField( _("description"), max_length=4000, blank=True, help_text=_(""" This is your chance to tell potential subscribers all about your podcast. Describe your subject matter, media format, episode schedule, and other relevant info so that they know what they'll be getting when they subscribe. In addition, make a list of the most relevant search terms that you want your podcast to match, then build them into your description. Note that iTunes removes podcasts that include lists of irrelevant words in the itunes:summary, description, or itunes:keywords tags. This field can be up to 4000 plain text characters. No HTML tags or styling allowed.""")) tracklist = models.TextField( _("tracklist"), blank=True, help_text=_("""One track per line, machine will automatically add the numbers.""")) tweet_text = models.CharField(_("tweet text"), max_length=140, editable=False) if 'photologue' in settings.INSTALLED_APPS: original_image = models.ForeignKey(Photo, verbose_name=_("image"), default=None, null=True, blank=True, help_text=_(""" A podcast must have 1400 x 1400 pixel cover art in JPG or PNG format using RGB color space. See our technical spec for details. To be eligible for featuring on iTunes Stores, choose an attractive, original, and square JPEG (.jpg) or PNG (.png) image at a size of 1400x1400 pixels. The image will be scaled down to 50x50 pixels at smallest in iTunes. For reference see the <a href="http://www.apple.com/itunes/podcasts/specs.html#metadata">iTunes Podcast specs</a>.<br /><br /> For episode artwork to display in iTunes, image must be <a href="http://answers.yahoo.com/question/index?qid=20080501164348AAjvBvQ"> saved to file's <strong>metadata</strong></a> before enclosure uploading!""")) else: original_image = ImageField( _("image"), upload_to=get_episode_upload_folder, blank=True, help_text=_(""" A podcast must have 1400 x 1400 pixel cover art in JPG or PNG format using RGB color space. See our technical spec for details. To be eligible for featuring on iTunes Stores, choose an attractive, original, and square JPEG (.jpg) or PNG (.png) image at a size of 1400x1400 pixels. The image will be scaled down to 50x50 pixels at smallest in iTunes. For reference see the <a href="http://www.apple.com/itunes/podcasts/specs.html#metadata">iTunes Podcast specs</a>.<br /><br /> For episode artwork to display in iTunes, image must be <a href="http://answers.yahoo.com/question/index?qid=20080501164348AAjvBvQ"> saved to file's <strong>metadata</strong></a> before enclosure uploading!""")) if ImageSpecField: admin_thumb_sm = ImageSpecField(source="original_image", processors=[ResizeToFill(50, 50)], options={"quality": 100}) admin_thumb_lg = ImageSpecField(source="original_image", processors=[ResizeToFill(450, 450)], options={"quality": 100}) img_episode_sm = ImageSpecField(source="original_image", processors=[ResizeToFill(120, 120)], options={"quality": 100}) img_episode_lg = ImageSpecField(source="original_image", processors=[ResizeToFill(550, 550)], options={"quality": 100}) img_itunes_sm = ImageSpecField(source="original_image", processors=[ResizeToFill(144, 144)], options={"quality": 100}) img_itunes_lg = ImageSpecField(source="original_image", processors=[ResizeToFill(1400, 1400)], options={"quality": 100}) # iTunes specific fields hours = models.SmallIntegerField(_("hours"), default=0) minutes = models.SmallIntegerField(_("minutes"), default=0, choices=SIXTY_CHOICES) seconds = models.SmallIntegerField(_("seconds"), default=0, choices=SIXTY_CHOICES) keywords = models.CharField( _("keywords"), max_length=255, blank=True, help_text=_("A comma-delimited list of words for searches, up to 12; " "perhaps include misspellings.")) explicit = models.PositiveSmallIntegerField( _("explicit"), choices=Show.EXPLICIT_CHOICES, help_text=_("``Clean`` will put the clean iTunes graphic by it."), default=1) block = models.BooleanField( _("block"), default=False, help_text=_("Check to block this episode from iTunes because <br />its " "content might cause the entire show to be <br />removed from iTunes.""")) objects = EpisodeQuerySet.as_manager() tags = TaggableManager(blank=True) class Meta: verbose_name = _("Episode") verbose_name_plural = _("Episodes") ordering = ("-published", "slug") def __str__(self): return self.title def get_absolute_url(self): return reverse("podcasting_episode_detail", kwargs={"show_slug": self.shows.all()[0].slug, "slug": self.slug}) def get_next(self): next = self.__class__.objects.filter(published__gt=self.published) try: return next[0] except IndexError: return False def get_prev(self): prev = self.__class__.objects.filter(published__lt=self.published).order_by("-published") try: return prev[0] except IndexError: return False def as_tweet(self): if not self.tweet_text: current_site = Site.objects.get_current() api_url = "http://api.tr.im/api/trim_url.json" u = urlopen("{0}?url=http://{1}{2}".format( api_url, current_site.domain, self.get_absolute_url(), )) result = json.loads(u.read()) self.tweet_text = "{0} {1} - {2}".format( self.shows.all()[0].episode_twitter_tweet_prefix, self.title, result["url"], ) return self.tweet_text def tweet(self): if can_tweet(): account = twitter.Api( username=settings.TWITTER_USERNAME, password=settings.TWITTER_PASSWORD) account.PostUpdate(self.as_tweet()) else: raise ImproperlyConfigured( "Unable to send tweet due to either " "missing python-twitter or required settings.") def seconds_total(self): try: return self.minutes * 60 + self.seconds except: return 0 def get_share_url(self): return "http://{0}{1}".format(Site.objects.get_current(), self.get_absolute_url()) def get_share_title(self): return self.title def get_share_description(self): return "{0}...".format(self.description[:512]) def is_show_published(self): for show in self.shows.all(): if show.published: return True return False
class Article(models.Model): """ A simple model. Use Article.get_articles(CATEGORY=None, TAG=None, NUM=100) to get available articles list. Use Article.get_recently_articles(RECENTLY_ARTICLES_NUM) to get recently(RECENTLY_ARTICLES_NUM) articles. Use Article.get_hots_articles(HOT_ARTICLES_NUM) to get hot(HOT_ARTICLES_NUM) articles. Use article_object.related_articles(REALITVE_ARTICLES_NUM) to get related_articles of an object. """ author = models.ForeignKey(User, verbose_name=_(u"Author")) category = models.ForeignKey(Category, verbose_name=_(u'Category')) title = models.CharField(max_length=100, verbose_name=_(u'Title')) tags = models.CharField(max_length=100, null=True, blank=True, verbose_name=_(u'Tags'), help_text=_(u"Use the comma(',') separated") ) summary = models.TextField( verbose_name=_(u'Summary'), validators=[MinLengthValidator(30)], error_messages={"min_length": _("At least %(limit_value)d word,please!(it has %(show_value)d).") } ) content = wmd_models.MarkDownField(verbose_name=_(u'Content')) title_image = ProcessedImageField(upload_to='thumbnail', processors=[ResizeToFill(70, 70)], format='JPEG', options={'quality': 60} ) status = models.IntegerField( default=0, choices=STATUS.items(), verbose_name=_(u'Status')) view_times = models.IntegerField(default=1) like_times = models.IntegerField(default=1) liked_ip = models.TextField(verbose_name=_(u'liked_ip')) disliked_ip = models.TextField(verbose_name=_(u'disliked_ip')) is_top = models.BooleanField(default=False, verbose_name=_(u'Top')) create_time = models.DateTimeField( _(u'Create Time'), auto_now_add=True, editable=True) update_time = models.DateTimeField(_(u'Update Time'), auto_now=True) def __unicode__(self): return self.title def tags_list(self): """ Use article_object.tags_list() to split and get article_object's tags. """ return [tag.strip() for tag in self.tags.split(',')] def related_articles(self, num): """ A simple method. Use article_object.related_articles(REALITVE_ARTICLES_NUM) to get related_articles of an object. """ related_articles = None try: related_articles = Article.objects.values('id', 'title', 'view_times', 'update_time', 'author').\ filter(tags__icontains=self.tags_list()[0]).\ exclude(id=self.id)[:num] except IndexError: pass if not related_articles: related_articles = Article.objects.values('id', 'title', 'view_times', 'update_time', 'author').\ filter(category=self.category).\ exclude(id=self.id)[:num] return related_articles @classmethod def get_articles(cls, CATEGORY=None, TAG=None, NUM=100): """ A simple classmethod. Use Article.get_articles(CATEGORY=None, TAG=None, NUM=100) to get articles list. """ if CATEGORY: article_list = cls.objects.filter( Q(status=0) & Q(category__name__icontains=CATEGORY))[:NUM] return article_list if TAG: article_list = cls.objects.filter( Q(status=0) & Q(tags__icontains=TAG))[:NUM] return article_list return cls.objects.filter(status=0)[:NUM] @classmethod def get_all_tags_list(cls): """ A simple classmethod. Use Article.get_all_tags_list() to get all articles' tags list. """ all_tags_list = [] # obj_list = cls.objects.filter(status=0).order_by('-update_time') obj_list = Article.objects.all() for obj in obj_list: all_tags_list = all_tags_list + obj.tags_list() # for tag in obj.tags.split(','): # all_tags_list.append(tag) return all_tags_list @classmethod def get_recently_articles(cls, num): """ A simple classmethod. Use Article.get_recently_articles(RECENTLY_ARTICLES_NUM) to get recently(RECENTLY_ARTICLES_NUM) articles. """ return cls.objects.values('title', 'view_times', 'update_time', 'author')\ .filter(status=0).order_by('-update_time')[:num] @classmethod def get_hots_articles(cls, num): """ A simple classmethod. Use Article.get_hots_articles(HOT_ARTICLES_NUM) to get hot(HOT_ARTICLES_NUM) articles. """ return cls.objects.values('id', 'title', 'view_times', 'update_time', 'author').\ filter(status=0).order_by('-view_times' )[:num] class Meta: ordering = ['-is_top', '-update_time', '-create_time'] verbose_name_plural = verbose_name = _(u"Article")
class ProfileImage(ImageSpec): processors = [ResizeToFill(50, 50)] format = 'JPEG' options = {'quality': 60}
class Post(models.Model): title = models.CharField(max_length=50, verbose_name='文章标题') excerpt = models.CharField(max_length=200, verbose_name='文章摘要') content = RichTextUploadingField(verbose_name='文章内容') click_count = models.PositiveIntegerField(default=0, verbose_name='点击次数') is_recommended = models.BooleanField(default=False, verbose_name='是否推荐') date_created = models.DateTimeField(auto_now_add=True, verbose_name='发布时间') date_modified = models.DateTimeField(auto_now=True, verbose_name='修改时间') author = models.ForeignKey(User, verbose_name='作者') category = models.ForeignKey(Category, verbose_name='分类') tag = models.ManyToManyField(Tag, verbose_name='标签') cover = ProcessedImageField(upload_to='cover', default='', verbose_name='封面', processors=[ResizeToFill(160, 120)], format='JPEG', options={"quality": 60}) favours = GenericRelation(Favour, related_query_name='posts') class Meta: verbose_name = '文章' verbose_name_plural = verbose_name ordering = ['-date_created'] def __str__(self): return self.title def favour_count(self, update=0): key = 'post_{}_favour_count'.format(self.id) count = cache.get(key) if count is None: count = self.favours.filter(liked=True).count() cache.set(key, count, timeout=300) elif update: count += update cache.set(key, count, timeout=300) return count def click_increase(self): self.click_count += 1 self.save(update_fields=['click_count']) def get_absolute_url(self): return reverse('blog:detail', kwargs={'pk': self.pk}) def to_comments_html(self): key = 'post_{}_comments'.format(self.id) html = '' comments = self.comment_set.all().order_by('-submit_date')[:15] for comment in comments: comment_html = comment.to_html() html += comment_html cache.set(key, html, timeout=300) return html def comment_user_count(self): key = "post_{}_comments_user_num".format(self.id) user_num = cache.get(key, None) if not user_num: user_list = [] key1 = "post_{}_comments_user".format(self.id) for comment in self.comment_set.all(): if comment.user not in user_list: user_list.append(comment.user) user_num = len(user_list) cache.set(key, user_num, timeout=300) cache.set(key1, user_list, timeout=300) return user_num def comment_count(self): key = "post_{}_comments_num".format(self.id) comment_num = cache.get(key, None) if not comment_num: comment_num = self.comment_set.all().count() cache.set(key, comment_num, timeout=300) return comment_num def comment_update(self, new_comment): comment_list_html = self.to_comments_html() key2 = "post_{}_comments_user".format(self.id) key3 = "post_{}_comments_user_num".format(self.id) user_list = cache.get(key2, None) if user_list: if new_comment.user not in user_list: user_list.append(new_comment.user) user_num = len(user_list) cache.set(key3, user_num, timeout=300) cache.set(key2, user_list, timeout=300) else: user_num = self.comment_user_count() key4 = "post_{}_comments_num".format(self.id) comment_num = cache.get(key4, None) if comment_num: comment_num += 1 cache.set(key4, comment_num, timeout=300) else: comment_num = self.comment_count() return comment_list_html, user_num, comment_num
class Event(models.Model): title = models.CharField(max_length=160, blank=False) status = models.CharField(max_length=2, choices=STATUS_CHOICES) event_type = models.CharField(max_length=11, choices=EVENT_TYPE_CHOICES) mode = models.CharField(max_length=9, choices=MODE_CHOICES) location = models.ForeignKey("authentication.Chapter", related_name="event", on_delete=models.CASCADE) host = models.CharField(max_length=50, blank=True) presenter_first_name = models.CharField(max_length=50, blank=False, verbose_name="First Name") presenter_last_name = models.CharField(max_length=50, blank=False, verbose_name="Last Name") presenter_designation = models.CharField(max_length=80, blank=False, verbose_name="Designation") pres_img = ProcessedImageField( upload_to="events/presenters", blank=True, verbose_name="Presenter Picture") # processedimagefield presenter_picture = ImageSpecField(source="pres_img", processors=[ResizeToFill(300, 300) ]) # sized image presenter_picture_thumbnail = ImageSpecField( source="pres_img", processors=[ResizeToFill(90, 90)]) # thumbnail image presenter_profile_url = models.URLField(blank=False, verbose_name="Public Profile URL") presenter_company_name = models.CharField(max_length=100, blank=False, verbose_name="Company Name") pres_com_log = ProcessedImageField( upload_to="events/company_logos", blank=True, verbose_name="Company Logo") # prcessedimagefield presenter_company_logo = ImageSpecField( source="pres_com_log", processors=[ResizeToFill(200, 200)]) # sized image presenter_company_website = models.URLField(blank=True, verbose_name="Company Website") presenter_bio = models.TextField(blank=False, verbose_name="Bio") event_description = models.TextField(blank=False) event_address = models.TextField(blank=True) link = models.URLField(blank=True) timezone = models.CharField(max_length=100, blank=False, choices=TIMEZONE_CHOICES) start_date = models.DateField(blank=False) start_time = models.TimeField(blank=False) end_date = models.DateField(blank=False) end_time = models.TimeField(blank=False) added_by = models.ForeignKey("authentication.User", related_name="event", null=True, on_delete=models.CASCADE) added_on = models.DateTimeField(auto_now_add=True) slides = models.FileField(upload_to="slides/", null=True, blank=True) def __str__(self): return self.title
class Post(models.Model): """ Post model """ id = models.UUIDField(primary_key=True, default=uuid4, editable=False) author = models.ForeignKey(User, on_delete=models.CASCADE, null=True) title = models.CharField(max_length=200) text = models.TextField(null=True, max_length=2000) image = models.ImageField(upload_to=settings.POST_IMAGE_UPLOAD_DIR, verbose_name='post image') image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(640, 360)], format='JPEG', options={'quality': 60}) created_date = models.DateTimeField(default=timezone.now) published_date = models.DateTimeField(blank=True, null=True, default=timezone.now) hits = models.PositiveIntegerField(blank=True, null=True, default=0) goods = models.PositiveIntegerField(blank=True, null=True, default=0) bads = models.PositiveIntegerField(blank=True, null=True, default=0) def __str__(self): return self.title def publish(self): """ Publish this post now """ self.published_date = timezone.now() self.save() def create(self, author): """ Create post """ self.author = author self.publish() def was_published_recently(self): """ Whether the post was published within 1 day """ now = timezone.now() return now - datetime.timedelta(days=1) <= self.published_date <= now was_published_recently.admin_order_field = 'published_date' was_published_recently.boolean = True was_published_recently.short_description = 'Published recently?' def change_image_name(self, name): """ Change the post image name """ self.image.name = name def count_hits(self): self.hits = PostHit.objects.filter(post=self.pk).count() return self.hits def count_goods(self): self.goods = PostEval.objects.filter(post=self.pk, good=True, bad=False).count() return self.goods def count_bads(self): self.bads = PostEval.objects.filter(post=self.pk, good=False, bad=True).count() return self.bads
class ThumbnailsImage(models.Model): image = models.ForeignKey(Image, on_delete=models.CASCADE) avatar_thumbnail = ProcessedImageField(upload_to='avatars', processors=[ResizeToFill(250, 150)], format='JPEG', options={'quality': 60})
class Product(models.Model): category = models.ForeignKey(ProductCategory, null=True) name = models.CharField(max_length=100, default="fill in your product name here") image_1 = ProcessedImageField(upload_to="products", processors=[ResizeToFill(360, 360)], format="PNG", options={'quality': 80}, null=True, blank=True) image_2 = ProcessedImageField(upload_to="products", processors=[ResizeToFill(360, 360)], format="PNG", options={'quality': 80}, null=True, blank=True) image_3 = ProcessedImageField(upload_to="products", processors=[ResizeToFill(360, 360)], format="PNG", options={'quality': 80}, null=True, blank=True) image_4 = ProcessedImageField(upload_to="products", processors=[ResizeToFill(360, 360)], format="PNG", options={'quality': 80}, null=True, blank=True) definition = models.CharField( max_length=300, default="Fill in product short definition here") optional_definition_switch = models.BooleanField(default=True) optional_definition = models.TextField( default="Fill in extra definition in HTML form here if switch = true") original_price = models.DecimalField(max_digits=10, decimal_places=2) discount_switch = models.BooleanField(default=False) discount = models.DecimalField(max_digits=10, decimal_places=2, default="5.00") in_stock = models.BooleanField(default=True) discounted_price = models.DecimalField(max_digits=10, decimal_places=2, default="50.00") member_price_switch = models.BooleanField(default=False) discount_member = models.DecimalField(max_digits=10, decimal_places=2, default="7.50") discounted_member_price = models.DecimalField(max_digits=10, decimal_places=2, default="50.00") slug = models.SlugField(default="will-be-generated-once-save") created_date = models.DateTimeField(default=timezone.now) def calculate_general_price(self): value = ((100 - self.discount) / 100) * self.original_price return float(round(value)) def calculate_member_price(self): value = ((100 - self.discount_member) / 100) * self.original_price return float(round(value)) def save(self, *args, **kwargs): self.slug = slugify(self.name) self.discounted_price = self.calculate_general_price() self.discounted_member_price = self.calculate_member_price() super(Product, self).save(*args, **kwargs) def __str__(self): return self.name
class ProgrammeEvent(models.Model): EVENT_TYPES = ( (0, 'Yksinkertainen'), (1, 'Yksityiskohtainen'), ) event = models.ForeignKey(Event, verbose_name='Tapahtuma', on_delete=models.PROTECT) start = models.DateTimeField('Alku', help_text='Tapahtuman alkamisaika.') end = models.DateTimeField('Loppu', help_text='Tapahtuman loppumisaika.', null=True, blank=True) description = models.TextField('Kuvaus', blank=True) title = models.CharField('Otsikko', help_text='Lyhyt otsikko.', max_length=128) presenters = models.CharField('Henkilöt', help_text='Esityksen pitäjät tms.', max_length=256, blank=True) presenters_titles = models.CharField( 'Nimikkeet', help_text='Henkilön arvo-, ammatti- tai virkanimike.', max_length=256, blank=True) place = models.CharField('Paikka', help_text='Tarkka paikka tapahtuma-areenalla', max_length=64, blank=True) # This is such a hackish solution that it makes me want to throw up. Oh well. icon_original = models.ImageField('Kuva 1', upload_to='programme/images/', help_text="Kuva 1 tapahtumalle.", blank=True) icon_small = ImageSpecField([ResizeToFill(64, 64)], source='icon_original', format='PNG') icon2_original = models.ImageField('Kuva 2', upload_to='programme/images/', help_text="Kuva 2 tapahtumalle.", blank=True) icon2_small = ImageSpecField([ResizeToFill(64, 64)], source='icon2_original', format='PNG') email = models.EmailField( 'Sähköposti', help_text='Tapahtumaan liittyvä sähköposti-osoite (esim. esiintyjän).', blank=True) home_url = models.URLField('Kotiurli', help_text='Tapahtumaan liittyvä URL.', blank=True) twitter_url = models.URLField( 'Twitter', help_text='Tapahtumaan liittyvä Twitter-url.', blank=True) github_url = models.URLField('Github', help_text='Tapahtumaan liittyvä Github-url', blank=True) facebook_url = models.URLField( 'Facebook', help_text='Tapahtumaan liittyvä facebook-url.', blank=True) linkedin_url = models.URLField( 'LinkedIn', help_text='Tapahtumaan liittyvä LinkedIn-url.', blank=True) wiki_url = models.URLField('Wikipedia', help_text='Tapahtumaan liittyvä Wikipedia-url.', blank=True) gplus_url = models.URLField( 'Google+', help_text='Tapahtumaan liittyvä Google Plus-url.', blank=True) event_type = models.IntegerField( 'Tapahtuman tyyppi', choices=EVENT_TYPES, default=0, help_text= "Määrittää tapahtuman tyypin. Yksityiskohtaiset tapahtumat näkyvät etusivun tapahtumalistassa." ) active = models.BooleanField('Aktiivinen', help_text='Deaktivoidut piilotetaan.', default=True) @property def short_start_time(self): if self.start: start = arrow.get(self.start).to(settings.TIME_ZONE) return "{} {}".format(short_days[start.weekday()], start.format("HH:mm")) return "" def save(self, *args, **kwargs): # Delete old icon file when editing try: this = ProgrammeEvent.objects.get(id=self.id) if this.icon_original != self.icon_original: this.icon_original.delete(save=False) except ProgrammeEvent.DoesNotExist: pass # Continue with normal save super(ProgrammeEvent, self).save(*args, **kwargs) def __str__(self): return self.title class Meta: verbose_name = "ohjelmatapahtuma" verbose_name_plural = "ohjelmatapahtumat"
class StoryImage(models.Model): image = ProcessedImageField(processors=[ResizeToFill(300, 300)], format='JPEG', options={'quality': 90}, upload_to='storys') story = models.ForeignKey(Story, on_delete=models.CASCADE)
class Picture(models.Model): text = models.TextField() image = models.ImageField(upload_to="blogimg") image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(130, 130)])
class Project(models.Model): STATUS_CHOICES = ( ('draft', 'Draft'), ('published', 'Published') ) title = models.CharField(max_length=255) slug = models.SlugField( max_length=255, unique=True) image = models.ImageField( upload_to=project_image_folder, blank=True) image_thumbnail = ImageSpecField( source='image', processors=[ResizeToFill(850, 550)], format='JPEG', options={'quality': 90}) thumb = ImageSpecField( source='image', processors=[ResizeToFit(600, 600)], format='JPEG', options={'quality': 90}) project_url = models.URLField( 'Project URL', null=True, blank=True) description = models.TextField(blank=True) technology = models.CharField(max_length=255) report_file = models.FileField( upload_to='report/%Y/%m/%d/', null=True, blank=True) meta_keywords = models.CharField( max_length=255, null=True, blank=True, help_text='Comma-delimited set of SEO keywords for meta tag') meta_description = models.TextField( max_length=255, null=True, blank=True, help_text='Content for description meta tag, maximum are 200 characters') publish = models.DateTimeField(default=timezone.now) added = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) category = models.ForeignKey( 'ProjectCategory', null=True, blank=True, on_delete=models.CASCADE) status = models.CharField( max_length=10, choices=STATUS_CHOICES, default='draft') object = models.Manager() published = PublishedManager() class Meta: ordering = ('-added',) verbose_name = 'Project' verbose_name_plural = 'Projects' def __str__(self): return self.title def get_absolute_url(self): return reverse('project_detail', args=[self.pk, self.slug])
def processors(self): model, field_name = get_field_info(self.source) return [ResizeToFill(model.width, model.height)]
class Post(models.Model): STATUS_CHOICES = ( ('draft', 'Draft'), ('published', 'Published'), ) title = models.CharField(max_length=255) slug = models.SlugField( max_length=250, unique_for_date='publish') author = models.ForeignKey( User, on_delete=models.CASCADE) body = models.TextField() image = models.ImageField( upload_to=blog_image_folder, blank=True) image_thumbnail = ImageSpecField( source='image', processors=[ResizeToFill(50, 50)], format='JPEG', options={'quality': 90}) thumb = ImageSpecField( source='image', processors=[ResizeToFill(600, 600)], format='JPEG', options={'quality': 90}) publish = models.DateTimeField(default=timezone.now) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) status = models.CharField( max_length=10, choices=STATUS_CHOICES, default='draft') meta_keywords = models.CharField( max_length=250, help_text='Comma-delimited set of SEO keywords for keywords meta tag', blank=True) meta_description = models.CharField( max_length=250, help_text='Content for description meta tag', blank=True) objects = models.Manager() published = PublishedManager() tags = TaggableManager() class Meta: ordering = ('-publish',) def __str__(self): return self.title def get_absolute_url(self): return reverse('post_detail', args=[self.publish.year, self.publish.month, self.publish.day, self.slug]) @property def comments(self): instance = self qs = Comment.objects.filter_by_instance(instance) return qs @property def get_content_type(self): instance = self content_type = ContentType.objects.get_for_model(instance.__class__) return content_type
class Shirt(models.Model): related_fields = ["collection", "fabric", "size_option", "size", "hem", "placket", "pocket", "back", "custom_buttons_type", "custom_buttons", "shawl", "yoke"] CLASP_OPTIONS = Choices((False, _(u'Не использовать застежку')), (True, _(u'Использовать застежку'))) is_template = models.BooleanField(_(u'Используется как шаблон'), default=False) is_standard = models.BooleanField(_(u'Используется как стандартный вариант'), default=False, editable=False) collection = models.ForeignKey(Collection, verbose_name=_(u'Коллекция'), related_name='shirts', null=True) code = models.CharField(_(u'Артикул'), max_length=255, null=True) individualization = models.TextField(_(u'Индивидуализация'), null=True, blank=True) fabric = models.ForeignKey(Fabric, verbose_name=_(u'Ткань'), null=True) showcase_image = models.ImageField(_(u'Изображение для витрины'), blank=False, null=True, upload_to='showcase') showcase_image_list = ImageSpecField(source='showcase_image', processors=[ResizeToFill(*settings.SHOWCASE_IMAGE_SIZE)], format='JPEG', options={'quality': 100}) showcase_image_detail = ImageSpecField(source='showcase_image', processors=[ResizeToFill(*settings.SHOWCASE_DETAILS_IMAGE_SIZE)], format='JPEG', options={'quality': 100}) size_option = models.ForeignKey('dictionaries.SizeOptions', verbose_name=_(u'Выбранный вариант размера')) size = models.ForeignKey('dictionaries.Size', verbose_name=_(u'Размер'), blank=True, null=True) hem = models.ForeignKey('dictionaries.HemType', verbose_name=_(u'Низ'), related_name='hem_shirts') placket = models.ForeignKey('dictionaries.PlacketType', verbose_name=_(u'Полочка'), related_name='placket_shirts') pocket = models.ForeignKey('dictionaries.PocketType', verbose_name=_(u'Карман'), related_name='pocket_shirts') sleeve = models.ForeignKey('dictionaries.SleeveType', verbose_name=_(u'Рукав'), related_name='sleeve_shirts', default=ResolveDefault(SleeveType)) fit = ChainedForeignKey(Fit, verbose_name=_(u'Талия'), chained_field='collection', chained_model_field='collections', show_all=False, blank=True, null=True) tuck = ChainedForeignKey('dictionaries.TuckType', verbose_name=_(u'Вытачки'), chained_field='collection', chained_model_field='collections', show_all=False) back = models.ForeignKey('dictionaries.BackType', verbose_name=_(u'Спинка'), related_name='back_shirts') custom_buttons_type = models.ForeignKey('dictionaries.CustomButtonsType', verbose_name=_(u'Тип кастомных пуговиц'), null=True, blank=True, related_name='back_shirts') custom_buttons = ChainedForeignKey(CustomButtons, verbose_name=_(u'Кастомные пуговицы'), chained_field='custom_buttons_type', chained_model_field='type', show_all=False, null=True, blank=True) shawl = models.ForeignKey(ShawlOptions, verbose_name=_(u'Платок'), null=True, related_name='shirts', default=ResolveDefault(ShawlOptions)) yoke = models.ForeignKey('dictionaries.YokeType', verbose_name=_(u'Кокетка'), null=True) clasp = models.BooleanField(_(u'Застежка под штифты'), choices=CLASP_OPTIONS, default=False) STITCH = Choices(('none', _(u'0 мм (без отстрочки)')), ('1mm', _(u'1 мм (только со съемными косточками)')), ('5mm', _(u'5 мм'))) stitch = models.CharField(_(u'Ширина отстрочки'), max_length=10, choices=STITCH) price = models.DecimalField(_(u'Цена'), max_digits=10, decimal_places=2, editable=False, null=True) def save(self, *args, **kwargs): cuff = getattr(self, 'cuff', None) if cuff and not self.sleeve.cuffs: if cuff.id: cuff.delete() super(Shirt, self).save(*args, **kwargs) class Meta: ordering = ('code',) verbose_name = _(u'Сорочка') verbose_name_plural = _(u'Сорочки') def __unicode__(self): return self.code if self.code else self.id
class Movie(BaseAddModify, BaseNameSlug): """Movie model""" name = models.CharField(_('Name'), max_length=100) slug = models.SlugField(_('Slug'), max_length=110, unique=True, blank=True) release_year = models.CharField(_('Release Year'), max_length=4) duration = models.SmallIntegerField(_('Duration'), default=0, blank=True, help_text=_('in minutes')) imdb_rating = models.FloatField(_('IMDB Rating'), default=0, blank=True, help_text=_('e.g. 6.8')) content = models.TextField(_('Content'), default='', blank=True) source_content = models.URLField( # credits _('Content Source'), default='', blank=True) trailer = models.URLField( _('Trailer'), default='', blank=True, help_text=_('trailer url (ONLY for youtube videos yet)')) image = models.ImageField(_('Image'), default='movies/default-movie.jpg', upload_to=movie_directory_path, blank=True, null=True) image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(250, 400)], format='JPEG', options={'quality': 80}) credit_image = models.CharField( # credits _('Image Credit'), max_length=250, default='', blank=True) pg_rating = models.ForeignKey(PgRating, on_delete=models.SET_NULL, blank=True, null=True, related_name='movies', verbose_name=_('PG Rating')) genres = models.ManyToManyField(Genre, related_name='movies', verbose_name=_('Genres')) crews = models.ManyToManyField('celebs.Celebrity', through='MovieCrew', related_name='movies', verbose_name=_('Crews')) @property def casts(self): return self._get_crew('C') @property def directors(self): return self._get_crew('D') @property def producers(self): return self._get_crew('P') @property def writers(self): return self._get_crew('W') @property def youtube_video(self): return video_code(self.trailer) class Meta: verbose_name = _('Movie') verbose_name_plural = _('Movies') ordering = ('-release_year', 'name') def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(unidecode(self.name) + '-' + random_name(5)) super().save(*args, **kwargs) def get_absolute_url(self): return reverse('movie_detail', args=[self.slug]) def _get_crew(self, duty_code): if hasattr(self, '_prefetched_objects_cache' ) and 'moviecrews' in self._prefetched_objects_cache: return [ c for c in self._prefetched_objects_cache['moviecrews'] if c.duty.code == duty_code ] else: return self.moviecrews.filter(duty__code=duty_code)
class Recipe(models.Model): """ Django Model to hold Recipes. Courses have a one to Many relation with Recipes. Cuisines have a one to Many relation with Recipes. Tags have a Many to Many relation with Recipes. Ingredient Groups have a Many to one relation with Recipes. Subrecipes have a Many to Many relation with Recipes. They allow another recipe to be show in the Ingredient section. :title: = Title of the Recipe :author: = Creator of the Recipe :photo: = Raw Image of a Recipe :photo_thumbnail: = compressed image of the photo :info: = Description of the recipe :directions: = How to make the recipe :prep_time: = How long it takes to prepare the recipe :cook_time: = How long the recipe takes to cook :servings: = How many people the recipe with serve :rating: = Rating of the recipe :pub_date: = When the recipe was created :update_date: = When the recipe was updated """ title = models.CharField(_("Recipe Title"), max_length=250) slug = AutoSlugField(_('slug'), populate_from='title', unique=True) author = models.ForeignKey(User, verbose_name=_('user'), null=True) photo = models.ImageField(_('photo'), blank=True, upload_to="upload/recipe_photos") photo_thumbnail = ImageSpecField(source='photo', processors=[ResizeToFill(300, 200)], format='JPEG', options={'quality': 70}) cuisine = models.ForeignKey(Cuisine, verbose_name=_('cuisine')) course = models.ForeignKey(Course, verbose_name=_('course')) tags = models.ManyToManyField(Tag, verbose_name=_('tag'), blank=True) subrecipes = models.ManyToManyField('self', verbose_name=_('subrecipes'), through='SubRecipe', symmetrical=False) info = models.TextField(_('info'), help_text="enter information about the recipe", blank=True) directions = models.TextField(_('direction_text'), help_text="directions", blank=True) source = models.CharField(_('course'), max_length=200, blank=True) prep_time = models.IntegerField(_('prep time'), help_text="enter time in minutes") cook_time = models.IntegerField(_('cook time'), help_text="enter time in minutes") servings = models.IntegerField(_('servings'), help_text="enter total number of servings") rating = models.IntegerField(_('rating'), help_text="rating of the meal", default=0) pub_date = models.DateTimeField(auto_now_add=True) update_date = models.DateTimeField(auto_now=True) class Meta: ordering = ['-pub_date', 'title'] def __unicode__(self): return '%s' % self.title
class Show(models.Model): """ A podcast show, which has many episodes. """ EXPLICIT_CHOICES = ( (1, _("yes")), (2, _("no")), (3, _("clean")), ) uuid = UUIDField(_("id"), unique=True) created = models.DateTimeField(_("created"), auto_now_add=True, editable=False) updated = models.DateTimeField(_("updated"), auto_now=True, editable=False) published = models.DateTimeField(_("published"), null=True, blank=True, editable=False) sites = models.ManyToManyField(Site, verbose_name=_('Sites')) ttl = models.PositiveIntegerField( _("ttl"), default=1440, help_text=_("""``Time to Live,`` the number of minutes a channel can be cached before refreshing.""")) owner = models.ForeignKey( settings.AUTH_USER_MODEL, related_name="podcast_shows", verbose_name=_("owner"), help_text=_("""Make certain the user account has a name and e-mail address.""")) editor_email = models.EmailField( _("editor email"), blank=True, help_text=_("Email address of the person responsible for the feed's content.")) webmaster_email = models.EmailField( _("webmaster email"), blank=True, help_text=_("Email address of the person responsible for channel publishing.")) if 'licenses' in settings.INSTALLED_APPS: license = models.ForeignKey(License, verbose_name=_("license")) else: license = models.CharField( _("license"), max_length=255, help_text=_("To publish a podcast to iTunes it is required to set a license type.")) organization = models.CharField( _("organization"), max_length=255, help_text=_("Name of the organization, company or Web site producing the podcast.")) link = models.URLField(_("link"), help_text=_("""URL of either the main website or the podcast section of the main website.""")) enable_comments = models.BooleanField(default=True) author_text = models.CharField( _("author text"), max_length=255, help_text=_(""" This tag contains the name of the person or company that is most widely attributed to publishing the Podcast and will be displayed immediately underneath the title of the Podcast. The suggested format is: '[email protected] (Full Name)' but 'Full Name' only, is acceptable. Multiple authors should be comma separated.""")) title = models.CharField(_("title"), max_length=255) slug = AutoSlugField(_("slug"), populate_from="title", unique="True") subtitle = models.CharField( _("subtitle"), max_length=255, help_text=_("Looks best if only a few words, like a tagline.")) # If the show is not on iTunes, many fields may be ignored in your user forms on_itunes = models.BooleanField( _("iTunes"), default=True, help_text=_("Checked if the podcast is submitted to iTunes")) description_pretty = models.TextField( _("pretty description"), blank=True, help_text="May be longer than 4000 characters and contain HTML tags and styling.") description = models.TextField( _("description"), max_length=4000, help_text=_(""" This is your chance to tell potential subscribers all about your podcast. Describe your subject matter, media format, episode schedule, and other relevant info so that they know what they'll be getting when they subscribe. In addition, make a list of the most relevant search terms that you want yourp podcast to match, then build them into your description. Note that iTunes removes podcasts that include lists of irrelevant words in the itunes:summary, description, or itunes:keywords tags. This field can be up to 4000 characters.""")) if 'photologue' in settings.INSTALLED_APPS: original_image = models.ForeignKey(Photo, verbose_name=_("image"), default=None, null=True, blank=True, help_text=_(""" A podcast must have 1400 x 1400 pixel cover art in JPG or PNG format using RGB color space. See our technical spec for details. To be eligible for featuring on iTunes Stores, choose an attractive, original, and square JPEG (.jpg) or PNG (.png) image at a size of 1400x1400 pixels. The image will be scaled down to 50x50 pixels at smallest in iTunes. For reference see the <a href="http://www.apple.com/itunes/podcasts/specs.html#metadata">iTunes Podcast specs</a>.<br /><br /> For episode artwork to display in iTunes, image must be <a href="http://answers.yahoo.com/question/index?qid=20080501164348AAjvBvQ"> saved to file's <strong>metadata</strong></a> before enclosure uploading!""")) else: original_image = ImageField( _("image"), upload_to=get_show_upload_folder, blank=True, help_text=_(""" A podcast must have 1400 x 1400 pixel cover art in JPG or PNG format using RGB color space. See our technical spec for details. To be eligible for featuring on iTunes Stores, choose an attractive, original, and square JPEG (.jpg) or PNG (.png) image at a size of 1400x1400 pixels. The image will be scaled down to 50x50 pixels at smallest in iTunes. For reference see the <a href="http://www.apple.com/itunes/podcasts/specs.html#metadata">iTunes Podcast specs</a>.<br /><br /> For episode artwork to display in iTunes, image must be <a href="http://answers.yahoo.com/question/index?qid=20080501164348AAjvBvQ"> saved to file's <strong>metadata</strong></a> before enclosure uploading!""")) if ResizeToFill: admin_thumb_sm = ImageSpecField(source="original_image", processors=[ResizeToFill(50, 50)], options={"quality": 100}) admin_thumb_lg = ImageSpecField(source="original_image", processors=[ResizeToFill(450, 450)], options={"quality": 100}) img_show_sm = ImageSpecField(source="original_image", processors=[ResizeToFill(120, 120)], options={"quality": 100}) img_show_lg = ImageSpecField(source="original_image", processors=[ResizeToFill(550, 550)], options={"quality": 100}) img_itunes_sm = ImageSpecField(source="original_image", processors=[ResizeToFill(144, 144)], options={"quality": 100}) img_itunes_lg = ImageSpecField(source="original_image", processors=[ResizeToFill(1400, 1400)], options={"quality": 100}) feedburner = models.URLField( _("feedburner url"), blank=True, help_text=_("""Fill this out after saving this show and at least one episode. URL should look like "http://feeds.feedburner.com/TitleOfShow". See <a href="http://code.google.com/p/django-podcast/">documentation</a> for more. <a href="http://www.feedburner.com/fb/a/ping">Manually ping</a>""")) # iTunes specific fields explicit = models.PositiveSmallIntegerField( _("explicit"), default=1, choices=EXPLICIT_CHOICES, help_text=_("``Clean`` will put the clean iTunes graphic by it.")) redirect = models.URLField( _("redirect"), blank=True, help_text=_("""The show's new URL feed if changing the URL of the current show feed. Must continue old feed for at least two weeks and write a 301 redirect for old feed.""")) keywords = models.CharField( _("keywords"), max_length=255, blank=True, help_text=_("""A comma-demlimitedlist of up to 12 words for iTunes searches. Perhaps include misspellings of the title.""")) itunes = models.URLField( _("itunes store url"), blank=True, help_text=_("""Fill this out after saving this show and at least one episode. URL should look like: "http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=000000000". See <a href="http://code.google.com/p/django-podcast/">documentation</a> for more.""")) twitter_tweet_prefix = models.CharField( _("Twitter tweet prefix"), max_length=80, help_text=_("Enter a short ``tweet_text`` prefix for new episodes on this show."), blank=True) objects = ShowQuerySet.as_manager() tags = TaggableManager(blank=True) class Meta: verbose_name = _("Show") verbose_name_plural = _("Shows") ordering = ("organization", "slug") def __str__(self): return self.title def get_share_url(self): return "http://{0}{1}".format(Site.objects.get_current(), self.get_absolute_url()) def get_absolute_url(self): return reverse("podcasting_show_detail", kwargs={"slug": self.slug}) @property def current_episode(self): try: return self.episode_set.published().order_by("-published")[0] except IndexError: return None
class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) location = models.CharField(max_length=50, default='') bio = models.TextField(default='') gender = models.CharField(max_length=6, choices=GENDER_CHOICES, default='') role = models.CharField(max_length=6, blank=False, default='mentee', choices=ROLE_CHOICES) phone_number = models.CharField(max_length=32, default='') mentorship_areas = MultiSelectField(choices=MENTORSHIP_AREAS_CHOICES, max_choices=3, default='') highest_level_of_study = models.CharField(max_length=255, choices=EDUCATION_CHOICES, default='') is_previously_logged_in = models.CharField(max_length=5, default=False) email_confirmed = models.BooleanField(default=False) profile_picture = ProcessedImageField( upload_to='profiles', processors=[ResizeToFill(300, 300)], format='JPEG', options={'quality': 99}, default=DEFAULT, ) def is_mentor(self): return self.role == 'mentor' def is_mentee(self): return self.role == 'mentee' class Meta: db_table = 'auth_profile' def __str__(self): return self.user.username def get_gravatar(self): gravatar_url = 'https://www.gravatar.com/avatar/{0}?{1}'.format( hashlib.md5(self.user.email.lower().encode('utf-8')).hexdigest(), urlencode({'s': '256'})) return gravatar_url def get_screen_name(self): if self.user.get_full_name(): return self.user.get_full_name() else: return self.user.username def notify_favorited(self, question): if self.user != question.user: Notification(notification_type=Notification.FAVORITED, from_user=self.user, to_user=question.user, question=question).save() def unotify_favorited(self, question): if self.user != question.user: Notification.objects.filter( notification_type=Notification.FAVORITED, from_user=self.user, to_user=question.user, question=question).delete() def notify_answered(self, question): if self.user != question.user: Notification(notification_type=Notification.ANSWERED, from_user=self.user, to_user=question.user, question=question).save() def notify_also_answered(self, question): answers = question.get_answers() users = [] for answer in answers: if answer.user != self.user and answer.user != question.user: users.append(answer.user.pk) users = list(set(users)) for user in users: Notification(notification_type=Notification.ALSO_ANSWERED, from_user=self.user, to_user=User(id=user), question=question).save() def notify_accepted(self, answer): if self.user != answer.user: Notification(notification_type=Notification.ACCEPTED_ANSWER, from_user=self.user, to_user=answer.user, answer=answer).save() def unotify_accepted(self, answer): if self.user != answer.user: Notification.objects.filter( notification_type=Notification.ACCEPTED_ANSWER, from_user=self.user, to_user=answer.user, answer=answer).delete() def notify_article_commented(self, article): if self.user != article.create_user: Notification(notification_type=Notification.COMMENTED, from_user=self.user, to_user=article.create_user, article=article).save() def also_article_commented(self, article): comments = article.get_comments() users = [] for comment in comments: if comment.user != self.user and comment.user != article.create_user: users.append(article.create_user.pk) users = list(set(users)) for user in users: Notification(notification_type=Notification.ALSO_COMMENTED, from_user=self.user, to_user=User(id=user), article=article).save()
class Post(ModerationBaseModel, HitCountMixin): author = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_('Автор')) title = models.CharField( _('Заголовок'), max_length=150) slug = models.SlugField( _('Слаг'), max_length=60, unique=False, help_text=_('Слаг — это вариант названия, подходящий для URL. ' 'Обычно содержит только латинские буквы в нижнем регистре, цифры и дефисы.')) content = models.TextField( _('Контент'),) excerpt = models.TextField( _('Описание'), blank=True, help_text=_('По Умолчанию первый абзац Контента, при необходимости можно изменить.')) main = models.BooleanField( _('Главная страница'), default=False, help_text=_('Решает будет ли запись видна на главной странице.')) ordering = models.SmallIntegerField( _('Сортировка'), default=0, blank=True, null=True) hit_count_generic = GenericRelation( HitCount, object_id_field='object_pk', related_query_name='hit_count_generic_relation') thumbnail = models.ImageField( _('Миниатюра'), blank=True, null=True) video_link = models.TextField( _('Video from YpuTube or Vimeo'), blank=True, default='') big_thumbnail = models.BooleanField( _('Большая миниатюра'), default=False, help_text=_('Если отмечено, на превью будет большая миниатюра.')) thumbnail_big = ImageSpecField( source='thumbnail', processors=[ResizeToFit(width=620)], format='JPEG') thumbnail_small = ImageSpecField( source='thumbnail', processors=[ResizeToFill(100, 100)], format='JPEG') tags = TaggableManager(blank=True) class Meta: ordering = ["-created_at"] verbose_name = _('Пост') verbose_name_plural = _('Посты') def __str__(self): return self.title def get_absolute_url(self): return reverse("blog:detail", kwargs={"slug": self.slug, "id": self.id}) def save(self, *args, **kwargs): if self.slug == '': self.slug = slugify(unidecode(self.title)[:60]) if self.thumbnail is None or self.thumbnail == '': self.thumbnail = get_image(self.content) if self.excerpt == '': self.excerpt = strip_tags(get_excerpt(self.content)) return super(Post, self).save(*args, **kwargs) def get_conttent_type(self): conttent_type = ContentType.objects.get_for_model(self.__class__) return conttent_type
class Tour(models.Model): name = models.CharField(max_length=250) alias = models.CharField(max_length=250, unique=True) # url-safe date_start = models.DateField('Tour Started', null=True) track = MultiLineStringField(null=True, blank=True) #date_end = models.CharField('Tour Finished', null=True) #countries = models.ManyToMany(Country, blank=True) color = RGBColorField(default='#000000') #length = models.FloatField(blank=True) img = models.ImageField(upload_to='header', null=True, blank=True) img_thumb = ImageSpecField(source='img', processors=[ResizeToFill(100,100)], format='JPEG', options={'quality': 60}) #tourlog = models.TextField(blank=True) # html or md content? text = models.TextField(blank=True, null=True) # bericht = MarkdownxField(blank=True, null=True) bericht = RichTextUploadingField(blank=True, null=True) listed = models.BooleanField(default=True) short_text = models.CharField(max_length=600, default='Kurzbeschreibung') def __str__(self): """ Diese Funktion wird automatisch von python/django aufgerufen um ein Objekt zu bennen. """ return self.name def get_duration(self): """ returns duration of the tour if start and finish date are set correct. :return duration: <datetime.timedelta> """ try: #duration = date_start - date_end duration = 5 except: duration = dt.timedelta(days=0) return duration @property def dauer(self): """Berechnet die anzahl der tage aus start-enddatum oder anzahl der tagebuch einträge """ try: duration = self.date_finish - self.date_start days = duration.days except: from logbuch.models import Logbucheintrag logs = Logbucheintrag.objects.filter(tour=self) days = len(logs) return days @property def strecke(self): """Berechnet strecke als summe aller tageskilometer""" from logbuch.models import Logbucheintrag logs = Logbucheintrag.objects.filter(tour=self) km = 0 for log in logs: try: km += log.strecke except: pass return km @property def hoehe(self): """Hoehe als summe aller tagesdaten""" from logbuch.models import Logbucheintrag logs = Logbucheintrag.objects.filter(tour=self) hm = 0 for log in logs: try: hm += log.hoehe except: pass return hm def bericht_html(self): return markdownify(self.bericht)
class Images(models.Model): photo = ProcessedImageField(upload_to=user_path, processors=[ResizeToFill(80, 80)], format='JPEG', options={'qulity': 60}, null=True)
class User(models.Model): gender = ( ('male', "男"), ('female', "女"), ) # zone = models.OneToOneField(to='forum.Zone', to_field='id', null=True, on_delete=models.CASCADE) avatar = ProcessedImageField(verbose_name='头像', upload_to='user_avatar/', blank=True, null=False, default='avatar.png', processors=[ResizeToFill(150, 150)]) name = models.CharField(verbose_name='用户名', max_length=128, unique=True) age = models.IntegerField(verbose_name='年龄', blank=True, null=True) password = models.CharField(verbose_name='密码', max_length=256) email = models.EmailField(verbose_name='邮箱', unique=True) sex = models.CharField(verbose_name='性别', max_length=32, choices=gender, default="男") school = models.CharField(verbose_name='学校', max_length=128, null=True, blank=True) major = models.CharField(verbose_name='专业', max_length=128, null=True, blank=True) is_admin = models.BooleanField(verbose_name='管理员', default=False) c_time = models.DateTimeField(verbose_name='注册时间', auto_now_add=True) exp = models.IntegerField(verbose_name='经验值', default=0) level = models.IntegerField(verbose_name='等级', default=1) is_ban = models.BooleanField(verbose_name='禁言', default=False) is_read = models.BooleanField(verbose_name='已阅读新手教程', default=False) levelname = models.CharField(verbose_name='称号', default='新手', max_length=128) def save(self): if self.avatar is None: self.avatar = 'avatar.png' if int(self.exp) < 0: self.exp = 0 self.level = int(math.sqrt(int(self.exp)) // 10 + 1) if self.level <= 2: self.levelname = '新手' elif self.level <= 4: self.levelname = '咸鱼' elif self.level <= 6: self.levelname = '熟练' elif self.level <= 8: self.levelname = '高手' elif self.level <= 10: self.levelname = '水怪' else: self.levelname = '水怪' self.level = 10 if self.is_admin: self.is_read = True super(User, self).save() def __str__(self): return self.name class Meta: ordering = ["-c_time"] def get_absolute_url(self): # return reverse('space', args=str(self.id)) return reverse('space', kwargs={"id": str(self.id)})
class Film(models.Model): CERTIFICATES = [ ("U", "U"), ("PG", "PG"), ("12A", "12A"), ("12", "12"), ("15", "15"), ("18", "18"), ("TBC", "TBC"), ] name = models.CharField(max_length=100, null=True) director = models.CharField(max_length=100, null=True) cast = models.CharField(max_length=100, null=True) country = models.CharField(max_length=50, null=True) year = models.CharField(max_length=10, null=True) certificate = models.CharField(max_length=10, choices=CERTIFICATES, null=True) length = models.PositiveIntegerField( null=True, help_text="In minutes", ) trailer = models.URLField(max_length=100, help_text="Youtube or Vimeo link", blank=True, null=True) copy = HTMLField("Text", help_text="Only if the screening needs special copy", null=True) quote = models.TextField(max_length=500, blank=True) quote_source = models.CharField(max_length=100, blank=True) image = models.ImageField( default="default.jpg", help_text="Dimensions 1200px+ width work best", upload_to="films", ) image_credit = models.CharField(max_length=100, blank=True) slug = models.SlugField(default="film", editable=False) image_thumbnail = ImageSpecField( source="image", processors=[ResizeToFill(350, 350)], format="JPEG", options={"quality": 100}, ) def __str__(self): return self.name class Meta: ordering = ["name"] def get_absolute_url(self): kwargs = {"slug": self.slug, "pk": self.pk} return reverse("film-detail", kwargs=kwargs) def save(self, *args, **kwargs): value = self.name self.slug = slugify(value) super().save(*args, **kwargs) img = Image.open(self.image.path) if img.width > 1400 or img.height > 1000: img.thumbnail((1400, 1000), Image.ANTIALIAS) img.save(self.image.path, optimize=True)
class AdminThumbnailSpec(ImageSpec): processors = [ResizeToFill(100, 100)] format = 'JPEG' options = {'quality': 90 }
class Project(models.Model): """ Project model. Stores basic metadata, information about the project, donations, energy impact, goals, and info about the organization. Note about project statuses: there are five kinds of statuses that a project can have, and we show projects to different users in different ways based on their status. When an ambassador or admin first creates a project, it becomes DRAFTED, which means that it's a draft and can be edited, but is not in a complete state yet (description may need editing, etc). Eventualy the ambassador can propose the project for review from the admins, at which time it becomes PROPOSED. A proposed project is viewable by admins in their dashboard, as well as by the ambassadors that created it. When an admin approves a project, it becomes STAGED, which means it is ready to go but is not active yet, and as such is not viewable by the public. Staged projects are also visible to all admins in their dashboards. When it's time for the project to go live and start accepting donations, the admin can mark it as ACTIVE, which means it will actually be public and people can donate to it. When a project is done, the admin can mark it as COMPLETED, at which point it will stop accepting donations and start using repayments. """ ACTIVE = 'AC' STAGED = 'ST' PROPOSED = 'PR' COMPLETED = 'CO' DRAFTED = 'DR' PROJECT_STATUS_CHOICES = ( (ACTIVE, 'Active'), (STAGED, 'Staged'), (PROPOSED, 'Proposed'), (COMPLETED, 'Completed'), (DRAFTED, 'Drafted'), ) LESS_THAN_ONE_DAY_LEFT_STATEMENT = "only hours left" NO_DAYS_LEFT_STATEMENT = "deadline reached" funding_goal = models.DecimalField( max_digits=15, decimal_places=2, help_text='How much do you aim to raise for this project?') total_kwh_value = models.DecimalField( max_digits=15, decimal_places=2, default=0, help_text= 'How much is the total kWH value for 25 years to this project?') project_url = models.CharField( max_length=255, null=True, blank=False, help_text='How to show project url for this project?') title = models.CharField( max_length=255, help_text='How would you like to title this project?') tagline = models.CharField( max_length=100, null=True, blank=False, help_text= 'Select a short tag line that describes this project. (No more than 100 characters.)' ) video_url = models.URLField( 'Video URL', max_length=255, blank=False, help_text='Link to a Youtube video about the project or community.', ) # power output of array in kilowatts impact_power = models.FloatField( 'Expected Killowatt Output', help_text= 'What is the expected output in killowatts of the proposed solar array?' ) # solar log graphics url solar_url = models.URLField( 'Solar Log Graphics URL', max_length=255, blank=True, help_text= 'This can be found by going to http://home.solarlog-web.net/, going to the \ solar log profile for your site, and clicking on the Graphics sub-page. Copy and paste \ the URL in the address bar into here.') location = models.CharField( 'Organization Address', max_length=255, help_text= 'What is the address of the organization where the solar panels will be installed?' ) # latitude and longitude of the organization location location_latitude = models.DecimalField(max_digits=17, decimal_places=14, default=0.0) location_longitude = models.DecimalField(max_digits=17, decimal_places=14, default=0.0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) end_date = models.DateField( help_text='When will this crowdfunding project end?') # the start date of a project is whenever the project becomes live, # so we have to set it dynamically. Accordingly, the start_date # field is blank=True. start_date = models.DateField(blank=True, null=True) project_status = models.CharField(max_length=2, choices=PROJECT_STATUS_CHOICES, default=DRAFTED) cover_photo = ProcessedImageField( upload_to='covers/', processors=[ResizeToFill(1200, 500)], format='JPEG', options={'quality': 80}, default=None, help_text= 'Choose a beautiful high resolution image to represent this project.', blank=False, ) preview_photo = ImageSpecField( source='cover_photo', processors=[ResizeToFill(400, 300)], format='JPEG', options={'quality': 80}, ) org_start_date = models.DateField( 'Organization Founding Date', blank=True, null=True, help_text='When was the organization being helped established?') org_name = models.CharField( 'Organization Name', max_length=255, help_text='What is the name of the organization being helped?') people_affected = models.PositiveIntegerField( default=0, help_text='How many people will be impacted by this project?') mission_statement = models.TextField( 'Organization Mission', help_text= 'What is the mission statement of the organization being helped by this project?', ) org_about = models.TextField( 'Organization Description', help_text= 'Elaborate more about the organization, what it does, who it serves, etc.' ) description = RichTextField( 'Project description', help_text= 'This is the body of content that shows up on the project page.') donors = models.ManyToManyField(RevolvUserProfile, blank=True) created_by_user = models.ForeignKey(RevolvUserProfile, related_name='created_by_user') ambassadors = models.ManyToManyField(RevolvUserProfile, related_name='ambassadors', null=True) # energy produced in kilowatt hours actual_energy = models.FloatField(default=0.0) internal_rate_return = models.DecimalField( 'Internal Rate of Return', max_digits=6, decimal_places=3, default=0.0, help_text='The internal rate of return for this project.') # solar data csv files daily_solar_data = models.FileField(blank=True, null=True, upload_to="projects/daily/") monthly_solar_data = models.FileField(blank=True, null=True, upload_to="projects/monthly/") annual_solar_data = models.FileField(blank=True, null=True, upload_to="projects/annual/") monthly_reinvestment_cap = models.FloatField(blank=True, default=0.0) is_paid_off = models.BooleanField(blank=True, default=False) objects = ProjectManager() factories = ImportProxy("revolv.project.factories", "ProjectFactories") def has_owner(self, creator): return self.created_by_user == creator def approve_project(self): self.project_status = Project.ACTIVE if self.start_date is None: self.start_date = datetime.date.today() self.save() return self # TODO(noah): change this verbiage. we should probably call the STAGED -> ACTIVE # transition "activate_project" and the PROPOSED -> STAGED transition "approve_project" # instead. def stage_project(self): self.project_status = Project.STAGED self.save() return self def unapprove_project(self): self.project_status = Project.STAGED self.start_date = None self.save() return self def propose_project(self): self.project_status = Project.PROPOSED self.save() return self def deny_project(self): self.project_status = Project.DRAFTED self.save() return self def complete_project(self): self.project_status = Project.COMPLETED self.save() return self def mark_as_incomplete_project(self): self.project_status = Project.ACTIVE self.save() return self def update_categories(self, category_list): """ Updates the categories list for the project. :category_list The list of categories in the submitted form """ # Clears all the existing categories self.category_set.clear() # Adds the list of categories to the project for category in category_list: category_object = Category.objects.get(title=category) self.category_set.add(category_object) def get_absolute_url(self): return reverse("project:view", kwargs={"title": str(self.project_url)}) def get_organic_donations(self): return self.payment_set.exclude(user__isnull=True).filter( entrant__pk=models.F('user__pk')) def proportion_donated(self, user): """ :return: The proportion that this user has organically donated to this project as a float in the range [0, 1] (inclusive) """ user_donation = Payment.objects.donations( project=self, user=user, organic=True).aggregate( models.Sum('amount'))['amount__sum'] or 0.0 prop = user_donation / self.amount_donated_organically assert 0 <= prop <= 1, "proportion_donated is incorrect!" return prop def get_anonymous_donors_count(self): """ Total number of anonymous donors count for project :return: Return anonymous donors count for project """ user_id = User.objects.get(username='******').pk anonymous_user = RevolvUserProfile.objects.get(user_id=user_id) return Payment.objects.donations(anonymous_user, self).values("user").count() def total_donors(self): """ Total number of donors for the project. This include distinct number of donors to project and all anonymous donors for the project :return: Return total number of donors """ user_id = User.objects.get(username='******').pk anonymous_user = RevolvUserProfile.objects.get(user_id=user_id) donor_count = Payment.objects.filter( project=self, admin_reinvestment__isnull=True).exclude( user=anonymous_user).values("user").distinct().count() anonymous_donors_count = Payment.objects.filter( project=self, user=anonymous_user).values("user").count() return donor_count + anonymous_donors_count def total_donors_user(self): user_id = User.objects.get(username='******').pk anonymous_user = RevolvUserProfile.objects.get(user_id=user_id).id payments = Payment.objects.filter(project=self, admin_reinvestment__isnull=True).distinct('user__id')\ .exclude(user_id=anonymous_user) return payments @property def amount_donated_organically(self): """ :return: the current total amount that has been organically donated to this project, as a float. """ return self.get_organic_donations().aggregate( models.Sum('amount'))["amount__sum"] or 0.0 @property def location_street(self): """ :return: a string of the street name of the location of this project. If the project location is malformed, will return an empty string. """ try: return self.location.split(',')[0] except IndexError: return "" @property def location_city_state_zip(self): """ :return: a string of the city, state, and zip code of the location of this project. If the project location is malformed, will return an empty string. """ try: pieces = self.location.split(',') if len(pieces) >= 3: return pieces[1] + "," + pieces[2] elif len(pieces) == 2: return pieces[1] return pieces[0] except IndexError: return "" @property def amount_donated(self): """ :return: the current total amount that has been donated to this project, as a float. """ return self.payment_set.aggregate( models.Sum('amount'))["amount__sum"] or 0.0 @property def amount_left(self): """ :return: the current amount of money needed for this project to reach its goal, as a float. """ amt_left = float(self.funding_goal) - self.amount_donated if amt_left < 0: return 0.0 return amt_left @property def amount_repaid(self): """ :return: the current amount of money repaid by the project to RE-volv. """ return self.adminrepayment_set.aggregate( models.Sum('amount'))["amount__sum"] or 0.0 @property def total_amount_to_be_repaid(self): """ :return: the total amount of money to be repaid by the project to RE-volv. """ # TODO (https://github.com/calblueprint/revolv/issues/291): Actually # calculate this amount based off of interest, but using the project's # funding goal is sufficient for now. return self.funding_goal @property def rounded_amount_left(self): """ :return: The amount needed to complete this project, floored to the nearest dollar. Note: if for some reason the amount left is negative, this will perform a ceiling operation instead of a floor, but that should never happen. """ return int(self.amount_left) @property def partial_completeness(self): """ :return: a float between 0 and 1, representing the completeness of this project with respect to its goal (1 if exactly the goal amount, or more, has been donated, 0 if nothing has been donated). """ ratio = self.amount_donated / float(self.funding_goal) return min(ratio, 1.0) @property def percent_complete(self): """ :return: a floored int between 0 and 100, representing the completeness of this project with respect to its goal (100 if exactly the goal amount, or more, has been donated, 0 if nothing has been donated). """ return int(self.partial_completeness * 100) def partial_completeness_as_js(self): return unicode(self.partial_completeness) @property def percent_repaid(self): """ :return: a floored int between 0 and 100, representing the amount repaid in respect to its repayment goal (100 if exactly the goal amount, or more, has been donated, 0 if nothing has been donated). """ return int(self.partial_repayment * 100) @property def partial_repayment(self): """ :return: a float between 0 and 1, representing the repayment progress of this project with respect to the repayment goal (1 if exactly the goal amount, or more, has been donated, 0 if nothing has been donated). """ ratio = self.amount_repaid / float(self.total_amount_to_be_repaid) return min(ratio, 1.0) def partial_repayment_as_js(self): return unicode(self.partial_repayment) @property def total_days(self): """ :return the total length of the campaign of this project, or None if the project hasn't started yet. Note: if a project's campaign starts and ends on the same day, it is defined to be one day long, not zero days long. """ if self.start_date is None: return None return max((self.end_date - self.start_date).days + 1, 0) @property def days_until_end(self): """ :return: the difference between today and the end date of this project. May be negative. """ return (self.end_date - datetime.date.today()).days @property def days_so_far(self): """ :return: the integer number of days that have passed since this project's campaign began, or None if it has not started yet. """ if self.start_date is None: return None difference = (datetime.date.today() - self.start_date).days if difference < 0: return 0 if difference > self.total_days: return self.total_days return difference @property def days_left(self): """ :return: the integer number of days until the end of this project, or 0 if the project's campaign has finished. """ return max(self.days_until_end, 0) def formatted_days_left(self): """ :return: the number of days left in this project's campaign, formatted according to how many days left there are. This includes a default message when there are 0 days left instead of just saying "0". TODO: this should probably be moved to the template logic. """ days_left = self.days_until_end if days_left == 1: return "1 day left" if days_left == 0: return self.LESS_THAN_ONE_DAY_LEFT_STATEMENT if days_left < 0: return self.NO_DAYS_LEFT_STATEMENT return unicode(days_left) + " days left" @property def is_active(self): return self.project_status == Project.ACTIVE @property def is_proposed(self): return self.project_status == Project.PROPOSED @property def is_drafted(self): return self.project_status == Project.DRAFTED @property def is_staged(self): return self.project_status == Project.STAGED @property def is_completed(self): return self.project_status == Project.COMPLETED @property def status_display(self): return dict(Project.PROJECT_STATUS_CHOICES)[self.project_status] @property def categories(self): return [category.title for category in self.category_set.all()] @property def updates(self): """ :return: The set of all ProjectUpdate models associated with this project. """ return self.updates.all() @property def donation_levels(self): """ :return: The set of all DonationLevel models associated with this project. """ return self.donationlevel_set.all() @property def statistics(self): """ Return a revolv.project.stats.KilowattStatsAggregator for this project. Having this as a property is usefule in templates where we need to display statistics about the project (e.g. lbs carbon saved, $ saved, etc). """ return KilowattStatsAggregator.from_project(self) def add_update(self, text): update = ProjectUpdate(update_text=text, project=self) update.save() @property def reinvest_amount_left(self): """ :return max reinvestment can be receive """ return min(self.amount_left, self.monthly_reinvestment_cap) def get_statistic_for_project(self): user_impact = 0 project_funding_total = (int)(self.funding_goal) amount_donated = (int)(self.amount_donated) project_total_kwh_value = self.total_kwh_value total_carbon_avoided = float(project_total_kwh_value) * 1.5 per_doller_co2_avoided = total_carbon_avoided / project_funding_total project_impact = per_doller_co2_avoided * amount_donated user_impact += project_impact return user_impact def paid_off(self): """Set the project PAID_OFF flag """ self.is_paid_off = True self.save() def __unicode__(self): return self.title + '-' + self.project_status
class Background(ImageSpec): processors = [ResizeToFill(1920, 1200)] format = "JPEG" options = {"quality": 60}