【发布时间】:2014-06-05 20:27:24
【问题描述】:
我想我可以用一种非常丑陋的方式来解决这个问题,其中包含许多数据库查询和大量可怕的 jQuery,但我希望有一个更简单的方法。
我正在为 Django 网站构建一个小型分类应用程序。网站上有各种媒体,它们被分类为属于某种类型、子类型、子子类型和子子子类型。例如,一些媒体可能被分类为音乐(流派)、布鲁斯(子流派)、孟菲斯蓝调(子子流派)、福音蓝调(第二子子流派)和第 32 街班卓蓝调(子子子流派,这个是编的)。
Genre、SubGenre、SubSubGenre 和 SubSubSubGenre 都是模型:
class Genre(models.Model):
description = models.CharField(max_length=200, unique=True)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.description
class SubGenre(models.Model):
parent = models.ForeignKey(Genre, related_name='sub_genre')
description = models.CharField(max_length=200, unique=True)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.description
class SubSubGenre(models.Model):
parent = models.ForeignKey(SubGenre, related_name='sub_sub_genre')
description = models.CharField(max_length=200, unique=True)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.description
class SubSubSubGenre(models.Model):
parent = models.ForeignKey(SubSubGenre, related_name='sub_sub_sub_genre')
description = models.CharField(max_length=200, unique=True)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.description
添加到网站的每条媒体都有一个 MTM 字段,将其与这些限定符中的一个或多个相关联,如下所示:
class Media(models.Model):
genres = models.ManyToManyField(Genre)
sub_genres = models.ManyToManyField(SubGenre)
sub_sub_genres = models.ManyToManyField(SubSubGenre)
sub_sub_sub_genres = models.ManyToManyField(SubSubSubGenre)
#other fields
我们网站上的每个用户都有一个用户个人资料(使用一对一关系扩展基本用户模型)。在该用户个人资料中,他们可以告诉我们他们喜欢使用哪种类型的媒体。
class UserProfile(models.Model):
user = models.OneToOneField(User)
preferred_genres = models.ManyToManyField(Genre, related_name='genre_pref')
preferred_sub_genres = models.ManyToManyField(SubGenre, related_name = 'subgenre_pref')
preferred_sub_sub_genres = models.ManyToManyField(SubSubGenre, related_name = 'subsubgenre_pref')
preferred_sub_sub_sub_genres = models.ManyToManyField(SubSubSubGenre, related_name = 'subsubsubgenre_pref')
我想创建两种表单:一种用于创建新的用户配置文件,另一种用于创建新的媒体。用户应该能够定义他们喜欢的流派、子流派等。媒体上传者应该能够以相同的方式对其媒体进行分类。
我们只有几个流派,但每个流派都有十几个或更多子流派。每个子流派有 20 多个子子流派。大多数子子流派有 20 多个子子子流派。我不能一次将所有这些选项都扔到页面上——这太可怕了。
这就是我希望发生的事情。以“新用户资料表格”为例。我不想让用户一次设置他们喜欢的流派、子流派、子子流派和子子子流派,我希望只有一个多选表单,用户可以在其中设置他们的首选流派。 Then, when the preferred genre is selected (but before the form is submitted), sub-genre choices specific to that genre appear.选择子流派后,以该子流派为父的子子流派将显示为选项等。
例如,假设我们在系统中定义了三种类型:音乐、书籍和播客。我们的新用户遇到了设置他们喜欢的类型的问题,并单击了音乐和书籍的复选框,但将 Podcast 留空。我希望该用户能够为 Music 和 Book 设置他们的首选子流派,并且 CheckboxSelectMultiple 字段仅填充以 Music 或 Book 作为父级的子流派(Music.subgenre_set .all() 或 Book.subgenre_set.all() 将返回适当的选择)。
再举一个例子,假设我们有一个上传播客的用户。在上传表单上,他们遇到了询问媒体属于什么类型的问题。用户选中“播客”框。现在我们想知道媒体属于哪些子类型。我们如何仅使用具有父“播客”的子类型填充 CheckboxSelectMultiple 字段?
在任一示例中,如果“Podcast”是选择的类型,则表单下一部分的适当子类型选择将由 Podcast.subgenre_set.all() 表示。如果该播客的子流派之一是“非小说类”,那么选择该子流派还应调出适当的子子流派选择:Nonfiction.subsubgenre_set.all()。我不能只是硬编码流派、子流派、子子流派和子子子流派名称,但是因为将来肯定会添加新的名称,这将造成扩展的噩梦。
我也觉得只是在幕后“加载”每一个可能的whatever_set,然后用javascript 技巧揭开它会给数据库带来很大的压力。
如果我将表单分散到多个页面(以及对数据库的多个查询),这很容易。但是如何在不破坏数据库的情况下以一种形式完成所有这些操作?
感谢您阅读所有这些内容!
【问题讨论】: