gpt4 book ai didi

python - Django 形式的多个模型

转载 作者:行者123 更新时间:2023-12-04 15:07:24 25 4
gpt4 key购买 nike

我有以下模型:

class Category(models.Model):
label = models.CharField(max_length=40)
description = models.TextField()


class Rating(models.Model):
review = models.ForeignKey(Review, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
rating = models.SmallIntegerField()


class Review(models.Model):
author = models.ForeignKey(User, related_name="%(class)s_author", on_delete=models.CASCADE)
coach = models.ForeignKey(User, related_name="%(class)s_coach", on_delete=models.CASCADE)
comments = models.TextField()

我想创建一个前端表单,允许用户评论教练,包括对一些预填充类别的评级。

在我的脑海中,表单看起来像这样:

 Coach: _______________         # Selection of all coach users from DB, this works as standard

Category: "Professionalism" # These would be DB entries from the Category model
Rating: _ / 5

Category: "Friendliness"
Rating: _ / 5

Category: "Value"
Rating: _ / 5

Comments:
_________________________________
_________________________________

Submit

我看过 Django Formsets在文档中,但这些似乎存在用于从与单个表单相同的模型创建多个表单?

不是在寻找完整的答案,但如果有人能指出正确的方向,我将不胜感激。

编辑:Vineet 的回答(https://stackoverflow.com/a/65883875/864245)几乎正是我要找的,但它是针对管理区域的,我在前端需要它。

最佳答案

鉴于类别相当静态,您不希望用户选择类别。类别本身应该是标签,而不是供用户选择的字段。

您在评论中提到,标签有时会发生变化。我想在决定如何在这里进行之前我会问两个问题:

  1. 谁将继续更新标签(他们是否具有基本的编码能力,或者他们是否依赖于使用诸如管理员之类的工具)。
  2. 当标签改变时,它们的基本含义会改变还是只是措辞

考虑 1

如果更改标签的人对 django 有基本的了解,并且有适当的权限(或者可以请开发人员为他们进行更改),那么一开始就对这 5 件事进行硬编码可能是最好的方法:

class Review(models.Model):
author = models.ForeignKey(User, related_name="%(class)s_author", on_delete=models.CASCADE)
coach = models.ForeignKey(User, related_name="%(class)s_coach", on_delete=models.CASCADE)
comments = models.TextField()
# Categories go here...
damage = models.SmallIntegerField(
help_text="description can go here",
verbose_name="label goes here"
)
style = models.SmallIntegerField()
control = models.SmallIntegerField()
aggression = models.SmallIntegerField()

这有很多优点:

  • 这是一个非常简单且易于理解的表,而不是 3 个带有连接的表。
  • 这将使您的代码库上下的一切变得更简单。它将使当前情况(管理表单)变得更容易,但它也会使您编写的每个查询、 View 、模板、报告、管理命令等更容易,向前发展。
  • 您可以在需要时使用 verbose_namehelp_text 编辑标签和说明。

如果像这样更改代码不是一个选项,并且标签必须通过 django 管理应用程序之类的东西设置,那么外键是你唯一的出路。

同样,您并不真的希望您的用户选择类别,所以我只是将它们动态添加为字段,而不是使用表单集:

class Category(models.Model):
# the field name will need to be a valid field-name, no space etc.
field_name = models.CharField(max_length=40, unique=True)
label = models.CharField(max_length=40)
description = models.TextField()
class ReviewForm.forms(forms.Form):
coach = forms.ModelChoiceField()

def __init__(self, *args, **kwargs):
return_value = super().__init__(*args, **kwargs)

# Here we dynamically add the category fields
categories = Categories.objects.filter(id__in=[1,2,3,4,5])
for category in categories:
self.fields[category.field_name] = forms.IntegerField(
help_text=category.description,
label=category.label,
required=True,
min_value=1,
max_value=5
)

self.fields['comment'] = forms.CharField(widget=forms.Textarea)

return return_value

由于(我假设)当前用户将是 review.author,您将需要访问 request.user 因此我们应该保存您的所有 View 中而不是窗体中的新对象。您的看法:

def add_review(request):
if request.method == "POST":
review_form = ReviewForm(request.POST)
if review_form.is_valid():
data = review_form.cleaned_data
# Save the review
review = Review.objects.create(
author=request.user,
coach=data['coach']
comment=data['comment']
)
# Save the ratings
for category in Category.objects.filter(id__in=[1,2,3,4,5]):
Rating.objects.create(
review=review
category=category
rating=data[category.field_name]
)

# potentially return to a confirmation view at this point
if request.method == "GET":
review_form = ReviewForm()

return render(
request,
"add_review.html",
{
"review_form": review_form
}
)

考虑2

要了解第 2 点(上文)的重要性,请想象以下情况:

  1. 您从 4 个类别开始:伤害、风格、控制和侵略。
  2. 您的网站上线并收到了一些评论。假设教练 Tim McCurrach 获得的评论分别为 2、1、3、5。
  3. 几个月后,我们意识到“风格”不是一个非常有用的类别,因此我们将标签更改为“效果”。
  4. 现在 Tim McCurrach 对一个类别的评分为“1”,该类别过去标签为“风格”,但现在标签为“效果”,这根本不是评论作者的本意。
  5. 您所有的旧数据都毫无意义。

如果 Style 只会改变为与 style 非常相似的东西,我们就不必太担心了。

如果您确实需要更改标签的基本性质,我会在您的Category 模型中添加一个active 字段:

class Category(models.Model):
field_name = models.CharField(max_length=40, unique=True)
label = models.CharField(max_length=40)
description = models.TextField()
active = models.BooleanField()

然后在上面的代码中,我会写 Category.objects.filter(id__in=[1,2,3,4,5]) 而不是 Category.objects.filter (事件=真)。老实说,我想我会这样做。在你的代码中硬编码 ids 是不好的做法,而且很容易出错。无论如何,第二种方法更灵活。

关于python - Django 形式的多个模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65870482/

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