gdritter repos frony-ritter-designs / master model.py
master

Tree @master (Download .tar.gz)

model.py @master

58a74d4
687ccb6
20f235a
 
 
687ccb6
20f235a
 
58a74d4
 
39d45fa
58a74d4
 
 
 
 
 
 
 
 
 
20f235a
 
 
 
 
 
 
 
 
 
 
58a74d4
 
39d45fa
 
 
58a74d4
 
20f235a
 
 
 
 
 
 
 
 
 
58a74d4
39d45fa
58a74d4
 
 
 
 
a7ad730
 
 
 
 
58a74d4
 
 
660f523
58a74d4
a7ad730
 
 
 
 
 
 
 
 
660f523
 
 
 
 
 
 
 
 
 
 
 
a56e485
660f523
 
 
a7ad730
 
 
 
 
 
 
 
 
 
 
 
58a74d4
0dd132a
58a74d4
39d45fa
58a74d4
 
 
 
 
 
 
 
660f523
58a74d4
39d45fa
58a74d4
20f235a
 
 
7cfd12e
20f235a
58a74d4
 
 
0dd132a
 
 
 
 
 
687ccb6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7cfd12e
 
 
 
687ccb6
 
854db81
687ccb6
 
 
 
20f235a
 
 
 
 
 
 
 
 
 
 
 
 
 
58a74d4
 
39d45fa
 
 
 
58a74d4
 
 
20f235a
 
 
 
 
 
 
58a74d4
 
 
 
20f235a
 
58a74d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7cfd12e
 
 
 
 
 
 
58a74d4
 
 
 
 
 
 
from dataclasses import dataclass
import os
import markdown
import peewee
import typing
import PIL.Image

db = peewee.SqliteDatabase("new.db")
PER_PAGE = 16


def slugify(string):
    def process(char):
        if char in "- \n\t\f":
            return "-"
        elif char.isalpha():
            return char.lower()
        else:
            return ""

    return "".join(process(c) for c in string)[:40]


class Model(peewee.Model):
    class Meta:
        database = db


class Category(Model):
    name = peewee.TextField()
    nicename = peewee.TextField()

    @classmethod
    def all(klass):
        elements = (
            {"url": f"/category/{c.name}", "name": c.nicename} for c in klass.select()
        )
        return {"elements": elements}


class Design(Model):
    visible_id = peewee.IntegerField()
    title = peewee.TextField()
    description = peewee.TextField()
    category = peewee.ForeignKeyField(Category, backref="designs")

    def rendered(self):
        return markdown.markdown(self.description)

    def id_str(self):
        return f"{self.visible_id:05}"

    def slug(self):
        return slugify(self.title)

    def thumbnail(self):
        photo = Photo.select().where(Photo.design == self).limit(1).execute()
        if photo:
            return photo[0].thumb()
        else:
            return None

    def category_list(self):
        categories = Category.select()
        return [{"name": c.name, "selected": "selected='selected'" if c == self.category else ""} for c in categories]

    def to_json(self):
        return {
            "id": self.visible_id,
            "title": self.title,
            "tags": [t.tag_name for t in self.tags],
            "categories": self.category_list(),
            "description": self.description,
            "photos": [{"id": p.id, "image": p.filename} for p in self.photos],
        }
    def update_with(self, stuff):
        # update the category
        if 'title' in stuff:
            self.title = stuff['title']
        if 'category' in stuff:
            self.category = Category.get(name=stuff['category'])
        if 'contents' in stuff:
            self.description = stuff['contents']
        if 'tags' in stuff:
            old_tags = set((t.tag_name for t in self.tags))
            new_tags = set(stuff['tags'])
            for to_add in new_tags - old_tags:
                Tag.create(tag_name=to_add, design=self)
            for to_remove in old_tags - new_tags:
                Tag.get(tag_name=to_remove, design=self).delete_instance()
        self.save()

    @classmethod
    def make_new(klass):
        new_visible_id = klass.select(peewee.fn.max(klass.visible_id)).scalar() + 1
        klass.create(
            visible_id=new_visible_id,
            title="My Great New Design",
            description="A blank canvas awaits...",
            category=Category.get(),
        )
        return new_visible_id

    @classmethod
    def get_all(klass, page=1):
        designs = klass.select().paginate(page, PER_PAGE)
        return Paginated.paginate(page, klass.select().count(), designs,)

    @classmethod
    def get_where(klass, *, tag=None, category=None, page=0):
        query = klass.select(klass)
        if tag is not None:
            query = query.join(Tag).where(Tag.tag_name == tag)
        if category is not None:
            query = query.switch(klass).join(Category).where(Category.name == category)
        query = query.group_by(klass).order_by(klass.id.desc())
        designs = query.paginate(page, PER_PAGE)
        return Paginated.paginate(page, query.count(), designs,)


