gpt4 book ai didi

python - 使用 Django ModelForm 的条件表单显示逻辑

转载 作者:太空宇宙 更新时间:2023-11-04 08:10:39 25 4
gpt4 key购买 nike

我想我可以用很多很多数据库查询和很多可怕的 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.选择子类型时,将该子类型作为 parent 的子子流域被视为选项等。

例如,假设我们在系统中定义了三种类型:音乐、书籍和播客。我们的新用户遇到了设置他们喜欢的类型的问题,并单击了音乐和书籍的复选框,但将 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技巧揭开它会给数据库带来很大的压力。

如果我将表单分散到多个页面(以及对数据库的多个查询),这很容易。但是,如何在不破坏数据库的情况下以一种形式完成这一切?

感谢您阅读所有这些!

最佳答案

首先,我会重新考虑你是如何塑造你的流派的。我认为更好的解决方案是只有一个模型 Genre ,而不是为每个 SubGenre 指定新模型.这也将允许您扩展到任意深度,而无需更改模型结构。

class Genre(models.Model):
parent = models.ForeignKey(Genre, null=True, related_name='sub_genre')
description = models.CharField(max_length=200, unique=True)
slug = models.SlugField(unique=True)

def __unicode__(self):
return self.description

@property
def is_top_level(self):
return bool(self.parent)

然后我会使用 Form而不是 ModelForm像这样:
class GenreForm(forms.Form):
genre = forms.ModelChoiceField(
queryset=Genre.objects.filter(parent__is_null=True))
sub_genre = forms.ModelChoiceField(
queryset=Genre.objects.filter(
parent__is_null=False, parent__parent__is_null=True))

对于前端,我认为最简单的解决方案是从给每个 sub_genre 选项一个 class='hidden' 开始。 ,并使用一个简单的 javascript 片段在选择父项时取消隐藏后续字段上的选项。

如果您有大量的类型,您可能会发现在页面加载时间方面最有效的方法是使用 ajax 填充后续字段。

希望能帮助到你!

关于python - 使用 Django ModelForm 的条件表单显示逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23203066/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com