You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a model name clashes with a built-in name (e.g. Set), generation leads to weird behavior:
(dolce-py3.11) nchiang@rowlet ~/repos/dolce (nicholas/posts) $ prisma generate
Traceback (most recent call last):
File "/Users/nchiang/repos/dolce/.venv/bin/prisma", line 5, in <module>
from prisma.cli import main
File "/Users/nchiang/repos/dolce/.venv/lib/python3.11/site-packages/prisma/__init__.py", line 24, in <module>
from .client import *
File "/Users/nchiang/repos/dolce/.venv/lib/python3.11/site-packages/prisma/client.py", line 50, in <module>
from . import types, models, errors, actions
File "/Users/nchiang/repos/dolce/.venv/lib/python3.11/site-packages/prisma/types.py", line 111157, in <module>
from . import types, enums, models, fields
File "/Users/nchiang/repos/dolce/.venv/lib/python3.11/site-packages/prisma/models.py", line 3951, in <module>
_User_relational_fields: Set[str] = {
~~~^^^^^
TypeError: type 'Set' is not subscriptable
How to reproduce
Steps to reproduce the behavior:
Create a new Prisma schema that has a model named Set
Run generation once
Run it again
See error
Expected behavior
I should be able to name my Prisma models whatever I want to, even if they clash with built-in class names.
Prisma information
datasourcedb {provider="postgresql"url=env("DATABASE_URL")directUrl=env("DIRECT_URL")}generatorjs {provider="prisma-client-js"previewFeatures=["fullTextSearch"]}generatorpy {provider="prisma-client-py"interface="sync"recursive_type_depth=5enable_experimental_decimal=True}// A user is a person who has created an account with us.modelUser {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The user's name, as designated by the user.// @todo there may be multiple users with the same name...nameString@unique// The user's description (e.g. a designer biography).descriptionString?// The user's publicly visible username, as designated by the user.usernameString?@unique// The user's email address, as designated by the user.emailString?@unique// The user's password, stored as an encrypted hash.passwordPassword?// The user's avatar image URL.avatarString?@unique// URL to the user's website or portfolio (e.g. journalist bio pages).urlString?@unique// The articles about this user.articlesArticle[]// The articles written by the user.articlesWrittenArticle[]@relation("ArticlesWritten")// The reviews written by the user.reviewsReview[]// The posts uploaded by the user (this does not mean that the post was// originally authored by this user, but that it was added to our database by// this user).postsPost[]// The user's sets (i.e. arbitrary groupings of saved looks).setsSet[]// The looks this user has authored.looksLook[]// Whether the user is a curator (i.e. someone who can edit shows, etc).curatorBoolean@default(false)// DESIGNER FIELDS - only applicable to fashion designers.// Where the designer purports to be from.countryCountry?@relation(fields: [countryId], references: [id], onDelete: Cascade, onUpdate: Cascade)countryIdInt?// The collections that the designer created or otherwise curated.collectionsCollection[]// The products that the designer designed.productsProduct[]// MODEL FIELDS - only applicable to fashion models.// The looks that this model wore during runway shows.looksModeledLook[]@relation("LooksModeled")}// A user's password, stored in Postgres as an encrypted hash.modelPassword {createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The securely encrypted hash of the user's original password text.hashString// The user whose password this is.userUser@relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)userIdInt@unique}// A company is a legal corporation. Companies can own many brands.// e.g. The LVMH company owns Louis Vuitton, Dior, Givenchy, etc.modelCompany {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The corporations legal name.nameString@unique// The company's avatar URL (i.e. logo).avatarString?@unique// URL to the company's website.urlString?@unique// A short description of the company, typically sourced from Wikipedia.descriptionString?// The brands owned and operated by the corporation.brandsBrand[]// The retailers owned and operated by the corporation.retailersRetailer[]// The country where the corporation is legally headquartered.countryCountry@relation(fields: [countryId], references: [id], onDelete: Cascade, onUpdate: Cascade)countryIdInt// @todo perhaps store links to where this information was sourced from?}// A retailer is a recognizable commerce entity that sells products. Note that// this is different than a company to allow companies to own many retailers.// e.g. Neiman Marcus, Nordstrom, GOAT, StockX, Ebay, etc.modelRetailer {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The retailer's most recognizable name, styled in their preferred format.nameString@unique// The retailer's avatar URL (i.e. logo).avatarString?@unique// URL to the retailer's website.urlString?@unique// The company that owns and operates the retailer.companyCompany?@relation(fields: [companyId], references: [id], onDelete: Cascade, onUpdate: Cascade)companyIdInt?// A short description of the retailer, typically sourced from Wikipedia.descriptionString?// The brands sold by the retailer.// @todo perhaps this shouldn't be an explicit relation but rather implied by// the products (and their associated brands) that the retailer sells.brandsBrand[]// The prices (associated with products) sold by the retailer.pricesPrice[]// The countries in which the retailer operates.countriesCountry[]// The links (to collections or brands) on this retailer's website.linksLink[]}// Tiers attempt to encapsulate a brand's reputation, business model, and prices:// // 0 - $50k-∞ bespoke. does not sell to the general public. // 1 - $5-50k superpremium. e.g. Patek Philippe, Bottega, Hermes // 2 - $1500-5k premium core. e.g. Rolex, Berluti, Omega, Cartier// 3 - $300-1500 accessible core. e.g. GUCCI, Prada, Tod's, Montblanc// 4 - $100-300 affordable luxury. e.g. Coach, Geox// // 5 - $80-$700 diffusion. secondary lines by luxury names. e.g. Marc by Marc Jacobs// 6 - $40-500 high-end street. e.g. All Saints, Coast// 7 - $20-120 mid-level high street. e.g. Topshop, M&S// 8 - $5-30 value market. relies on huge sales. e.g. Primark, Shein, Walmart// // https://createafashionbrand.com/the-many-market-levels-of-fashion-brands/// https://www.businessinsider.com/pyramid-of-luxury-brands-2015-3//// @todo perhaps this should be a model of its own?enumTier {BESPOKESUPERPREMIUMPREMIUM_COREACCESSIBLE_COREAFFORDABLE_LUXURYDIFFUSIONHIGH_STREETMID_STREETVALUE_MARKET}// A brand is a recognizable name. Brands with similar names are given tiers.// e.g. GUESS is given tier 1 while GBG and GUESS FACTORY are given tier 2.//// Typically, a brand will be the name that appears on that tags of products.// Occasionally, a brand will not have its own products (e.g. "Fashion East" is// considered a brand even though they do not create their own products; they// simply showcase other designer's brand's clothing at their runway shows).modelBrand {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The brand's most recognizable name, styled in the brand's preferred format.nameString@unique// The URL friendly slug identifier for the brand. This is different than the// integer ID column as I want to have a user-friendly URL for each brand.// Ex: /shows/resort-2024/hermes is better than /shows/356 for SEO.// @see {@link https://linear.app/nicholaschiang/issue/NC-673}slugString@unique// The brand's avatar URL (i.e. logo).avatarString?@unique// URL to the brand's website.urlString?@unique// A short description of the brand, typically sourced from Wikipedia.descriptionString?// The brand's tier. This will be NULL if it has not been assigned yet.// @todo perhaps rename this to "BrandTier" to avoid confusion with "Level"? tierTier?// The company that owns and operates the brand (if known).companyCompany?@relation(fields: [companyId], references: [id], onDelete: Cascade, onUpdate: Cascade)companyIdInt?// The products designed or otherwise produced by the brand.productsProduct[]// The runway shows presented by the brand.showsShow[]// The sizes used by the brand.sizesSize[]// The prices (associated with products) sold by the brand (i.e. MSRPs).pricesPrice[]// Links to the brand's page on retailer sites.linksLink[]// The retailers that sell the brand.retailersRetailer[]// The collections designed by the brand.collectionsCollection[]// The country the brand purports to be from (if known).countryCountry?@relation(fields: [countryId], references: [id], onDelete: Cascade, onUpdate: Cascade)countryIdInt?}// A country is a sovereign state. Countries can have many brands and sizes.modelCountry {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The country's full name, as designated by the United Nations.nameString@unique// The designers that purport to be from the country.designersUser[]// The companies that are legally headquartered in the country.companiesCompany[]// The brands that purportedly originate from the country.brandsBrand[]// The retailers that operate in the country.retailersRetailer[]// The country's nationwide standardized sizes.sizesSize[]}// A style group represents a collection of mutually exclusive styles.// Allegorical to Linear's label groups (you can only filter on one at a time).// e.g. the "Neckline" style group contains "Crewneck", "V-Neck", etc (a product// can not have a crewneck and a v-neck at the same time).modelStyleGroup {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The style group's name.nameString@unique// The styles that belong to the style group.stylesStyle[]}// A product style category is a high-level grouping of products. Styles are a// tad bit reminiscent of the typical issue tracking tool's "labels" feature.// e.g. blazer, bomber, cardigan, quilted, raincoat, jeans, tuxedos, etc.modelStyle {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The style category's name, styled in the preferred format.nameString@unique// The products that belong to the style category.productsProduct[]// The sizes used by the style category.sizesSize[]// The items that have this style (e.g. "turtleneck").itemsItem[]// The collections that exclusively contain products from this style.collectionsCollection[]// The style group that the style belongs to, if any.styleGroupStyleGroup?@relation(fields: [styleGroupId], references: [id], onDelete: Cascade, onUpdate: Cascade)styleGroupIdInt?// The style subcategories that can be nested underneath this style.// e.g. tops > t-shirts > crew neck, tops > t-shirts > v-neck, etc.parentIdInt?parentStyle?@relation("ParentChildStyle", fields: [parentId], references: [id])childrenStyle[]@relation("ParentChildStyle")}// A size is a measurement of a product's dimensions. Sizes can either be owned// by a brand (for proprietary brand specific sizing systems) or a country (for// nationwide standardized sizes). Users can then add multiple sizes to their // profile. Our system will automatically suggest sizes to add based on the // user's previous purchases and existing profile sizes.modelSize {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The size's name, as designated by the brand or country.nameString// A unique slug derived from the name, sex, style, and brand. This exists// primarily to make imports easier (i.e. we can use the slug to match sizes// in a connectOrCreate statement instead of having to fetch the styleId).slugString@unique// The product style the size is used for (e.g. tops, outerwear, puffers).styleStyle@relation(fields: [styleId], references: [id], onDelete: Cascade, onUpdate: Cascade)styleIdInt// The original intended sex the size is specifying for.sexSex// The size's chest measurement (cm) as designated by the brand.chestDecimal?// The size's shoulder measurement (cm) as designated by the brand.shoulderDecimal?// The size's waist measurement (cm) as designated by the brand.waistDecimal?// The size's sleeve measurement (cm) as designated by the brand.sleeveDecimal?// The brand whose size this is.brandBrand?@relation(fields: [brandId], references: [id], onDelete: Cascade, onUpdate: Cascade)brandIdInt?// The country whose size this is.countryCountry?@relation(fields: [countryId], references: [id], onDelete: Cascade, onUpdate: Cascade)countryIdInt?// Equivalent sizes. A size can have zero or more equivalent sizes.equivalentsSize[]@relation("SizeEquivalents")equivalentOfSize[]@relation("SizeEquivalents")// The product variants that are available in this size.variantsVariant[]// @todo ensure that a size always has either a country or a brand.// @see https://github.com/prisma/prisma/issues/17319// Each brand or country must have unique size names per category and sex. @@unique([name, sex, styleId, brandId, countryId])}// A color is a label assigned to products by their designers.// @todo perhaps standardize this by associating each color with an RGBA range?modelColor {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The color's name, as designated by the brand (e.g. "Beige", "Black", etc).nameString@unique// The product variants that are available in this color.variantsVariant[]// The items that have this color.itemsItem[]// @todo perhaps colors should be associated with brands? e.g. "Gucci Beige"?}// A sustainability is a label indicating some level of sustainability.enumSustainability {RECYCLED// Certified recycled materials. ORGANIC// Certified organic materials.RESPONSIBLE_DOWN// Responsible Down Standard cerified.RESPONSIBLE_FORESTRY// Wood-based fabrics from sustainably managed forests.RESPONSIBLE_WOOL// Responsible Wool Standard certified.RESPONSIBLE_CASHMERE// Responsible Cashmere Standard certified.}// A material is a fabric or other ingrediant used to formulate a product.modelMaterial {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The material's name, as designated by industry standard (e.g. "Cotton") or// the brand for proprietary fabrics (e.g. "Bombtwill", "City Wool").nameString@unique// The material's description, as designated by the brand (e.g. for// proprietary fabrics like LENZING ECOVERO Viscose) or industry standard.descriptionString?// The material's sustainability status, if any.sustainabilitySustainability?// The product variants that are available in this material.variantsVariant[]// The style subcategories that can be nested underneath this style.// e.g. Viscose > LENZING ECOVERO Viscose, Wool > Merino > City Wool, etc.parentIdInt?parentMaterial?@relation("ParentChildMaterial", fields: [parentId], references: [id])childrenMaterial[]@relation("ParentChildMaterial")// @todo perhaps materials should be associated with brands or countries// similar to how sizes are associated with either a brand or country?// @todo perhaps create a manufacturer model to associate with materials?}// A tag is an arbitrary label applied by a brand or retailer to their items.// This was added primarily to preserve information from scraping Shopify. These// often correlate with specific collections, seasons, or styles. There's no// easy way to classify them at save time, so I just include them and will run// SQL queries manually to re-classify them.modelTag {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The tag's name, as designated by the brand or retailer.nameString@unique// The product variants that are available in this tag.variantsVariant[]}// A variant specifies the properties of an item you can purchase. Each variant// is associated with a unique SKU number. Variants are identified primarily by// size and color. Each variant has prices from different vendors.modelVariant {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The variant's SKU, as designated by the brand.skuString@unique// The product the variant is of.productProduct@relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: Cascade)productIdInt// The colors the variant consists of. Typically a single color but can be// multiple if the variant contains a gradient or a mix of multiple colors.colorsColor[]// The materials (a.k.a. fabrics) that the variant is made of.materialsMaterial[]// The size of the variant.sizeSize@relation(fields: [sizeId], references: [id], onDelete: Cascade, onUpdate: Cascade)sizeIdInt// Images and videos of the product variant being modeled.videosVideo[]imagesImage[]// Arbitrary tags applied by the brand or retailer.tagsTag[]// The prices that are associated with the variant. Typically a single price// but can be multiple if the item is sold by multiple retailers or if there// are different prices per size. Can be empty if the variant is sold out.pricesPrice[]// The user-curated sets that the product variant is a part of.setsSet[]// The posts that include this product variant.postsPost[]// @todo each product can only have a single variant per color and size combo.}// A sex is an arbitrary label designated by a brand or designer to indicate a // product's originally intended consumer.enumSex {MANWOMANUNISEX}// A market is either primary (MSRP and retailers) or secondary (resale).enumMarket {PRIMARYSECONDARY}// A price is an encapsulation of a product's value. A price can be for all the// sizes and color variants of a product (e.g. when being sold at retail value)// or specific to a single size and color variant (e.g. GOAT, Ebay, StockX).modelPrice {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The price's value in USD.valueDecimal// The price's market (primary—MSRP and retailers—or secondary—resale value).marketMarket// The URL of the product's listing at this price.urlString// The retailer that sells the product at this price.retailerRetailer?@relation(fields: [retailerId], references: [id], onDelete: Cascade, onUpdate: Cascade)retailerIdInt?// The brand that sells the product at this price.brandBrand?@relation(fields: [brandId], references: [id], onDelete: Cascade, onUpdate: Cascade)brandIdInt?// The product variant sold at this price (the size and color combo).variantVariant@relation(fields: [variantId], references: [id], onDelete: Cascade, onUpdate: Cascade)variantIdInt// Whether or not the price is still available (e.g. if it is sold out). This// is stored on the price model instead of the variant model as different// vendors can have different stocks of a given variant.// @todo instead of this, perhaps we should have a "stock" numeric field that// tracks how many units are available at this price from this retailer?availableBoolean@default(true)// @todo ensure that a price always has either a retailer or a brand.// @see https://github.com/prisma/prisma/issues/17319// Each price must have a unique value and URL (note that I can't simply put a// unique constraint on the URL due to secondary markets like GOAT that have a// single URL for many different sizes at many different prices).// Because each price contains the stock information for a specific size and// color variant, each price must be unique to that variant.@@unique([variantId, value, url])}// An image. Typically of a product being modeled.// @todo perhaps we should also store the image's original source?modelImage {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The URL (either fully qualified or a relative path) to the largest size of// the image available (the front-end optimizes images at runtime).urlString@unique// The image position in the product or look's gallery (if applicable).// @todo enforce unique image positions per product, variant, or look.positionInt?// The image width (if known) in px.widthInt?// The image height (if known) in px.heightInt?// The product variant(s) the image is of.// @todo if multiple products refer to the same image, we should make it// associated with a look instead and then link the look with those products.variantsVariant[]// The runway look the image is of.lookLook?@relation(fields: [lookId], references: [id], onDelete: Cascade, onUpdate: Cascade)lookIdInt?// The post that the image is from.postPost?@relation(fields: [postId], references: [id])postIdInt?// @todo store information on the models in the image (e.g. insta, etc).}// A video. Typically of a product being modeled.// @todo perhaps we should also store the image's original source?modelVideo {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The video's URL (either fully qualified or a relative path).urlString@unique// The video's mime type.mimeTypeString// The product variant(s) the video is of.variantsVariant[]// The show the video is of.showShow?// The post that the video is from.postPost?@relation(fields: [postId], references: [id])postIdInt?// @todo store information on the models in the video (e.g. insta, etc).}// Levels attempt to encapsulate a product's quality, price, and availability:// // 0 - bespoke. made to measure e.g. by comission.// 1 - haute couture. handmade approved by french law.// 2 - handmade. e.g. one-of-one etsy items, products made a friend.// 3 - ready-to-wear. widely available online or in-store.enumLevel {BESPOKECOUTUREHANDMADERTW}// An item is a high-level product category (e.g. "white turtleneck sweater").modelItem {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The item's styles (e.g. "turtleneck", "sweater").stylesStyle[]// The item's colors (e.g. "white").colorsColor[]// Products that satisfy the item specifications (i.e. a turtleneck sweater// sold by Aritzia that has a white color variant).//// Note that I intentionally do not associate variants with items. Instead, it// will be up to the client (i.e. the front-end) to show the correct product// variant that has the item's correct colors.productsProduct[]// The posts that include this item category in them.postsPost[]}// A product is an item that can be bought and sold.modelProduct {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The product's name as designated by the brand and designer.nameString@unique// The URL friendly slug identifier for the product.// Ex: /products/hermes-frozen-shorts is better than /products/356 for SEO.// @see {@link https://linear.app/nicholaschiang/issue/NC-673}slugString@unique// The product's description.descriptionString?// The product's level.// @todo perhaps rename this to "ProductLevel" to avoid confusion with "Tier"? levelLevel// The variants (colors + materials + sizes) the product was made in.variantsVariant[]// The original MSRP value of the product in USD (if applicable).// @todo perhaps this should be a field on the variant?msrpDecimal?// When a product was originally conceived.designedAtDateTime// When a product was first available to be purchased.releasedAtDateTime// The product's styles. Allegorical to labels (e.g. top, t-shirt, v-neck).// @todo preserve relationships between the same product in two different // styles (e.g. the "Agency Pant" and the "Agency Cropped Pant").stylesStyle[]// Item specifications that the product satisfies (e.g. a turtleneck sweater).itemsItem[]// The collections that feature the product.collectionsCollection[]// The product's designers. Typically, this will be a single person.designersUser[]// The product's brands. Collaborations can have multiple brands.brandsBrand[]// The product's looks (runway outfits that it was included in).looksLook[]// The posts that include this item.postsPost[]// @todo perhaps we should also store the product's original source?// @todo products must have a unique name per brand(s).}// A set is an arbitrary grouping of looks created by a user to act as a sort of// mood board. Users can "save" looks that they like to a "set" that can then be // shared with other users. Users can discover sets by other users (e.g. I see a// look that I like and then expore all the sets that include that look to find// similar looks).//// Sets are separate from collections for simplicity. Collections are officially// curated by a brand while sets are simple groupings of looks and products// created by users. I may opt to combine these two data models in the future, // but for now, simply adding an additional data model was easiest.//// Users can import looks and products from anywhere to add to their sets (e.g.// if I see an outfit I like on Instagram, I can click "share" to DOLCE and the// app will add it as a look to the selected set... that look will then be// automatically augmented with possible products to purchase).//// The name "set" was inspired by the website "Polyvore" which allowed users to// add products to a shared index called a "set".// @see {@link https://en.wikipedia.org/wiki/Polyvore}modelSet {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The set's name (e.g. "Summer Essentials").nameString// The set's description.descriptionString?// The set's author (i.e. the user who created the set).// @todo I should support multiple author(s) for a set (i.e. shared "sets") or// perhaps advanced access control (i.e. users who can view, can edit, etc).authorUser@relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)authorIdInt// The set's looks.looksLook[]// The set's product variants.// @todo perhaps we should also allow users to add products to a set without// having to select a specific size and/or color (e.g. when they're adding// products from the products list, they do not select a size)?variantsVariant[]// A user can only have one set with a given name.@@unique([name, authorId])}// A collection is an arbitrary grouping of products, typically done by a brand// or a designer. Often, collections are created entirely by a single designer.// Collections are separate from shows as every show has a collection but not// every collection has a show (e.g. Mission Workshop "Merino Core" collection// has no show v.s. Saint Laurent Fall-Winter 2023 has a show). Each show can// also have multiple collections shown (e.g. Fashion East often showcases// three collections from three different designers on the same runway).modelCollection {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The collection's name (e.g. "Hermès Spring-Summer 2023 Menswear").nameString@unique// The collection's style category (if limited to a single category).styleStyle?@relation(fields: [styleId], references: [id], onDelete: Cascade, onUpdate: Cascade)styleIdInt?// The collection's season. Typically, collection have seasons. While unusual,// collections can be released outside of a season (e.g. mw acre series).seasonSeason?@relation(fields: [seasonId], references: [id], onDelete: Cascade, onUpdate: Cascade)seasonIdInt?// The show that the collection was debuted at.showShow?@relation(fields: [showId], references: [id], onDelete: Cascade, onUpdate: Cascade)showIdInt?// The collection's webpage (from the designer, brand, or retailer site).linksLink[]// The products that belong to the collection.productsProduct[]// The designers that created the collection. Often, this is one person.// @todo products are already associated with designers; do we need this?designersUser[]// The brands that created the collection. Generally, we will only have one // brand, but—according to ChatGPT—there have been runway collections that // have been operated by multiple brands and showcased pieces from both of the // brands. One example is the "Fashion East" show in London, which provides a // platform for emerging designers to showcase their collections. The show // often features a combination of individual designers and collaborative // collections. Another example is the "Designer Collaborations" show at New // York Fashion Week, which features collaborations between established // designers and brands.// @todo products are already associated with brands; do we need this?brandsBrand[]}// A link is exactly that. A link to an external website. Currently, this model// is just used for collections, but will likely be used more in the future.modelLink {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The link's URL.urlString@unique// The collection the link is associated with.collectionCollection?@relation(fields: [collectionId], references: [id], onDelete: Cascade, onUpdate: Cascade)collectionIdInt?// The brand that the link is associated with.brandBrand?@relation(fields: [brandId], references: [id], onDelete: Cascade, onUpdate: Cascade)brandIdInt?// The retailer that the link is associated with.retailerRetailer?@relation(fields: [retailerId], references: [id], onDelete: Cascade, onUpdate: Cascade)retailerIdInt?// Each collection can only have one link per brand or retailer.@@unique([collectionId, brandId])@@unique([collectionId, retailerId])// Each brand can only have one link per retailer.@@unique([brandId, retailerId])}// A widely accepted and used season name.//// While brands may use different season names, these are the ones used by Vogue // and/or WWD (where I'm scraping data from), and thus these are the ones I use.enumSeasonName {RESORTSPRINGPRE_FALLFALL}// A fashion season is a widely accepted grouping of fashion releases.modelSeason {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The name of the season, as widely accepted and recognized.nameSeasonName// The year the season takes place in.yearInt// The runway shows that took place during the season.showsShow[]// The collections that were released during the season.collectionsCollection[]// Each season must have a unique name and year.@@unique([name, year])}// A look is an outfit that a model wore during a runway show.modelLook {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The look's number. Typically, looks are numbered sequentially.numberInt// The look's show.showShow?@relation(fields: [showId], references: [id], onDelete: Cascade, onUpdate: Cascade)showIdInt?// The look's author (if not part of a show, this was created by a user).authorUser?@relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)authorIdInt?// @todo ensure that a look always has either a show or an author.// @see https://github.com/prisma/prisma/issues/17319// The look's model (if known).modelUser?@relation("LooksModeled", fields: [modelId], references: [id], onDelete: Cascade, onUpdate: Cascade)modelIdInt?// The look's products (if known).// @todo perhaps I should optionally include variants if a specific size/color// of the product is shown in the look images and that information is known.productsProduct[]// The look's picture (if known).imagesImage[]// The user-curated sets that the look is a part of.setsSet[]// The posts that the look is a part of.postsPost[]// Each look must have a unique number in the show or by the author.@@unique([showId, number])@@unique([authorId, number])}// A post is an Instagram or TikTok or Threads or other social media post that// contains product(s) or look(s).modelPost {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The post's original URL.urlString@unique// The post's original description (i.e. the caption).descriptionString?// The post's author (this is not necessarily the original author but the user// that brought the post unto the DOLCE platform).authorUser@relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)authorIdInt// The post's images.imagesImage[]// The post's videos.videosVideo[]// The post's items (overall type of item e.g. "white turtleneck sweater").itemsItem[]// The post's products (exact brand of the item if known).productsProduct[]// The post's variants (exact color/size of the product if known).variantsVariant[]// The post's looks (exact collection of looks).looksLook[]}// An article is exactly that: a work of writing about some fashion-related // topic. For now, these generally fall into two categories:// - biographies about fashion designers (e.g. imported from Wikipedia);// - critic reviews of fashion shows (e.g. imported from Vogue and WWD).// @see {@link https://linear.app/nicholaschiang/issue/NC-658}modelArticle {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The date when the article was originally written or last edited (if known).// // The date when the article was originally written and the time when I // imported it will often be different (which is why this field exists // separately from the `createdAt` database field).writtenAtDateTime?// The article's canonical URL.urlString@unique// The article title (usually included as the header on their webpage).titleString// The article subtitle (typically included below the title on their webpage).// This is often a short summary of the general gist of the article content.// This field differs from the `summary` field as it is author-provided. The// `summary` field is generated by OpenAI or written by one of our curators.subtitleString?// The article summary (a plain text string; generated via OpenAI).summaryString?// The article content (an HTML string).contentString// The article review sentiment score from 0-1 (if applicable).//// A score of 0.5 is neutral, 0 is negative, and 1 is positive.// // Critical reviews will use whatever scale the critic uses (e.g. 0-10) or// will revert back to using a five-star scale if the critic does not assign// a score in their review (it will then be assigned via OpenAI).//// This field should only ever be NULL if a critic review has been imported// but no score has been assigned to it yet (e.g. when scraping Vogue) or if// this article simply isn't a critic review.scoreDecimal?// The article author (if applicable; Wikipedia has too many authors).authorUser?@relation("ArticlesWritten", fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)authorIdInt?// The user that the article is about (if this is a designer biography).userUser?@relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)userIdInt?// The show that the review is about (if this is a critic review).showShow?@relation(fields: [showId], references: [id], onDelete: Cascade, onUpdate: Cascade)showIdInt?// The publication that the article was posted to (Vogue, WWD, Wikipedia).publicationPublication@relation(fields: [publicationId], references: [id], onDelete: Cascade, onUpdate: Cascade)publicationIdInt// Each publication can only have one canonical article about a topic. This// constraint exists primarily to ensure that I don't import duplicates.// @@unique([publicationId, userId])// @@unique([publicationId, showId])// Each author can only submit one review for a show. I've yet to encounter// the same journalist publishing two different reviews for the same show. If// that does happen, I can always just replace their review with whichever is// the most recent. If a single journalist publishes two reviews in two// different publications for the same show, I should only count one of them// towards the aggregate critic score.@@unique([authorId, showId])// Each publication can only have one canonical article with a given title.@@unique([publicationId, title])}// A review is a review for a show from a consumer.modelReview {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The review sentiment score from 0-1.//// A score of 0.5 is neutral, 0 is negative, and 1 is positive.// // This will always increment by 0.2 (as we use a five-star scale to assign // these score numbers for consumer reviews).scoreDecimal// The review content (a plain text string).contentString// The review author.authorUser@relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)authorIdInt// The show that the review is about.showShow@relation(fields: [showId], references: [id], onDelete: Cascade, onUpdate: Cascade)showIdInt// Each user can only submit one review per show.@@unique([authorId, showId])}// A publication is a resource that publishes fashion reviews (e.g. Vogue).modelPublication {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The publication's name.nameString@unique// The publication's avatar URL (i.e. logo).avatarString?@unique// The publication's articles.articlesArticle[]}// There are only a few locations where fashion shows are held. While these may// not always be entirely accurate, they are more of a category of shows (e.g.// "Spring Tokyo 2023") than a specific location.//// This field was inspired by the Vogue season names (e.g. "Tokyo Spring 2023")// and the drop-down included on the WWD website (e.g. "New York", "Paris").//// @todo replace the "BRIDAL" location with some other show flag.// @todo this really should probably be its own model instead of an enum.enumLocation {NEW_YORKLONDONMILANPARISTOKYOBERLINFLORENCELOS_ANGELESMADRIDCOPENHAGENSHANGHAIAUSTRALIASTOCKHOLMMEXICOMEXICO_CITYKIEVTBILISISEOULRUSSIAUKRAINESAO_PAOLOBRIDAL}// A show is a fashion runway show.modelShow {idInt@id@default(autoincrement())createdAtDateTime@default(now())updatedAtDateTime@default(now())@updatedAt// The name of the show, as designated by the show's organizer.// @todo often this will be the same as the collection name; do we need this?// @todo often this is just a function of the brand + season names...nameString@unique// The link to the show on the brand website (where the description is from).urlString@unique// The show's sex (i.e. "womenswear", "menswear", or both).// @todo remove this once we have full show > collection > product data, as// the product object already has the sex field attached to it.sexSex// The show's level (i.e. "ready-to-wear", "couture", etc).// @todo remove this once we have full show > collection > product data, as// the product object already has the level field attached to it.levelLevel// A description of the collection, typically provided by the brand.descriptionString?// The critic's consensus on the show.articlesConsensusString?// The articles about the show (i.e. the show's critic reviews).articlesArticle[]// The consumer's consensus on the show.reviewsConsensusString?// Consumer reviews of the show.reviewsReview[]// Video of the show (typically just a single shot of runway models walking).videoVideo?@relation(fields: [videoId], references: [id], onDelete: Cascade, onUpdate: Cascade)videoIdInt?@unique// The fashion season in which the show was presented. e.g. Spring 2021// @todo collections are already associated with seasons; do we need this?seasonSeason@relation(fields: [seasonId], references: [id], onDelete: Cascade, onUpdate: Cascade)seasonIdInt// The date when the show started (if known).dateDateTime?// The runway show's location.locationLocation?// The collections that were presented at the show. Often, there is only one.collectionsCollection[]// The looks that were presented at the show.looksLook[]// The brand that hosted the show. This is different than the collection(s)// brand(s) that were presented at the show. Often, they will be the same.// Occasionally, however, the brand that hosts the show (e.g. "Fashion East")// will not be the brand(s) that presented their products at the show.brandBrand@relation(fields: [brandId], references: [id], onDelete: Cascade, onUpdate: Cascade)brandIdInt// A brand can only have a single show per season per sex (i.e. "menswear",// "womenswear", or both) per level (i.e. "couture", "ready-to-wear", etc) per// location (e.g. an "Australia" collection alongside a "Paris" collection).//// Ex: https://www.vogue.com/fashion-shows/australia-spring-2015/maticevski// Ex: https://www.vogue.com/fashion-shows/spring-2015-ready-to-wear/maticevski//// This constraint was inspired by Vogue's URLs (e.g. /resort-2024/hermes). It // may need adjustment in the future if there is ever a brand that presents // twice during a single season (but that probably means I need more seasons).@@unique([brandId, seasonId, sex, level, location])}
Environment & setup
OS: Mac OS
Database: PostgreSQL
Python version: Python 3.11.4
Prisma version: 5.4.2
prisma : 5.4.2
prisma client python : 0.11.0
platform : darwin
expected engine version : ac9d7041ed77bcc8a8dbd2ab6616b39013829574
installed extras : []
install path : /Users/nchiang/repos/dolce/.venv/lib/python3.11/site-packages/prisma
binary cache dir : /Users/nchiang/.cache/prisma-python/binaries/5.4.2/ac9d7041ed77bcc8a8dbd2ab6616b39013829574
The text was updated successfully, but these errors were encountered:
Bug description
When a model name clashes with a built-in name (e.g.
Set
), generation leads to weird behavior:How to reproduce
Steps to reproduce the behavior:
Set
Expected behavior
I should be able to name my Prisma models whatever I want to, even if they clash with built-in class names.
Prisma information
Environment & setup
The text was updated successfully, but these errors were encountered: