Python 简化Django模型以实现eStore,并协助ManyToManyField
建立一个专门销售衬衫、书籍和相册的电子商务网站,以了解不同型号的产品。有两件事让我很反感: 1.)我不确定我的模型是否产生了过多的冗余,如果是,如何将其最小化。例如,对于音乐专辑,我正在为专辑、艺术家和曲目创建一个模型,在每个模型中,我多次引用其他模型 2.)关于我的许多字段,通过引用一个在models.py中进一步定义后才定义的模型,Python 简化Django模型以实现eStore,并协助ManyToManyField,python,database,django,sqlite,django-models,Python,Database,Django,Sqlite,Django Models,建立一个专门销售衬衫、书籍和相册的电子商务网站,以了解不同型号的产品。有两件事让我很反感: 1.)我不确定我的模型是否产生了过多的冗余,如果是,如何将其最小化。例如,对于音乐专辑,我正在为专辑、艺术家和曲目创建一个模型,在每个模型中,我多次引用其他模型 2.)关于我的许多字段,通过引用一个在models.py中进一步定义后才定义的模型,python manage.py syncdb抛出了一个错误,即我没有定义关系。本问题对此作了进一步解释: 这是我的models.py: from django.
python manage.py syncdb
抛出了一个错误,即我没有定义关系。本问题对此作了进一步解释:
这是我的models.py:
from django.db import models
#Artist, Album, and Tracks are tables for music albums
class Artist(models.Model):
artist_name = models.CharField(max_length=100, null=False, blank=False)
short_bio = models.CharField(max_length=2000, null=False, blank=False)
albums = models.ManyToManyField(Album)
tracks = models.ManyToManyField(Track)
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
class Album(models.Model):
album_name = models.CharField(max_length=150, null=False, blank=False)
artists = models.ManyToManyField(Artist)
tracks = models.ManyToManyField(Track)
active = models.BooleanField(default=True)
slug = models.SlugField(null=True, blank=True)
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.album_name
class Track(models.Model):
track_name = models.CharField(max_length=200, null=False, blank=False)
artists = models.ManyToManyField(Artist)
album_name = models.ManyToManyField(Album)
class AlbumImage(models.Model):
album_name = models.ForeignKey(Album)
description = models.CharField(max_length=200, null=True, blank=False)
main = models.BooleanField(default=False)
image = models.ImageField(upload_to='albums/images/')
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
#Book, BookGenre, Author tables for books
class Book(models.Model):
title = models.CharField(max_length=200, null=False, blank=False)
authors = models.ManyToManyField(Author)
pages = models.PositiveSmallIntegerField(null=True, blank=True)
genre = models.ManyToManyField(BookGenre)
active = models.BooleanField(default=True)
slug = models.SlugField(null=True, blank=True)
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.title
class Author(models.Model):
author_name = models.CharField(max_length=50, null=False, blank=False)
short_bio = models.CharField(max_length=2000, null=True, blank=True)
titles = models.ManyToManyField(Book)
genre = models.ManyToManyField(BookGenre)
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
class BookGenre(models.Model):
genre = models.CharField(max_length=50, null=False, blank=False)
class BookImage(models.Model):
title = models.ForeignKey(Book)
description = models.CharField(max_length=200, null=True, blank=False)
main = models.BooleanField(default=False)
image = models.ImageField(upload_to='books/images/')
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
#Shirt and Colors are for tables exclusively for shirts
class Shirt(models.Model):
title = models.CharField(max_length=50)
description = models.CharField(max_length=2000, null=True, blank=False)
styles = models.ManyToManyField('ShirtStyle.style')
sz_xs = models.PositiveSmallIntegerField(null=False, blank=False)
sz_sm = models.PositiveSmallIntegerField(null=False, blank=False)
sz_md = models.PositiveSmallIntegerField(null=False, blank=False)
sz_lg = models.PositiveSmallIntegerField(null=False, blank=False)
sz_xl = models.PositiveSmallIntegerField(null=False, blank=False)
active = models.BooleanField(default=True)
slug = models.SlugField(null=True, blank=True)
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.title
class ShirtStyle(models.Model):
style = models.CharField(max_length=50, null=False, blank=False)
title = models.ForeignKey('Shirt.title')
class ShirtImage(models.Model):
title = models.ForeignKey(Shirt)
description = models.CharField(max_length=200, null=True, blank=False)
main = models.BooleanField(default=False)
image = models.ImageField(upload_to='shirts/images/')
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
谢谢您的时间。很好的开始,但是,正如您所猜测的,您的模型中有太多的冗余。我将提供以下建议: 1) 不要过多地使用
ManyToManyField
。
当每个模型与其他许多模型相关时,应使用多个模型。对于你的一些模型来说,情况并非如此。例如,虽然每个专辑
都有许多曲目
,但反过来可能不正确;每首曲目
只属于一首专辑
。“闻起来像少年精神”是专辑中的曲目
“Nevermind”,但它不是任何其他专辑中的曲目
。因此,您应该使用外键
class Track(models.Model):
track_name = models.CharField(max_length=200, null=False, blank=False)
album_name = models.ForeignKey(Album)
这里的一个例外是,如果一首曲目实际上会出现在多张专辑中,也就是说,如果它也出现在一张“最受欢迎的”专辑中或除“Nevermind”之外的其他歌曲中
2) 不要重复关系
在上面的示例中,我们通过外键将每个曲目
连接到专辑
。我们不需要做相反的事情。也就是说,Album
不需要显式字段来跟踪其所有曲目。您可以在查询时执行此操作。Django关于跨关系查询的文档如下所示
这也有进一步的含义。您可能会通过外键将您的相册
连接到艺术家
。因为您可以跨越关系,所以不需要显式连接曲目
和艺术家
。因此,三种模型的简单示例如下所示:
from django.db import models
#Artist, Album, and Tracks are tables for music albums
class Artist(models.Model):
artist_name = models.CharField(max_length=100, null=False, blank=False)
short_bio = models.CharField(max_length=2000, null=False, blank=False)
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
class Album(models.Model):
album_name = models.CharField(max_length=150, null=False, blank=False)
artist = models.ForeignKey(Artist)
active = models.BooleanField(default=True)
slug = models.SlugField(null=True, blank=True)
added = models.DateTimeField(auto_now=True, auto_now_add=False)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.album_name
class Track(models.Model):
track_name = models.CharField(max_length=200, null=False, blank=False)
album_name = models.ForeignKey(Album)
这还需要注意,如果要将一张专辑
连接到多个艺术家
,则需要对其进行一些调整。这就像你将乐队成员分开一样,即“Abbey Road”是四位不同的艺术家的专辑
:John、Paul、George和Ringo
3) 定义模型错误
一旦停止重复关系,您在(2)中提到的与模型相关的问题就应该消失。基本上,在定义模型之前,不能将其用作关系。当您在两个模型上执行manytomy
操作时,这导致了一个问题。其中一个必须先于另一个,这将导致进口问题。如果您想在定义前使用它,也可以设置null=True
,但在这种情况下确实没有必要
如果有任何不清楚的地方或者您有任何进一步的问题,请告诉我
编辑:
附加提示:
如果要在许多模型上使用added
和modified
字段,可能需要使用django模型utils
包。医生。您可以将一个timestamesedmodel
子类化,该子类自动生成已创建的和已修改的字段。看
因此:
谢谢你,亚历克斯。这是非常有洞察力的,对我理解DB模式有很大帮助。我一直在剖析你的答案,并进一步深入兔子洞,阅读关于Django模型的文章。两个问题:1.)由于ForeignKey关系较少,我在admin.py上遇到了问题,它需要ForeignKey进行内联编辑。如何创建一个一站式界面,在不改变模型的情况下添加艺术家、专辑、曲目和图像?2.你最好的例子就是为什么我用了很多。如果95%的歌曲是原创歌曲,而只有5%是封面歌曲,那么仍然有必要吗?@SeanDominguez:Re(1):您是否尝试过InlineModelAdmin
对象?见文件。允许使用外键进行内联模型编辑。如果您对此有困难,我建议您创建一个新的问题,因为在评论中很难回答而不看到您的代码。至于(2):如果您有理由将一个子模型分配给多个父模型,则需要使用多个子模型。
from model_utils.models import TimeStampedModel
class Artist(TimeStampedModel):
artist_name = models.CharField(max_length=100, null=False, blank=False)
short_bio = models.CharField(max_length=2000, null=False, blank=False)