class Photo(Model):
    filename = peewee.TextField()
    design = peewee.ForeignKeyField(Design, backref="photos", null=True)

    def thumb(self):
        return self.filename[:-4] + "_thumb" + self.filename[-4:]

    @classmethod
    def get_all(klass, page=1):
        size = klass.select().count()
        photos = klass.select().paginate(page, PER_PAGE).order_by(klass.filename.desc())
        return photos, 1, (size // PER_PAGE) + 1

    @classmethod
    def upload(klass, upload, design_id):
        last_image = klass.select().order_by(klass.filename.desc()).limit(1)
        if last_image:
            n = int(last_image[0].filename[:5]) + 1
        else:
            n = 0
        ext = upload.filename[upload.filename.rindex(".")+1:]

        full_name = f"{n:05}.{ext}"
        thumb_name = f"{n:05}_thumb.{ext}"
        img = PIL.Image.open(upload.stream)
        img.thumbnail((400, 400), PIL.Image.ANTIALIAS)
        img.save(os.path.join(os.getcwd(), "static", "photos", full_name))

        img.thumbnail((100, 100), PIL.Image.ANTIALIAS)
        img.save(os.path.join(os.getcwd(), "static", "photos", thumb_name))

        if design_id != -1:
            design = Design.get(visible_id=design_id)
        else:
            design = None
        klass.create(
            filename=full_name,
            design=design,
        )

        return full_name


class Page(Model):
    name = peewee.TextField()
    text = peewee.TextField()
    title = peewee.TextField()

    def rendered(self):
        return markdown.markdown(self.text)


class Tag(Model):
    tag_name = peewee.TextField()
    design = peewee.ForeignKeyField(Design, backref="tags")

    @classmethod
    def all(klass):
        elements = (
            {"url": f"/tag/{t.tag_name}", "name": t.tag_name}
            for t in klass.select(klass.tag_name).distinct().order_by(klass.tag_name)
        )
        return {"elements": elements}


class PageRef(typing.NamedTuple):
    page: int

    def __iter__(self):
        return [self]


@dataclass
class Paginated:
    next_page: typing.Optional[dict]
    prev_page: typing.Optional[dict]
    last_page: int
    contents: typing.List[Design]

    @classmethod
    def paginate(
        cls, offset: int, total: int, contents: typing.List[Design],
    ) -> "Paginated":
        last_page = (total // PER_PAGE) + 1
        next_page = PageRef(page=offset + 1) if offset < last_page else None
        prev_page = PageRef(page=offset - 1) if offset > 1 else None
        return cls(
            next_page=next_page,
            prev_page=prev_page,
            last_page=last_page,
            contents=contents,
        )

MODELS = [
    Category,
    Design,
    Photo,
    Page,
    Tag,
]

# @dataclass
# class Paginated:
#     next_page: typing.Optional[dict]
#     prev_page: typing.Optional[dict]
#     last_page: int
#     contents: typing.List[Design]