Most efficient way to write a "Many to Occasional" field in Django

So I read that ManytoMany fields in Django were slower than ForeignKey lookups (as they make use of a helper table). I am creating an application that allows performers to catalog their acts. Each act they have in their catalog can have multiple images. However, I also want to specify one "Hero Image" of the Act which will be used for preview when they search through their catalog. each act can have many images, but only one of those could be a header image. I came up with three options but I want to hear what the hive has to think.

  1. ManytoManyField
from django.db import models
from django.contrib.auth.models import User

# Create your models here.
class Act(models.Model):
    title = models.CharField(max_length=200)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    description = models.TextField()
    hero_image = models.ForeignKey('Image', on_delete=models.SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class Image(models.Model):
    act = models.ManyToManyField(Act)
    image = models.ImageField(upload_to='images/')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
  1. Two Foreign Keys
from django.db import models
from django.contrib.auth.models import User

# Create your models here.
class Act(models.Model):
    title = models.CharField(max_length=200)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    description = models.TextField()
    hero_image = models.ForeignKey('Image', on_delete=models.SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class Image(models.Model):
    act = models.ForeignKey(Act, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='images/')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
  1. Create a separate table just for hero images. This may lead to duplicate data, if a performer includes the same image as their hero image and in their gallery (collection of images mapping to the act), but since there's only one hero image per act, I don't think it's too much storage wise? We could also edit UI to display hero image in the gallery by default do encourage users NOT to put their hero image in the image table as well... curious for thoughts on this one!
class Act(models.Model):
    title = models.CharField(max_length=200)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    description = models.TextField()
    hero_image = models.ForeignKey(HeroImage, on_delete=SET_NULL, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class HeroImage(models.Model):
    image = models.ImageField(upload_to='hero_images/')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class Image(models.Model):
    act = models.ForeignKey(Act, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='images/')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

I'll also take any other feedback about my code! I'm doing this as a personal project so I'll take any opportunity I can for a second pair of eyes. Thanks!

Вернуться на верх