Jump to content

Hello and good day.

I'm creating a website where users can commission artists. I wanted to check my work and see if the models I've made for this website lack anything or there might be a better way to do them.

I'm relatively new to Django and since I don't personally know any senior Django developers I though I might ask here. all criticism is welcome.

the website is divided into 4 apps. the main web app, the artist profile app, the digital art app and the physical art app.

 

1. Artist Profile App:

where you can create an artist account, track your orders, score and reviews.

from django.db import models

class Artist(models.Model):
    user = models.CharField(max_length=50, verbose_name="Artist Username")
    fname = models.CharField(max_length=50, verbose_name=("First Name"))
    lname = models.CharField(max_length=50, verbose_name=("Last Name"))
    email = models.EmailField(max_length=100, verbose_name=("Email"))
    phone = models.BigIntegerField(verbose_name=("Phone Number"))
    UserAddress = models.ManyToManyField("artistProfileApp.UserAddress", verbose_name=("User Addresses"))
    overall_score = models.DecimalField(max_digits=3, decimal_places=1, default=0, verbose_name=("User Score"))

    def __str__(self):
        return self.user

class Review(models.Model):
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE, related_name='reviews')
    reviewer = models.ForeignKey(Artist, on_delete=models.CASCADE)
    score = models.PositiveIntegerField(choices=[(i, i) for i in range(1, 6)])
    review_text = models.TextField()

    def __str__(self):
        return f"{self.reviewer}'s review of {self.artist}"

#I realize UserAddress model can be done a lot better using lists and dropdowns, im going to do that later on and the charfields are just placeholders for now
class UserAddress(models.Model):
    user = models.ForeignKey(Artist, on_delete=models.CASCADE)
    address_name = models.CharField(max_length=50)
    country = models.CharField(max_length=50)
    province = models.CharField(max_length=50)
    city = models.CharField(max_length=50)
    address = models.CharField(max_length=50)
    postal_code = models.CharField(max_length=50)

 

2. Digital Art App:

a separate app to handle all digital art displays and orders

from django.db import models
from artistProfileApp import models as artistProfileModel

class DigitalArtwork(models.Model):
    artist = models.ForeignKey(artistProfileModel.Artist, on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    description = models.TextField(max_length=500)
    image = models.ImageField(upload_to='artworks/', blank=True)
    plans = models.ManyToManyField("digitalArtApp.DigitalArtworkPlan", verbose_name=("Digital Artwork Plans"))
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    def __str__(self):
        return self.title
    
class DigitalArtworkPlan(models.Model):
    title = models.CharField(max_length=255)
    description = models.TextField(max_length=500)
    price = models.BigIntegerField()
    image = models.ImageField(upload_to='artworks/plans', blank=True)
    
class DigitalArtworkOrder(models.Model):
    customer = models.ForeignKey(artistProfileModel.Artist, on_delete=models.CASCADE)
    artwork = models.ForeignKey(DigitalArtwork, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    payed_at = models.DateTimeField(auto_now_add=True)

 

3. Physical Art App:

a separate app to handle physical arts, similar to digital art app with some changes

from django.db import models
from artistProfileApp import models as artistProfileModel

class PhysicalArtwork(models.Model):
    artist = models.ForeignKey(artistProfileModel.Artist, on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    description = models.TextField()
    image = models.ImageField(upload_to='artworks/', blank=True)
    plans = models.ManyToManyField("physicalArtApp.PhysicalArtworkPlan", verbose_name=("Digital Artwork Plans"))
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    def __str__(self):
        return self.title
    
class PhysicalArtworkPlan(models.Model):
    title = models.CharField(max_length=255)
    description = models.TextField(max_length=500)
    price = models.BigIntegerField()
    image = models.ImageField(upload_to='artworks/plans', blank=True)
    
class PhysicalArtworkOrder(models.Model):
    customer = models.ForeignKey(artistProfileModel.Artist, on_delete=models.CASCADE)
    artwork = models.ForeignKey(PhysicalArtwork, on_delete=models.CASCADE)
    address = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

 

Link to comment
https://linustechtips.com/topic/1493714-django-check-my-models/
Share on other sites

Link to post
Share on other sites

Not all that familiar with django, but I wouldn't use an integer for price, and I wouldn't use a separate table or database for physical art.  The data to describe both are too similar, and paying the overhead for a new database/table doesn't make sense to me when you can just add a type field instead.  If you intend to keep it separated, don't forget to rename the verbose_name attribute value of the field.

Link to comment
https://linustechtips.com/topic/1493714-django-check-my-models/#findComment-15840326
Share on other sites

Link to post
Share on other sites

I see Vicarian posted about the seperate database/table issue but assuming you are all for it [you do you if it works] you really shouldn't use an integer for a price. Heres a fun article about how to handle money https://learnpython.com/blog/count-money-python/ .Good luck other then that looks great! 

Link to comment
https://linustechtips.com/topic/1493714-django-check-my-models/#findComment-15842601
Share on other sites

Link to post
Share on other sites

- use full and correct names. "user" is not a good name for "Artist username" (and it should be name rather than username?)

- don't use abbreviations like "fname", use full understandable names to make the code easy to understand and clear

- variables should not be CamelCased like "UserAddress"

- why one Artist would have multiple addresses ? And you have two sided relation - M2M and FK which is redundant.

- why a reviewer is another Artist? Should you have separate artists and users? The same is in order model?

- Review model can have a "text" field, no need to repeat "review" twice.

- not sure what's going on with Artworks and ArtworkPlans

- didn't checked but the cascades should be used carefully. Not every related object should cascade delete others.

 

Also you should protect the artwork so no easy to guess path, filename etc. Best if not exposed publicly as media files. Depends on business context on how this would work.

Link to comment
https://linustechtips.com/topic/1493714-django-check-my-models/#findComment-15844436
Share on other sites

Link to post
Share on other sites

5 hours ago, riklaunim said:

- variables should not be CamelCased like "UserAddress"

Presumably you meant "should be" rather than "should not be?"  Also, naming conventions are subjective.  Perhaps the OP likes snake case.  Consistency is, in my opinion, more important.  For example, our group collectively decided to use kebab case for HTML element IDs and class names, camel case for JavaScript variable names, and Pascal case for JavaScript class names.  All of our files follow these conventions, so any of us can maintain each other's code if needed.

Link to comment
https://linustechtips.com/topic/1493714-django-check-my-models/#findComment-15844798
Share on other sites

Link to post
Share on other sites

3 hours ago, Vicarian said:

Presumably you meant "should be" rather than "should not be?"

In Python CamelCase naming is used only for class names not for variables, functions, attributes and so on. It's not that subjective as it's at the core of Python styling and every linter will pick it up. This isn't JavaScript where things are quite different.

Link to comment
https://linustechtips.com/topic/1493714-django-check-my-models/#findComment-15844916
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×