def image_formatted(self): f = ImageSpecField( source="image", format="PNG", options={"quality": self.bit.image_quality}, processors=[ResizeToFill(self.bit.image_x, self.bit.image_y)], ) f.contribute_to_class(ContentBit, "image_formatted") return self.image_formatted
class UserProfile(models.Model): """ユーザー情報(JoiRePa用) user_account: Parks共通アカとの紐付け display_name: 表示用名前 birthday: 誕生日 details: ユーザー詳細 homepage: ホームページ title: 肩書き image_origin: プロフィール画像 アップロード保存 image_thumnail,middle: プロフィール画像 表示用 """ user_account = models.OneToOneField(UserAccount, on_delete=models.CASCADE) display_name = models.CharField(max_length=128, blank=False, default=user_account.name) birthday = models.DateField(blank=False, default='2000-01-01') details = models.TextField(blank=True) homepage = models.URLField(blank=True) title = models.CharField(max_length=128,blank=True) def get_image_path(self, filename): """カスタマイズした画像パスを取得する. :param self: インスタンス (models.Model) :param filename: 元ファイル名 :return: カスタマイズしたファイル名を含む画像パス """ prefix = 'user_profile/' name = str(uuid.uuid4()).replace('-', '') extension = os.path.splitext(filename)[-1] return prefix + name + extension def delete_previous_file(function): """不要となる古いファイルを削除する為のデコレータ実装.(未検証) :param function: メイン関数 :return: wrapper """ def wrapper(*args, **kwargs): """Wrapper 関数. :param args: 任意の引数 :param kwargs: 任意のキーワード引数 :return: メイン関数実行結果 """ self = args[0] # 保存前のファイル名を取得 result = UserProfile.objects.filter(pk=self.pk) previous = result[0] if len(result) else None super(UserProfile, self).save() # 関数実行 result = function(*args, **kwargs) # 保存前のファイルがあったら削除 if previous: file_path = settings.MEDIA_ROOT + '/' + previous.image_origin.name if os.path.isfile(file_path): os.remove(file_path) return result return wrapper @delete_previous_file def save(self, force_insert=False, force_update=False, using=None, update_fields=None): super(UserProfile, self).save() @delete_previous_file def delete(self, using=None, keep_parents=False): super(UserProfile, self).delete() image_origin = models.ImageField(_('image_origin'), upload_to=get_image_path, blank=True) image_thumbnail = ImageSpecField(source='image_origin', processors=[ResizeToFill(250,250)], format="JPEG", options={'quality': 60} ) image_middle = ImageSpecField(source='image_origin', processors=[ResizeToFill(400, 400)], format="JPEG", options={'quality': 75} ) def __str__(self): return self.display_name
class Event(models.Model): """ Container model for general metadata and associated ``Occurrence`` entries. """ image = models.ImageField(verbose_name="Image", default=None, null=True, upload_to='events/') title = models.CharField(verbose_name="Titre", max_length=100, default=None, null=True) description = models.TextField(verbose_name="Description", default=None, null=True) event_type = models.ForeignKey(EventType, verbose_name="Catégorie", default=None, null=True, on_delete=models.SET_DEFAULT, ) price = models.PositiveSmallIntegerField(verbose_name="Prix en euros", default=0) contact = models.CharField(verbose_name="Coordonnées du contact éventuel", max_length=150, default="non précisé", null=True, blank=True) website = models.CharField(verbose_name="Lien vers le site officiel de l'événement", max_length=150, default="non précisé", null=True, blank=True) image_main = ImageSpecField(source='image', processors=[ResizeToFill(800, 300)], format='JPEG', options={'quality': 100}, ) event_planner = models.ForeignKey(EnjoyTodayUser, on_delete=models.CASCADE, default=None, null=True, verbose_name='annonceur', ) address = models.CharField(verbose_name="Adresse", max_length=150, default="non précisé") #public_transport = models.CharField(verbose_name="Arrêt transport en commun (métro,...)", # max_length=150, # default="non précisé", # null=True, # blank=True # ) site = models.ForeignKey(Site, default=None, null=True, on_delete=models.SET_DEFAULT, # if affected, breaks # default=None, ) objects = models.Manager() on_site = CurrentSiteManager() # =========================================================================== class Meta: verbose_name = 'event' verbose_name_plural = 'events' ordering = ('title', ) # --------------------------------------------------------------------------- def __str__(self): return self.title # -------------------------------------------------------------------------- #def get_absolute_url(self): #return reverse('', kwargs={'event_id': self.pk}) def delete_url(self): return reverse('catho:crud:delete_event', kwargs={'event_id': self.pk}) def update_url(self): return reverse('catho:crud:update_event', kwargs={'event_id': self.pk}) # -------------------------------------------------------------------------- def add_occurrences(self, start_time, end_time, is_multiple, **rrule_params): """ Add one or more occurences to the event using a comparable API to ``dateutil.rrule``. Because ``rrule.rrule`` returns an iterator that can essentially be unbounded, we need to slightly alter the expected behavior here in order to enforce a finite number of occurrence creation. If ``until`` entry is missing from ``rrule_params``, only a single ``Occurrence`` instance will be created using the exact ``start_time`` and ``end_time`` values. """ until = rrule_params.get('until') if not until: self.occurrence_set.create(start_time=start_time, end_time=end_time) else: delta_hour = end_time - start_time occurrences = [] for ev in rrule.rrule(dtstart=start_time, **rrule_params): occurrences.append(Occurrence(start_time=ev, end_time=ev + delta_hour, event=self, is_multiple=is_multiple)) self.occurrence_set.bulk_create(occurrences) # -------------------------------------------------------------------------- def upcoming_occurrences(self): """ Return all occurrences that are set to start on or after the current time. """ return self.occurrence_set.filter(start_time__gte=datetime.now()) # -------------------------------------------------------------------------- def next_occurrence(self): """ Return the single occurrence set to start on or after the current time if available, otherwise ``None``. """ upcoming = self.upcoming_occurrences() return upcoming[0] if upcoming else None
class Image(TimeStampedModel): user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE) original = models.ImageField( upload_to="cast_images/originals", height_field="original_height", width_field="original_width", ) original_height = models.PositiveIntegerField(blank=True, null=True) original_width = models.PositiveIntegerField(blank=True, null=True) img_full = ImageSpecField( source="original", processors=[Transpose()], format="JPEG", options={"quality": 60}, ) IMAGE_SIZES = { "img_full": None, "img_xl": 2200, "img_lg": 1100, "img_md": 768, "img_sm": 500, "img_xs": 300, } img_xl = image_spec_thumbnail(IMAGE_SIZES["img_xl"]) img_lg = image_spec_thumbnail(IMAGE_SIZES["img_lg"]) img_md = image_spec_thumbnail(IMAGE_SIZES["img_md"]) img_sm = image_spec_thumbnail(IMAGE_SIZES["img_sm"]) img_xs = image_spec_thumbnail(IMAGE_SIZES["img_xs"]) sizes = [(v, k) for k, v in IMAGE_SIZES.items()] post_context_key = "image" def get_all_paths(self): paths = set() paths.add(self.original.name) for size, attr_name in self.sizes: paths.add(getattr(self, attr_name).name) return paths def __str__(self): return self.original.name def get_srcset(self): sources = [] for size, attr_name in self.sizes: img = getattr(self, attr_name) width = self.original_width if size is None else size url = img.url sources.append(url) sources.append("{}w,".format(width)) return " ".join(sources) @property def srcset(self): return self.get_srcset() @property def thumbnail_src(self): return self.img_xs.url @property def full_src(self): return self.img_full.url
class Video(TimeStampedModel): user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE) original = models.FileField(upload_to="cast_videos/") poster = models.ImageField(upload_to="cast_videos/poster/", null=True, blank=True) poster_seconds = models.FloatField(default=1) poster_thumbnail = ImageSpecField( source="poster", processors=[Thumbnail(300, 300, crop=False)], format="JPEG", options={"quality": 60}, ) post_context_key = "video" calc_poster = True def _get_video_dimensions(self, video_url): ffprobe_cmd = 'ffprobe -i "{}"'.format(video_url) result = subprocess.check_output( ffprobe_cmd, shell=True, stderr=subprocess.STDOUT ) lines = result.decode("utf8").split("\n") return get_video_dimensions(lines) def _create_poster(self): """Moved into own method to make it mockable in tests.""" fp, tmp_path = tempfile.mkstemp(prefix="poster_", suffix=".jpg") logger.info("original url: {}".format(self.original.url)) video_url = self.original.url if not video_url.startswith("http"): video_url = self.original.path width, height = self._get_video_dimensions(video_url) poster_cmd = ( 'ffmpeg -ss {seconds} -i "{video_path}" -vframes 1' " -y -f image2 -s {width}x{height} {poster_path}" ).format( video_path=video_url, seconds=self.poster_seconds, poster_path=tmp_path, width=width, height=height, ) logger.info(poster_cmd) check_output(poster_cmd, shell=True) name = os.path.basename(tmp_path) content = DjangoFile(open(tmp_path, "rb")) self.poster.save(name, content, save=False) os.unlink(tmp_path) logger.info(self.pk) logger.info(self.poster) def create_poster(self): if self.poster or not self.calc_poster: # poster is not null logger.info("skip creating poster") else: try: self._create_poster() except Exception as e: logger.info(e) logger.info("create poster failed") def get_all_paths(self): paths = set() paths.add(self.original.name) if self.poster: paths.add(self.poster.name) try: if self.poster_thumbnail: paths.add(self.poster_thumbnail.name) except (FileNotFoundError, OSError): pass return paths def save(self, *args, **kwargs): generate_poster = kwargs.pop("poster", True) # need to save original first - django file handling is driving me nuts result = super().save(*args, **kwargs) if generate_poster: logger.info("generate video poster") # generate poster thumbnail by default, but make it optional # for recalc management command self.create_poster() # save again after adding poster result = super().save(*args, **kwargs) return result
class Post(models.Model): STATUS_CHOICES = Choices( (1, 'published', 'published'), (2, 'draft', 'draft'), (3, 'hidden', 'hidden'), ) status = models.PositiveSmallIntegerField(_('status'), choices=STATUS_CHOICES, default=STATUS_CHOICES.draft) title = models.CharField(_('title'), max_length=255) body = models.TextField(_('body')) excerpt = models.CharField(_('excerpt'), max_length=255, blank=True) views = models.PositiveIntegerField(_('views'), default=0, editable=False) pub_date = models.DateTimeField(_('publication time'), blank=True, null=True) # Do not user auto_add=True or auto_now_add=True since value is None before instance be saved created_time = AutoCreatedField(_('creation time')) modified_time = AutoLastModifiedField(_('modification time')) cover = models.ImageField(_('cover'), upload_to=post_cover_path, blank=True) cover_thumbnail = ImageSpecField(source='cover', processors=[ResizeToFill(60, 60)], format='JPEG', options={'quality': 90}) category = models.ForeignKey(Category, verbose_name=_('category'), null=True, blank=True) tags = models.ManyToManyField(Tag, verbose_name=_('tags'), blank=True) author = models.ForeignKey(settings.AUTH_USER_MODEL) comments = GenericRelation(BlogComment, object_id_field='object_pk', content_type_field='content_type') class Meta: ordering = ['-created_time'] def __str__(self): return self.title def save(self, *args, **kwargs): if not self.excerpt: md = markdown.Markdown(extensions=[ 'markdown.extensions.extra', 'markdown.extensions.codehilite', ]) # TODO: refactor and test self.excerpt = strip_tags(md.convert(self.body))[:150] if not self.pub_date and self.status == self.STATUS_CHOICES.published: self.pub_date = self.created_time super().save(*args, **kwargs) def get_absolute_url(self): return reverse('blog:detail', kwargs={'pk': self.pk}) def increase_views(self): self.views += 1 self.save(update_fields=['views']) def word_count(self): md = markdown.Markdown(extensions=[ 'markdown.extensions.extra', 'markdown.extensions.codehilite', ]) # TODO: refactor and test return len(strip_tags(md.convert(self.body))) def is_tutorial(self): if not self.category: return False return self.category.get_genre_display() == 'tutorial' def root_comments(self): # TODO: move the logic to comment manager return self.comments.filter(parent__isnull=True, is_public=True, is_removed=False) def participants_count(self): return self.comments.values_list('user_id', flat=True).distinct().count()
class Loja(EditorialModel): def new_filename(instance, filename): fname, dot, extension = filename.rpartition('.') fname = slugify(fname) return os.path.join('lojas', '%s.%s' % (fname, extension)) shopping = models.ForeignKey(Shopping, verbose_name=u'Shopping', related_name='lojas') id_multilan = models.IntegerField('Id na Multiplan', null=True, blank=False) nome = models.CharField(u'Nome', max_length=100, null=True, blank=False) slug = models.CharField(u'Slug', max_length=150, null=True, blank=True) logo = models.ImageField(u'Imagem', upload_to=new_filename, null=True, blank=True) logo_120x50 = ImageSpecField( [Adjust(contrast=1.1, sharpness=1.1), resize.ResizeToFill(120, 50)], source='logo', format='PNG', options={'quality': 90}) telefone = models.CharField(u'telefone', max_length=100, null=True, blank=True) class Meta: verbose_name = u'Loja' verbose_name_plural = u'Lojas' ordering = ['nome'] def __unicode__(self): return u'%s - %s' % (self.nome, self.shopping) def to_dict(self): return { 'id': self.id, 'nome': self.nome, 'slug': self.slug, 'logo': self.logo_120x50.url if self.logo else None, 'telefone': self.telefone, 'shopping': self.shopping.to_dict() } @classmethod def publicadas_com_oferta(cls, shopping): lojas = cls.objects.filter(ofertas__status=1, ofertas__inicio__lte=date.today(), ofertas__fim__gt=datetime.now(), ofertas__loja__shopping_id=shopping)\ .order_by('nome')\ .distinct() return lojas '''return separa_tres_colunas([l.to_dict() for l in lojas])''' @classmethod def publicadas_sem_oferta(cls, shopping): lojas = cls.objects.filter(publicada=True, shopping_id=shopping).order_by('nome') return [l.to_dict() for l in lojas if not l.ofertas.filter(status=1)] @classmethod def relatorio_visitas(cls, shopping_id, date=None): if not date: return Loja.objects.annotate(vistas=Count( 'pk', only=Q(ofertas__logs__acao=1, shopping=shopping_id))).order_by('-vistas') else: return Loja.objects.annotate(vistas=Count('pk', only=Q(ofertas__logs__acao=1, shopping=shopping_id, ofertas__logs__data_criacao__gte=date)))\ .order_by('-vistas') @classmethod def relatorio_solicitacoes(cls, shopping_id, date=None): if not date: return Loja.objects.annotate( pedidos=Count('solicitacoes', only=Q( shopping=shopping_id))).order_by('-pedidos') else: return Loja.objects.annotate( pedidos=Count('solicitacoes', only=Q(shopping=shopping_id, solicitacoes__data_criacao__gte=date) )).order_by('-pedidos')
class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(verbose_name='Email Address', max_length=255, unique=True, db_index=True) USERNAME_FIELD = 'email' username = models.CharField(max_length=255, blank=True, null=True) is_active = models.BooleanField(default=False) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) gender = models.IntegerField(choices=GENDER_CHOICES) display_name = models.CharField(max_length=255, blank=True, null=True) about = models.TextField(max_length=255, blank=True, null=True) address = models.CharField(max_length=255, blank=True, null=True) phone = models.CharField(max_length=50, blank=True, null=True) avatar = models.ImageField(upload_to='avatars/', blank=True, null=True) avatar_thumb = ImageSpecField(source='avatar', processors=[ResizeToFill(150, 150)], format='JPEG', options={'quality': 90}) avatar_ext = models.CharField(max_length=255, blank=True, null=True) date_joined = models.DateTimeField(auto_now_add=True, null=True) objects = UserManager() def get_full_name(self): return "%s" % (self.display_name) def get_short_name(self): return self.email def __unicode__(self): return self.display_name def get_facebook_avatar(self, width, height): try: connections = UserSocialAuth.objects.all().filter( user=self, provider='facebook') if connections[0].uid: return 'https://graph.facebook.com/%s/picture?type=large&width=%s&height=%s' % ( connections[0].uid, width, height) except: return def get_avatar(self): avatar = self.get_facebook_avatar(300, 300) if avatar: return avatar elif self.avatar: return self.avatar.url elif self.avatar_ext: return self.avatar_ext else: return 'http://placehold.it/300x300.png' def get_avatar_thumb(self): avatar = self.get_facebook_avatar(140, 140) if avatar: return avatar elif self.avatar: return self.avatar_thumb.url elif self.avatar_ext: return self.avatar_ext else: return 'http://placehold.it/140x140.png' def get_absolute_url(self): return reverse('profile', args=[str(self.id)])
class Image(models.Model): CATEGORY_PROFILE = 'profile' CATEGORY_POST = 'post' user = models.ForeignKey(User, on_delete=models.PROTECT) # 投稿に紐づける post = models.ForeignKey(Post, on_delete=models.PROTECT, null=True) # 画像保存用のフィールド image = models.ImageField(upload_to='images', null=True, blank=True) # imageのリサイズを行う(使い方はpostの画像はmiddleにしてprofileの画像はthumbnailにするとか) big = ImageSpecField(source='image', processors=[ResizeToFill(1280, 1024)], format='JPEG') thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(250, 250)], format='JPEG', options={'quality': 60}) middle = ImageSpecField(source='image', processors=[ResizeToFill(600, 400)], format='JPEG', options={'quality': 75}) small = ImageSpecField(source='image', processors=[ResizeToFill(75, 75)], format='JPEG', options={'quality': 50}) # 論理削除 is_deleted = models.BooleanField(default=False) # categoryを分ける category = models.CharField(null=True, max_length=8) created_at = models.DateTimeField() updated_at = models.DateTimeField() class Meta: db_table = 'images' @staticmethod def create(file, category, user_id, post_id): # 今の時間 date = timezone.now() # 12文字で作成 file_name = str(uuid.uuid4())[:12] # fileの拡張子を取得 extension = imghdr.what(file_name, file) # jpegの時jpgにする extension = "jpg" if extension == "jpeg" else extension # fileの名前を定義 complete_file_name = "%s.%s" % (file_name, extension) # ImageFieldに保存するためのobject data = ContentFile(file, name=complete_file_name) # imageをdbに保存 image = Image.objects.create(user_id=user_id, category=category, post_id=post_id, created_at=date, updated_at=date) image.image.save(complete_file_name, data, save=True) return image
class Article(TimeStampedModel): """文章""" STATUS_CHOICES = ( ('d', '草稿'), ('p', '发表'), ) COMMENT_STATUS = ( ('o', '打开'), ('c', '关闭'), ) ARTTYPE = ( ('a', '文章'), ('p', '页面'), ) title = models.CharField('标题', max_length=200) body = models.TextField('正文') description = models.CharField('描述', max_length=1000) pub_time = models.DateTimeField('发布时间', blank=True, null=True, default=timezone.now) status = models.CharField('文章状态', max_length=1, choices=STATUS_CHOICES, default='p') comment_status = models.CharField('评论状态', max_length=1, choices=COMMENT_STATUS, default='o') arttype = models.CharField('类型', max_length=1, choices=ARTTYPE, default='a') views = models.PositiveIntegerField('浏览量', default=0) article_order = models.IntegerField('排序,数字越大越靠前', blank=False, null=False, default=0) cover = models.ImageField(upload_to="blog/cover", verbose_name=_('cover')) thumbnail = ImageSpecField(source='cover', processors=[ResizeToFill(400, 300)], format='JPEG', options={'quality': 90}) excerpt = models.CharField(max_length=200, blank=True) # created_time = models.DateTimeField('创建时间', default=timezone.now) # last_mod_time = models.DateTimeField('修改时间', default=timezone.now) User = get_user_model() creater = models.ForeignKey(User, on_delete=models.CASCADE, related_name="articles", blank=True, null=True) def __str__(self): return self.title class Meta: ordering = ['-article_order', '-pub_time'] verbose_name = "文章" verbose_name_plural = verbose_name get_latest_by = 'id' # def get_absolute_url(self): # return reverse('blog:detailbyid', kwargs={ # 'article_id': self.id, # 'year': self.created_time.year, # 'month': self.created_time.month, # 'day': self.created_time.day # }) def viewed(self): self.views += 1 self.save(update_fields=['views'])
class StoryObject(models.Model): CHARACTER = "Character" CREATURE = "Creature" THING = "Thing" FACTION = "Faction" ORGANIZATION = "Organization" TERRITORY = "Territory" PLACE = "Place" EVENT = "Event" CHAR_CHOICES = ( (FACTION, "Faction"), (CHARACTER, "Character"), (CREATURE, "Creature"), (ORGANIZATION, "Organization"), (PLACE, "Place"), (TERRITORY, "Territory"), (THING, "Thing"), (EVENT, "Event"), ) creator = models.ForeignKey(User, unique=False, blank=True) name = models.CharField(max_length=128, unique=False) story = models.ForeignKey('Story', default=1) c_type = models.CharField(choices=CHAR_CHOICES, max_length=32, default="Character", verbose_name="Story Object Type", help_text="Select a story object category.") role = models.CharField(max_length=256) core_role = models.BooleanField( default=False, help_text='''Select if this is a player character, a major protagonist or otherwise a critical element to your story. These elements will show up first in lists and have a graphic distinction. ''') description = MarkdownField(blank=True) image = ImageField(upload_to='profile_images/%Y/%m/%d/%H_%M_%S', default='profile_images/shadow_figure.jpeg') thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(50, 50)], format='JPEG', options={'quality': 60}) slug = models.SlugField(unique=True, max_length=255) published = models.BooleanField( default=True, help_text= "Elements that are NOT published will only be viewable in your Workshop." ) def save(self, slug=None, creator=None, *args, **kwargs): self.story.object_count = F('object_count') + 1 self.story.save() self.slug = slugify("{}-{}".format(self.story.id, self.name)) super(StoryObject, self).save(*args, **kwargs) def __str__(self): return self.name
class BaseImageMolecule(RichContentAtom, VersionableAtom, AddressibleAtom): help = { 'alt': "Alt text (very important for SEO)", 'use_png': "Render image as png instead of jpg when possible" } alt = models.CharField(_("Alt Text"), max_length=255, blank=True, help_text=help['alt']) # -- Variations thumbnail_jpg = ImageSpecField( source='image', format='JPEG', processors=[ ResizeToFit(settings.IMAGE_THUMBNAIL_WIDTH, settings.IMAGE_THUMBNAIL_HEIGHT) ], options={'quality': settings.IMAGE_THUMBNAIL_QUALITY}) thumbnail_png = ImageSpecField( source='image', format='PNG', processors=[ ResizeToFit(settings.IMAGE_THUMBNAIL_WIDTH, settings.IMAGE_THUMBNAIL_HEIGHT) ], options={'quality': settings.IMAGE_THUMBNAIL_QUALITY}) use_png = models.BooleanField(default=False, verbose_name='Use .PNG (instead of .JPG)', help_text=help['use_png']) image_width = models.IntegerField(null=True, blank=True) image_height = models.IntegerField(null=True, blank=True) class Meta: abstract = True def get_alt(self): if self.alt: return self.alt return self.title @cached_property def get_format(self): if self.use_png: return 'PNG' return 'JPEG' @cached_property def image_url(self): try: return self.image.url except: return None @cached_property def image_width(self): try: return self.image.width except: return None @cached_property def image_height(self): try: return self.image.height except: return None @cached_property def file(self): return self.image @cached_property def thumbnail(self): if self.use_png: return self.thumbnail_png else: return self.thumbnail_jpg @cached_property def thumbnail_url(self): try: return self.thumbnail.url except: return '' def get_variant_url(self, variant_name): try: field = getattr(self, variant_name) return field.url except Exception, err: print traceback.format_exc()
class Producto(models.Model): numero_serie = models.CharField( verbose_name = _('Numero Serie'), validators = [validador_numero_serie], help_text = 'Ingresa el numero de serie ej. USM-1001', unique = True, max_length = 100 ) nombre = models.CharField( verbose_name = _('Nombre'), max_length = 100 ) marca = models.CharField( verbose_name = _('Marca'), max_length = 100, default = 'USM' ) color = models.CharField( verbose_name = _('Color'), max_length=20 ) cantidad = models.IntegerField( verbose_name= _('Cantidad') ) precio_compra = models.DecimalField( verbose_name = _('Precio Compra'), max_digits = 7, decimal_places = 2, default = 0.00 ) precio_venta = models.DecimalField( verbose_name = _('Precio Venta'), max_digits = 7, decimal_places = 2, default = 0.00 ) proveedor = models.ForeignKey( Proveedor, verbose_name = _('Proveedor') ) caracteristicas = models.TextField( verbose_name = _('Caracteristicas'), null = True, blank = True ) tipo = models.CharField( verbose_name = _('Tipo'), max_length = 50, choices = TIPO_CHOICES, default = SCOOTER ) imagen = models.ImageField( verbose_name = _('Imagen'), null = True, blank = True, upload_to = "imagenes/productos/" ) thumbnail = ImageSpecField( source = 'imagen', processors = [ResizeToFill(100, 50)], format = 'JPEG', options = {'quality': 60} ) habilitado = models.BooleanField( verbose_name = _('Habilitado'), default = False ) def __str__(self): return self.numero_serie + " " + self.tipo class Meta: ordering = ['numero_serie'] verbose_name= 'Producto' verbose_name_plural = "Productos"
class Profile(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) SEX_CHOICES = ( (1, _('man')), (0, _('woman')), (None, _("don't show")) ) user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') sex = models.IntegerField(choices=SEX_CHOICES, blank=True, null=True, verbose_name=_('gender')) slug = models.SlugField( unique=True, max_length=100, help_text=_("automatically generated, don't change manually !"), ) address_line1 = models.CharField(verbose_name=_("address line1"), max_length=200, blank=True, null=True) address_line2 = models.CharField(verbose_name=_("address line2"), max_length=200, blank=True, null=True) city = models.CharField(_("city"), max_length=200, blank=True, null=True) state = CountryField(blank=True, null=True, blank_label=_('(select country)')) postal = models.CharField(_("postal"), max_length=200, blank=True, null=True) dob = models.DateField(null=True, blank=True, verbose_name=_('birthday')) phone = models.CharField( max_length=50, verbose_name=_("phone"), blank=True, null=True, ) cell = models.CharField( max_length=20, verbose_name=_("cell number"), blank=True, null=True, validators=[ RegexValidator( regex=r'^\+?1?\d{9,15}$', message=_("Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.") ) ] ) profile_image = ProcessedImageField(upload_to=UploadToPathAndRename('profile_images'), processors=[ ResizeToFill(400, 400), Adjust(sharpness=1.1, contrast=1.1)], format='JPEG', options={'quality': 90}, null=True, blank=True) created_date = models.DateTimeField(auto_now_add=True) modified_date = models.DateTimeField(auto_now=True) class Meta: ordering = ('-id',) def __str__(self): return self.user.username @property def user_container(self): # be carefull this data is exposed to frontend to user :) context = { "first_name": self.user.first_name, "last_name": self.user.last_name, "email": self.user.email } return json.dumps(context) # thumbnail for admin interface def admin_image_thumb(self): if self.profile_image: return mark_safe( '<img src="{0}{1}" width="100" height="100" />'.format(settings.MEDIA_URL, self.profile_image) ) else: return mark_safe( '<img src="{0}accounts/default-avatar.jpg" width="100" height="100" />'.format(settings.STATIC_URL) ) # small thumbnail and method for it profile_image_thumbnail_sm = ImageSpecField( source='profile_image', processors=[ResizeToFill(155, 155)], format='JPEG', options={'quality': 80} ) def get_avatar_sm(self): if self.profile_image: return self.profile_image_thumbnail_sm.url else: return '{}accounts/default-avatar_sm.jpg'.format(settings.STATIC_URL) # extra small thumbnail and method for it profile_image_thumbnail_xs = ImageSpecField( source='profile_image', processors=[ResizeToFill(48, 48)], format='JPEG', options={'quality': 80} ) def get_avatar_xs(self): if self.profile_image: return self.profile_image_thumbnail_xs.url else: return '{}accounts/default-avatar_xs.jpg'.format(settings.STATIC_URL)
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 = 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.""")) 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 = PassThroughManager.for_queryset_class(ShowManager)() 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 Image(models.Model): image = models.ImageField(upload_to='static/uploaded/images/%Y/%m/%d/', ) thumbnail = ImageSpecField(source='image', processors=[Thumbnail(width=290)], format='JPEG', options={'quality': 60})
class Initiative(models.Model): """Model to represent Initiative objects""" name = models.CharField( _('Nombre de la iniciativa'), max_length=200, blank=False, null=True, help_text=_('¿Cuál es el nombre de tu iniciativa?')) slug = models.SlugField(editable=False, blank=True) creation_date = models.DateField(editable=False, default=timezone.now) featured = models.BooleanField( _('Destacado'), blank=True, default=False, help_text=_('Indica si es una iniciativa destacada')) user = models.ForeignKey(User, verbose_name=_('Gestor'), blank=True, null=True, on_delete=models.SET_NULL) image = models.ImageField( _("Imagen"), blank=True, validators=[validate_image_size, validate_image_type], upload_to=initiatives_images_path, help_text= _("Sube una imagen representativa de la iniciativa haciendo click en la imagen inferior. " "La imagen ha de tener ancho mínimo de 600 píxeles y máximo de 1920, y altura mínima " "de 300 píxeles y máxima de 1280. Formatos permitidos: PNG, JPG, JPEG." )) image_medium = ImageSpecField( source="image", processors=[processors.ResizeToFill(600, 300)], format='JPEG', options={'quality': 90}) video = models.CharField( _('Video'), max_length=200, blank=True, null=True, help_text=_('Inserta la url de un video de Youtube o Vimeo')) description = models.TextField( _('Descripción de la iniciativa'), blank=False, null=True, help_text=_('Describe los objetivos y actividad de la iniciativa.')) website = models.URLField( _('Website'), blank=True, null=True, help_text=_( 'Especifica opcionalmente una web para conocer mejor la iniciativa.' )) twitter = models.CharField( _('Twitter'), blank=True, null=True, max_length=128, help_text=_( 'Si tienes una cuenta de Twitter, pon aquí el nombre de usuario.')) facebook = models.URLField( _('Facebook'), blank=True, null=True, help_text= _('Si tienes un perfil de Facebook pon aquí el enlace completo a la misma.' )) instagram = models.CharField( _('Instagram'), blank=True, null=True, max_length=128, help_text=_( 'Si tienes una cuenta de Instagram, pon aquí el nombre de usuario.' )) email = models.EmailField( _('Correo electrónico'), blank=False, null=True, help_text=_('Especifica un correo de contacto para la iniciativa.')) topic = models.CharField(_('Tema'), blank=False, null=False, default='DC', max_length=2, choices=categories.TOPICS, help_text=_('El tema de la iniciativa')) space = models.CharField( _('Tipo de espacio'), blank=False, null=False, default='CC', max_length=2, choices=categories.SPACES, help_text=_('El tipo de espacio asociado a la iniciativa')) agent = models.CharField( _('tipo de agente'), blank=False, null=False, default='IM', max_length=2, choices=categories.AGENTS, help_text=_('El tipo de agente involucrado en la iniciativa')) city = models.ForeignKey( City, verbose_name=_('Ciudad'), blank=False, null=True, on_delete=models.SET_NULL, help_text= _('Ciudad donde se encuentra la iniciativa. Si no encuentras la ciudad en el desplegable usa el botón inferior para añadir una nueva ciudad y seleccionarla' )) address = models.CharField( _('Dirección'), max_length=200, blank=False, null=True, help_text= _('Dirección de la iniciativa. No es necesario que vuelvas a introducir la ciudad de la iniciativa.' )) district = models.CharField( _('Distrito'), max_length=200, blank=True, null=True, help_text=_('¿En qué barrio de la ciudad se sitúa la iniciativa?')) position = PointField( _("Ubicación"), blank=False, null=True, help_text= _("Tras añadir ciudad y dirección puedes ubicar la iniciativa pulsando el botón inferior y ajustando la posición del marcador posteriormente." )) # ODS main_ods = models.ForeignKey( ODS, verbose_name=_('Objetivo de desarrollo sostenible principal'), blank=True, null=True, help_text= _('Indícanos que Objetivo de Desarrollo Sostenible (ODS) crees que cumple o trabaja principalmente tu iniciativa.' )) other_ods = models.ManyToManyField( ODS, verbose_name=_('Otros ODS'), blank=True, related_name='initiatives', help_text= _('Indícanos otros Objetivos de Desarrollo Sostenible (ODS) con los que también trabaja tu iniciativa (máximo 3). Puedes deseleccionar y hacer selecciones múltiples usando el ratón con la tecla Ctrl pulsada (Command en MAC)' )) # Relations initiatives = models.ManyToManyField('self', verbose_name=_('Relaciones'), blank=True) file = models.FileField( _('Archivo adjunto'), upload_to='files/initiatives', blank=True, validators=[validate_file_type], help_text=_( 'Puedes usar este campo para subir algún documento que explique ' 'mejor tu iniciativa. Sólo admite formato PDF.')) class Meta: verbose_name = _('Iniciativa') verbose_name_plural = _('Iniciativas') def __str__(self): """String representation of this model objects.""" return self.name or '---' @property def translated_name(self): print(self.request) @property def external_url(self): """Returns the first occurence of an external url related to the initiative""" if self.website: return self.website elif self.facebook: return self.facebook return "https://twitter.com/" + self.twitter def save(self, *args, **kwargs): """Populate automatically 'slug' field""" self.slug = slugify(self.name) # Notify by mail, only when creating new content if not self.id: send_mail( 'Creada la iniciativa \"' + self.name + "\"", 'Creada el ' + self.creation_date.strftime("%d/%b/%Y") + ' por ' + self.user.username + '\n---\n' + self.name + ' (' + self.email + '):\n' + self.description + '\n---\n' + 'Ciudad: ' + self.city.name, 'civics.cc <*****@*****.**>', settings.NOTIFICATIONS_EMAILS, fail_silently=False, ) super(Initiative, self).save(*args, **kwargs) def edit_permissions(self, user): """Returns users allowed to edit an instance of this model.""" if user.is_staff or (self.user and self.user == user): return True return False
class Drawing(TimeStampedModel): objects = DrawingManager() name = CharField( max_length=255, verbose_name=_('field-name'), help_text=_('field-name-help-text'), ) size = ForeignKey( 'DrawingSize', related_name='drawings', verbose_name=_('field-size'), ) status = PositiveIntegerField( choices=DRAWING_STATUS_CHOICES, default=DRAWING_STATUS_STORED, verbose_name=_('field-drawing-status'), ) image = ImageField( height_field="image_height", upload_to='var/drawings', verbose_name=_("field-drawing-image"), width_field="image_width", ) image_thumb_detail = ImageSpecField( source='image', format='JPEG', options={'quality': 95}, processors=[ ResizeToCover(600, 600), Watermark( 'web/static/images/watermark-black.png', 0.09, ) ], ) image_thumb_list = ImageSpecField( source='image', format='JPEG', options={'quality': 95}, processors=[ ResizeToCover(300, 300), Watermark( 'web/static/images/watermark-white.png', 0.1, ), ], ) image_height = PositiveIntegerField(null=True) image_width = PositiveIntegerField(null=True) tags = ManyToManyField( 'DrawingTag', verbose_name=_('field-tags'), related_name='drawings', ) class Meta: verbose_name = _('Drawing') verbose_name_plural = _('Drawings') def __str__(self): return '%s (%s)' % (self.name, self.size) def get_active_price_level(self): now = datetime.now() return self.price_levels.filter( (Q(valid_from__isnull=True) | Q(valid_from__gte=now)) & (Q(valid_until__isnull=True) | Q(valid_until__lte=now)), ).order_by('-created').first() def get_price(self): price_level = self.get_active_price_level() return price_level.price if price_level else None def is_price_visible(self): return self.status in DRAWING_AVAILABLE_STATES def is_status_visible(self): return self.status not in DRAWING_AVAILABLE_STATES def mark_as_reserved(self): self.status = DRAWING_STATUS_RESERVED def mark_as_sold(self): self.status = DRAWING_STATUS_SOLD def get_title(self): return '%s %s' % (self.size.name, self.name ) if self.size.standalone_name else self.name
class Event(models.Model): """Model to represent Event objects""" initiative = models.ForeignKey( Initiative, verbose_name=_("Iniciativa que organiza la actividad"), blank=True, null=True, help_text=_('¿Qué iniciativa organiza el evento?')) title = models.CharField( _('Título del evento'), max_length=200, blank=False, null=True, help_text=_('¿Cuál es el título del evento que quieres organiza?')) featured = models.BooleanField( _('Destacado'), blank=True, default=False, help_text=_('Indica si es un evento destacado')) description = models.TextField(_('Describe el evento'), blank=False, null=True, help_text=_('Describe el evento.')) image = models.ImageField( _("Imagen"), blank=True, validators=[validate_image_size, validate_image_type], upload_to=events_images_path, help_text= _("Sube una imagen representativa del evento haciendo click en la imagen inferior. " "La imagen ha de tener ancho mínimo de 600 píxeles y máximo de 1920, y altura mínima " "de 300 píxeles y máxima de 1280. Formatos permitidos: PNG, JPG, JPEG." )) image_medium = ImageSpecField( source="image", processors=[processors.ResizeToFill(600, 300)], format='JPEG', options={'quality': 90}) video = models.CharField( _('Video'), max_length=200, blank=True, null=True, help_text=_('Inserta la url de un video de Youtube o Vimeo')) website = models.URLField( _('Enlace'), blank=True, null=True, help_text=_( 'Especifica opcionalmente un enlace para conocer mejor el evento.') ) topic = models.CharField(_('Temática del evento'), blank=False, null=False, default='DC', max_length=2, choices=categories.TOPICS, help_text=_('El tema de la actividad')) category = models.CharField( _('Tipo de actividad'), blank=False, null=False, default='AU', max_length=2, choices=categories.ACTIVITIES, help_text=_('El tipo de actividad que quieres organizar')) agent = models.CharField( _('tipo de agente'), blank=False, null=False, default='IM', max_length=2, choices=categories.AGENTS, help_text=_('El tipo de agente involucrado en la actividad')) date = models.DateField( _('Fecha del evento'), help_text=_('Indica qué día se celebra o empieza el evento')) time = models.TimeField(_('Hora del evento'), help_text=_('¿A qué hora se celebra el evento?')) periodicity = models.CharField( _('Periodicidad'), max_length=200, blank=True, null=True, help_text= _('Especifica, en ese caso, la periodicidad del evento. Puedes indicar la fecha de fin en el siguiente campo' )) expiration = models.DateField( _('Fecha de fin'), blank=True, null=True, help_text= _('Indica opcionalmente en eventos de varios dias la fecha en que acaba el evento.' )) city = models.ForeignKey( City, verbose_name=_('Ciudad'), blank=False, null=True, on_delete=models.SET_NULL, help_text= _('Ciudad donde se encuentra la iniciativa. Si no la encuentras en la lista puedes añadir una nueva.' )) address = models.CharField( _('Dirección'), max_length=200, blank=False, null=True, help_text= _('Dirección de la iniciativa. No es necesario que vuelvas a introducir la ciudad de la iniciativa.' )) position = PointField( _("Ubicación"), blank=False, null=True, help_text= _("Añade la ubicación de la actividad. Si lo dejas en blanco se usará la ubicación de la iniciativa asociada." )) facebook_id = models.CharField(max_length=128, blank=True, null=True) google_id = models.CharField(max_length=128, blank=True, null=True) slug = models.SlugField(editable=False, blank=True) creation_date = models.DateField(editable=False, default=timezone.now) class Meta: verbose_name = _('Actividad') verbose_name_plural = _('Actividades') def __str__(self): """String representation of this model objects.""" return self.title or '---' def save(self, *args, **kwargs): """Populate automatically 'slug' field""" self.slug = slugify(self.title) # Notify by mail, only when creating new content if not self.id: send_mail( 'Creado el evento \"' + self.title + "\"", 'Creado el ' + self.creation_date.strftime("%d/%b/%Y") + ' por "' + self.initiative.name + '" (' + self.initiative.email + ')\n---\n' + self.title + ':\n' + self.description + '\n---\n' + 'Ciudad: ' + self.city.name, 'civics.cc <*****@*****.**>', settings.NOTIFICATIONS_EMAILS, fail_silently=False, ) super(Event, self).save(*args, **kwargs) def edit_permissions(self, user): """Returns users allowed to edit an instance of this model.""" if user.is_staff or (self.initiative and self.initiative.user and self.initiative.user == user): return True return False
class Image(models.Model): """Image model.""" # ******************************************************************* # ******************** Language independent data ******************** # ******************************************************************* api_url = models.TextField( null=False, blank=False, unique=True, verbose_name=_("Image API URL"), ) primary = models.BooleanField(default=False, verbose_name=_("Primary image")) image = models.FileField( null=True, blank=True, upload_to='collection_images', verbose_name=_("Image"), ) image_large = ImageSpecField(source='image', processors=[ ResizeToFit(960, 960, upscale=False), ], format='JPEG', options={ 'quality': 85, 'suffix': '_large' }) image_sized = ImageSpecField(source='image_large', processors=[ ResizeToFit(108, 108, upscale=False), ResizeCanvas(128, 128), ], format='JPEG', options={ 'quality': 90, 'suffix': '_sized' }) image_ml = ImageSpecField(source='image_large', processors=[ ResizeToFit(108, 108, upscale=False), ResizeCanvas(128, 128), ], format='PNG', options={ 'quality': 90, 'suffix': '_ml' }) active = models.BooleanField( default=False, verbose_name=_("Active"), ) trimmed = models.BooleanField( default=False, verbose_name=_("Trimmed"), ) created = models.DateField( auto_now_add=True, verbose_name=_("Date imported"), ) updated = models.DateField( auto_now=True, verbose_name=_("Date updated"), ) # ******************************************************************* # ******************** Data translated into English ***************** # ******************************************************************* title = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("Title"), help_text=_("Title of the object")) description = models.TextField(null=True, blank=True, verbose_name=_("Description"), help_text=_("Description of the object")) # ******************************************************************* # ******************** Original data as imported ******************** # ******************************************************************* title_orig = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("Original title"), help_text=_("Title of the object")) description_orig = models.TextField( null=True, blank=True, verbose_name=_("Original description"), help_text=_("Description of the object")) class Meta(object): """Meta options.""" def __str__(self): return self.api_url
class ImageBaseContentMixin(ImageRelatedMixin): """ ImageBaseContentMixin will be injected into real models when content is an image Attributes: image (ForeignKey to Image): See stack_it.images.mixins.ImageRelatedMixin ref_alt (CharField): See stack_it.images.mixins.ImageRelatedMixin ref_image (ImageField): See stack_it.images.mixins.ImageRelatedMixin size (CharField): Gives wanted image size value (ImageSpecField): Store the resized image Tests: test.test_content.abstract.test_image_base_content_mixin """ size = models.CharField(_("Size"), max_length=50, default="800x600", validators=[validate_image_size]) value = ImageSpecField(source="ref_image", id="utils:processors:resized_image") class Meta: abstract = True def __init__(self, *args, **kwargs): super(ImageBaseContentMixin, self).__init__(*args, **kwargs) def save(self, *args, **kwargs): """ Denormalize image information """ self.ref_image = self.image.image self.ref_alt = self.image.alt super(ImageBaseContentMixin, self).save(*args, **kwargs) @property def parsed_size(self): """ Parse model's size field Returns: tuple: (width,heigt) """ return tuple((int(size) for size in self.size.split("x"))) @property def width(self): return self.parsed_size[0] @property def height(self): return self.parsed_size[1] @property def url(self): return self.value.url @classmethod def init(cls, **kwargs): from stack_it.models import Image try: color = kwargs.pop("color") except KeyError: color = (0, 0, 0) content = cls(**kwargs) image = Image.init_image( name="init-{key}-{size}.jpg".format(**kwargs), size=content.parsed_size, color=color, ) content.image = image content.save() return content
class League(models.Model): """ A leauge will contain a group of users and logically separate registration and billing events. """ name = models.CharField( "League Name", max_length=50, help_text= "Example: 'Wreckers', 'Juniors', 'Madison Roller Derby', etc.", ) short_name = models.CharField( "Short Name", max_length=50, help_text="Example: 'MWD', 'Juniors', 'MRD', etc. Something short.", ) slug = models.CharField( "League Slug", max_length=20, help_text="Example: 'mrd', 'wreckers', 'juniors'. DO NOT CHANGE.", blank=True, ) organization = models.ForeignKey( 'league.Organization', on_delete=models.CASCADE, ) logo = models.ImageField(upload_to='logos', blank=True, null=True) logo_thumbnail = ImageSpecField(source='logo', processors=[ResizeToFill(100, 100)], format='JPEG', options={'quality': 80}) logo_thumbnail_header = ImageSpecField( source='logo', processors=[ResizeToFit(50, 50)], format='PNG', ) logo_thumbnail_footer = ImageSpecField( source='logo', processors=[ResizeToFit(300, 300)], format='PNG', ) logo_social = ImageSpecField( source='logo', processors=[ResizeToFit(1200, 630)], format='PNG', ) # Payment Settings default_payment_due_day = models.IntegerField( "Default Payment Due Day", choices=DAY_OF_MONTH_CHOICES, help_text="Default day of month to set billing due date.", default=1) default_invoice_day_diff = models.IntegerField( "Default Invoice Generation Day", choices=INVOICE_DAY_CHOICES, help_text="Default day to generate and email invoices.", default=10, ) stripe_private_key = EncryptedCharField( "Stripe Secret Key", max_length=100, blank=True, help_text= "Private/secret API key for Stripe.com. Used for charging credit cards.", ) stripe_public_key = EncryptedCharField( "Stripe Public Key", max_length=100, blank=True, help_text= "Private API key for Stripe.com. Used for charging credit cards.", ) # Registration Settings default_address_state = models.CharField( max_length=2, blank=True, choices=STATE_CHOICES, help_text="Default state choice on Registration forms.", ) default_insurance_type = models.ForeignKey( 'league.InsuranceType', blank=True, null=True, on_delete=models.SET_NULL, help_text="Default insurance type to show on Registration forms.", related_name="default_insurance_type", ) # Email Settings email_from_name = models.CharField( "Email From Name", max_length=100, help_text= "The name of the person or account sending email. Example 'MRD Training'.", blank=True, ) email_from_address = models.EmailField( "Email From Address", max_length=100, help_text="The email address all emails from this league will be from." ) email_cc_address = models.EmailField( "CC Emails To", max_length=100, help_text= "If you would like all emails sent from this league to be CC'd to an email, enter one here. Leave blank to disable.", blank=True, ) email_signature = models.TextField( "Email Signature", help_text= "Custom signature in HTML for all emails sent from this system.", blank=True, ) style_color_one = models.CharField( "Style Color #1", max_length=20, help_text= "First color for custom theme for this league. Default is '#F9FC69'.", blank=True, ) style_color_two = models.CharField( "Style Color #2", max_length=20, help_text= "Second color for custom theme for this league. Default is '#35E5F4'.", blank=True, ) style_email_font = models.CharField( "Email Font CSS Name", max_length=100, help_text= "The font to use for branding the logo in emails. Default is 'Lucida Sans Unicode', 'Lucida Grande', sans-serif'", blank=True, ) style_header_font_name = models.CharField( "Header Font Google Font Name", max_length=100, help_text= "The name of the font to use when loading the google font to use for the league name in the header. Default is 'Lobster'.", blank=True, ) style_header_font_css = models.CharField( "Header Font Google Font CSS Font-Family", max_length=100, help_text= "The font-face CSS to use for branding the league name in the header. Default is 'Lobster, cursive'.", blank=True, ) def __str__(self): return self.name class Meta: ordering = ['name'] unique_together = ('slug', 'organization') permissions = ( ('league_admin', 'Can manage league settings and email templates.'), ('billing_manager', 'Can send bills and manage dues.'), ('roster_manager', 'Can manage user profiles and assign people to teams.'), ('registration_manager', 'Can manage registration system and send invites.'), ('survey_manager', 'Can manage voting and surveys.'), ('event_manager', 'Can manage special event pages.'), ('league_member', 'Active member of league.'), ) def get_absolute_url(self): return reverse('league:league_update', kwargs={ 'slug': self.slug, 'organization_slug': self.organization.slug }) def get_stripe_private_key(self): if self.stripe_private_key: return self.stripe_private_key raise ImproperlyConfigured("Stripe private key not set for {}".format( self.name)) def get_stripe_public_key(self): if self.stripe_public_key: return self.stripe_public_key raise ImproperlyConfigured("Stripe public key not set for {}".format( self.name))
class Product(models.Model): GENDER_CHOICES = ( ('M', 'Male',), ('F', 'Female',), ) CONDITION_CHOICES = ( ('used', 'Used'), ('new', 'New') ) CATEGORY_CHOICES = ( ('traditional','TRADITIONAL'), ('formal', 'Formal'), ('casual', 'Casual'), ('ethnic', 'Erhnic'), ('sports', 'Sports'), ('western', 'Western'), ('t-shirts', 'T-shirts'), ('denim', 'Denim'), ('kids', 'Kids'), ('winter-wears', 'Winter-wears'), ('jumpsuits', 'Jumpsuits'), ) OCCASION_CHOICES = ( ('weddings', 'Weddings'), ('sangeet', 'Sangeet'), ('party', 'Party'), ('everyday', 'Everyday'), ('interview', 'Interview'), ('gym', 'Gym'), ('outings', 'Outings'), ) user = models.ForeignKey(Profile, on_delete=models.CASCADE, blank=True, null=True) title = models.CharField(max_length=100, db_index=True) description = models.TextField(blank=True) price = models.DecimalField(max_digits=10, decimal_places=2, default='99.99') gender = models.CharField(max_length=1, choices=GENDER_CHOICES) condition = models.CharField(max_length=4, choices=CONDITION_CHOICES) category = models.CharField(max_length=17, choices=CATEGORY_CHOICES) occasion = models.CharField(max_length=9, choices=OCCASION_CHOICES) featured = models.BooleanField(default=False) timestamp = models.DateTimeField(auto_now=True) sold = models.BooleanField(default=False) image1 = models.ImageField(upload_to=upload_image_path) image2 = models.ImageField(upload_to=upload_image_path, null=True, blank=True) image3 = models.ImageField(upload_to=upload_image_path, null=True, blank=True) image4 = models.ImageField(upload_to=upload_image_path, null=True, blank=True) # created_at = models.DateTimeField(auto_now_add=True) # updated_at = models.DateTimeField(auto_now=True) smart1 = ImageSpecField(source='image1', processors=[ResizeToFill(250, 250)], format='JPEG', options={'quality': 99}) smart2 = ImageSpecField(source='image2', processors=[SmartResize(250, 250)], format = 'JPEG', options={'quality': 99}) smart3 = ImageSpecField(source='image3', processors=[SmartResize(250, 250)], format = 'JPEG', options={'quality': 99}) smart4 = ImageSpecField(source='image4', processors=[SmartResize(250, 250)], format = 'JPEG', options={'quality': 99}) def __str__(self): return self.title class Meta: db_table = 'Product' def get_absolute_url(self): return reverse('detail', kwargs={'pk': self.pk})
def image_spec_thumbnail(size): processors = [Transpose(), Thumbnail(size, size, crop=False)] return ImageSpecField( source="original", processors=processors, format="JPEG", options={"quality": 60} )
class User(AbstractBaseUser, PermissionsMixin): # uuid uuid = models.UUIDField(default=uuid_lib.uuid4, primary_key=True, editable=False) # username, full name username_validator = UnicodeUsernameValidator() username = models.CharField( _('ユーザ名'), max_length=150, unique=True, help_text= _('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.' ), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }) full_name = models.CharField(_('氏名'), max_length=150, null=True) # email email = models.EmailField( _('メールアドレス'), help_text='メールアドレスを入力してください', unique=True, ) # image original original = models.ImageField(default=os.path.join("users", "dice.png"), upload_to="users/") # bio, icon bio = models.TextField(max_length=500, blank=True) icon = ImageSpecField(source='original', processors=[ResizeToFill(250, 250)], format="JPEG", options={'quality': 60}) bigicon = ImageSpecField(source='original', processors=[ResizeToFill(500, 500)], format="JPEG", options={'quality': 90}) # is staff, is active (boolean), and date joined is_staff = models.BooleanField( _('staff status'), default=False, help_text=_( 'Designates whether the user can log into this admin site.'), ) is_active = models.BooleanField( _('active'), default=True, help_text=_( 'Designates whether this user should be treated as active. ' 'Unselect this instead of deleting accounts.'), ) date_joined = models.DateTimeField(_('date joined'), default=timezone.now) # User Manager objects = UserManager() # env EMAIL_FIELD = 'email' USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] class Meta: verbose_name = _('user') verbose_name_plural = _('users') def clean(self): super().clean() self.email = self.__class__.objects.normalize_email(self.email) def email_user(self, subject, message, from_email=None, **kwargs): """Send an email to this user.""" send_mail(subject, message, from_email, [self.email], **kwargs)
class Eureka(TimeStampedModel, CommentsModel, VoteModel, TagsModel, LinkedModel, ModerationModel, DiaryModel, DeleteMaskModel, FavoriteModel, SympathizerModel): title = models.CharField(max_length=80, verbose_name='Tytuł') description = models.TextField(max_length=300, verbose_name='Opis') link = models.CharField( max_length=255, validators=[URLValidator()], verbose_name='Link do instrukcji, filmu lub źródła np.: http://www.', blank=True) content_type = models.CharField(max_length=9, choices=(('0', 'Autorska'), ('1', 'Cudza')), default='0', verbose_name='Typ treści') preview_image = models.ImageField(upload_to='preview_images', verbose_name='Miniaturka') preview_image_thumbnail = ImageSpecField( source='preview_image', processors=[SmartResize(180, 100)], format='JPEG', options={'quality': 100}) eurekaInstruction = models.ForeignKey('EurekaInstruction') is_waiting = models.BooleanField(default=True) is_published = models.BooleanField(default=False) published = models.DateTimeField(verbose_name='Opublikowano', blank=True, null=True) slug = models.SlugField(max_length=20) created_by = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='Stworzone przez') difficult = models.CharField(choices=(('easy', 'Łatwy'), ('medium', 'Średni'), ('hard', 'Trudny')), verbose_name='Poziom trudności', blank=True, max_length=20) price = models.PositiveIntegerField(verbose_name='Cena orientacyjna (PLN)', blank=True, default=0, validators=[MaxValueValidator(999999)]) def get_absolute_url(self): return "/eureka/{}/".format(self.slug) def publish(self): self.is_published = True self.published = datetime.now() self.save() class Meta: permissions = ( ('is_owner', 'Is owner eureka'), ('can_vote', 'Can votes eureka'), ('can_view', 'Can view eureka'), )
class Pictures(models.Model): text = models.TextField() image = models.ImageField(upload_to="blogimg") image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFill(120, 100)], format='JPEG', options={'quality':60})
class Post(models.Model): """ Managing posts of users """ user = models.ForeignKey(User, verbose_name='User', related_name='posts', on_delete=models.CASCADE) image = models.ImageField(verbose_name='Image', validators=[validate_image], upload_to=make_upload_path, blank=True, null=True) title = models.CharField(verbose_name='Title', max_length=50, default='', help_text='Title post.') message = models.TextField(verbose_name='Message', max_length=1000, default='', help_text='Your new message.') like = models.PositiveIntegerField(verbose_name='Like', blank=True, default=0) unlike = models.PositiveIntegerField(verbose_name='Unlike', blank=True, default=0) rating = models.IntegerField(verbose_name='Rating', blank=True, default=0) slug = models.SlugField(max_length=100, blank=True, null=True) is_disable = models.BooleanField('Is disable?', blank=True, default=False) created_at = models.DateTimeField(verbose_name='Publication date', auto_now_add=True) updated_at = models.DateTimeField(verbose_name='Updated', auto_now=True) thumbnail = ImageSpecField( [ResizeToFit(height=60, width=60, upscale=True)], source='image') middle = ImageSpecField([ResizeToFit(height=180, width=180, upscale=True)], source='image') def __str__(self): return self.title @property def upload_dir(self): return 'posts/images' class Meta: ordering = ('-pk', ) verbose_name = 'Post' verbose_name_plural = 'Posts' def save(self, *args, **kwargs): like = self.like unlike = self.unlike self.rating = like - unlike super(Post, self).save(*args, **kwargs) def admin_thumbnail(self): if self.image: return mark_safe('<img src="{}" />'.format(self.thumbnail.url)) else: return '' admin_thumbnail.short_description = 'Image' admin_thumbnail.allow_tags = True def get_absolute_url(self): return reverse('web_posts:view_post', kwargs={'slug': self.slug})
class Article(AdminUrlModel): headline = models.CharField(max_length=150, verbose_name=_("Headline")) slug = models.SlugField(max_length=150, verbose_name=_("Slug")) slug_locked = BooleanField(default=False, verbose_name=_("Locked Slug")) image = models.ImageField( blank=True, null=True, upload_to="news", verbose_name=_("Image") ) abstract = models.TextField(verbose_name=_("Abstract")) published = DateTimeField( verbose_name=_("Published"), help_text=_("Set a date & time in the future to schedule " "an announcement."), ) byline = models.CharField(max_length=75, blank=True, verbose_name=_("Byline")) keywords = models.CharField(max_length=255, blank=True, verbose_name=_("Keywords")) categories = ManyToManyField("Category", blank=True, verbose_name=_("Categories")) is_active = BooleanField(default=True, verbose_name=_("Enabled")) copy = HTMLField(_("Copy"), blank=True) # image and imagekit spec files thumbnail = ImageSpecField( source="image", processors=processor_factory(THUMBNAIL_IMAGE_PROCESSORS), **THUMBNAIL_IMAGE_KWARGS ) detail_image = ImageSpecField( source="image", processors=processor_factory(DETAIL_IMAGE_PROCESSORS), **DETAIL_IMAGE_KWARGS ) last_modified = DateTimeField(auto_now=True) objects = ArticleQuerySet.as_manager() class Meta: ordering = ("-published",) def clean(self): if not self.slug_locked or not self.slug: self.slug = slugify(self.headline) def get_absolute_url(self): return reverse( "news:article", kwargs={ "year": self.published.year, "month": self.published.strftime("%b").lower(), "day": self.published.day, "slug": self.slug, }, ) def __str__(self): return self.headline
class Project(models.Model): """プロジェクト users: 参加メンバー name: プロジェクト名 details: プロジェクト詳細 start_date: プロジェクト開始日付 project_status: ステータス homepage: プロジェクトHPリンク email: Email organization(_l): 参加団体 image_xxx: サムネイル画像 """ users = models.ManyToManyField(UserProfile, related_name="project") name = models.CharField(max_length=256) details = models.TextField(blank=True) start_date = models.DateField() categories = models.ManyToManyField("CategoryM", blank=True) project_status = models.ForeignKey(ProjectStatusM, on_delete=models.PROTECT) homepage = models.URLField(blank=True) email = models.EmailField(blank=True) organization = models.ManyToManyField(Organization, related_name="organization", blank=True) organization_l = models.ManyToManyField(OrganizationLight, related_name="organization_l", blank=True) def get_image_path(self, filename): """カスタマイズした画像パスを取得する. :param self: インスタンス (models.Model) :param filename: 元ファイル名 :return: カスタマイズしたファイル名を含む画像パス """ prefix = 'project/' name = str(uuid.uuid4()).replace('-', '') extension = os.path.splitext(filename)[-1] return prefix + name + extension def delete_previous_file(function): """不要となる古いファイルを削除する為のデコレータ実装.(未検証) :param function: メイン関数 :return: wrapper """ def wrapper(*args, **kwargs): """Wrapper 関数. :param args: 任意の引数 :param kwargs: 任意のキーワード引数 :return: メイン関数実行結果 """ self = args[0] # 保存前のファイル名を取得 result = Project.objects.filter(pk=self.pk) previous = result[0] if len(result) else None super(Project, self).save() # 関数実行 result = function(*args, **kwargs) # 保存前のファイルがあったら削除 if previous: file_path = settings.MEDIA_ROOT + '/' + previous.image_origin.name if os.path.isfile(file_path): os.remove(file_path) return result return wrapper @delete_previous_file def save(self, force_insert=False, force_update=False, using=None, update_fields=None): super(Project, self).save() @delete_previous_file def delete(self, using=None, keep_parents=False): super(Project, self).delete() image_origin = models.ImageField(_('image_origin'), upload_to=get_image_path, blank=True) image_thumbnail = ImageSpecField(source='image_origin', processors=[ResizeToFill(250,250)], format="JPEG", options={'quality': 60} ) image_middle = ImageSpecField(source='image_origin', processors=[ResizeToFill(400, 400)], format="JPEG", options={'quality': 75} ) def __str__(self): return self.name
class Picture(models.Model): """ Single picture item of given gallery. When new picture is uploaded it create automaticaly a thumbnail image for easy displaying in html page. """ MAX_WIDTH = 900 MAX_HEIGHT = 600 MAX_THUMB_WIDTH = 130 MAX_THUMB_HEIGHT = 100 IMAGES_ROOT = 'gallery' gallery = models.ForeignKey(Gallery, verbose_name=_('gallery'), related_name='pictures', on_delete=models.CASCADE) title = models.CharField(_('title'), max_length=255, blank=True, default='', help_text=_("Title of the picture")) image = ProcessedImageField( verbose_name=_('image'), max_length=255, upload_to=upload_picture_to, processors=[ResizeToFit(MAX_WIDTH, MAX_HEIGHT)], format='JPEG', options={'quality': 95}) thumb = ImageSpecField( source='image', processors=[ResizeToFit(MAX_THUMB_WIDTH, MAX_THUMB_HEIGHT)], format='JPEG', options={'quality': 60}) is_album_logo = models.BooleanField( _('is album logo'), default=False, help_text=_("If this is checked this picture will be the album logo")) uploaded = models.DateTimeField(_('uploaded at'), auto_now_add=True, db_index=True) modified = models.DateTimeField(_('modified at'), auto_now=True, db_index=True) objects = PictureManager() class Meta: ordering = '-uploaded', '-pk', verbose_name = _('picture') verbose_name_plural = _('pictures') def __str__(self): return force_str(self.title or self.image.name) def save(self, *args, **kwargs): """ Here we do the magic of creating a thumbnail automaticaly, when new picture are set. """ if not (self.pk or self.title): self.title = self.image.name.replace('_', ' ') super().save(*args, **kwargs) def natural_key(self): return str(self.image), natural_key.dependencies = 'gallery.gallery', def preview(self): """ Generate html for showing thumbnail image with link to the real one. """ if not self.thumb: return '' return format_html( '<a href="{image_url}" title="{title}"><img src="{thumb_url}" width="{width}" height="{height}" alt="{title}" /></a>', image_url=self.image.url, title=self.title, thumb_url=self.thumb.url, width=self.thumb.width, height=self.thumb.height) preview.short_description = _('preview') def as_dict(self): """ Return dict representing picture data. It is used for the API """ return { 'pk': self.pk, 'gallery': self.gallery_id, 'title': self.title, 'image': { 'url': self.image.url, 'thumbnail': self.thumb.url, }, }