重新组织Django中的多对多字段。

huangapple go评论59阅读模式
英文:

Regroup many-to-many fields in django

问题

我要获取给定用户的所有UserExercises,然后在我的模板中按类别分组显示它们,所以如果我有:{Ex1: {category: ["C1", "C2"]}, Ex2: {category: "C2"}},我希望它们被重新排序如下:{"C1": ["Ex1"], "C2": ["Ex2", "Ex1"]}

英文:

I have these model relationships

class ExerciseCategory(models.Model):
    owner = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, blank=True, null=True)
    name = models.CharField(max_length=100)
class UserExercises(models.Model): #Through table for the many-to-many relationship between User and Exercise
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name="user")
    exercise = models.ForeignKey('Exercise', on_delete=models.CASCADE)

class Exercise(models.Model):
    category= models.ManyToManyField(ExerciseCategory, through='CategoryExercisesThrough',blank=True, null=True) 
    assignee = models.ManyToManyField(get_user_model(), blank=True, null=True, through=UserExercises, related_name="assignee", through_fields=('exercise', 'user'))

class CategoryExercisesThrough(models.Model): #Through table for the many-to-many relationship between ExerciseCategory and Exercise
    category= models.ForeignKey(ExerciseCollections, on_delete=models.CASCADE)
    exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE)

I want to get all the UserExercises of a given user and then display them in my template grouped by category, so if I have: {Ex1: {category: ["C1", "C2"]}, Ex2: {category: "C2"}}, I want them reordered like this: {"C1": ["Ex1"], "C2": ["Ex2", "Ex1"]}

答案1

得分: 0

以下是您要求的翻译部分:

我建议手动进行后处理因此

<pre><code>from itertools import groupby
from operator import attrgetter

qs = (
    UserExercises.objects.filter(user=request.user)
    .annotate(category_id=F('exercise__category__pk'))
    .order_by('category_id')
)

result = {k: list(vs) for k, vs in <b>groupby(</b>qs, <b>attrgetter('category_id'))</b>}</code></pre>

这将把`ExerciseCategory`的主键映射到`UserExercises`列表上您可以进一步通过获取类别来进行后处理

<pre><code>categories = {ec.pk: ec for ec in ExerciseCategory.objects.filter(pk__in=result)}
result = {<b>categories[k]</b>: v for k, v in result.items()}</code></pre>

--- 

> **注意**: 通常Django模型应该使用*单数*名称所以应该是`UserExercise`而不是<s>`UserExercises`</s>

---

> **注意**: 通常最好使用[**`settings.AUTH_USER_MODEL`** <sup>\[Django-doc\]</sup>](https://docs.djangoproject.comen/stable/ref/settings/#std:setting-AUTH_USER_MODEL)来引用用户模型,而不是直接使用[**`User`**模型 <sup>\[Django-doc\]</sup>](https://docs.djangoproject.comen/stable/ref/contrib/auth/#django.contrib.auth.models.User)。有关更多信息,请参阅文档中的[*引用`User`模型*部分](https://docs.djangoproject.com/en/stable/topics/auth/customizing/#referencing-the-user-model)。
英文:

I suggest to just post-process this manually, so:

<pre><code>from itertools import groupby
from operator import attrgetter

qs = (
UserExercises.objects.filter(user=request.user)
.annotate(category_id=F('exercise__category__pk'))
.order_by('category_id')
)

result = {k: list(vs) for k, vs in <b>groupby(</b>qs, <b>attrgetter('category_id'))</b>}</code></pre>

this will map the primary key of the ExerciseCategory on to the list of UserExercisess, you can further post-process it by fetching the categories as well:

<pre><code>categories = {ec.pk: ec for ec in ExerciseCategory.objects.filter(pk__in=result)}
result = {<b>categories[k]</b>: v for k, v in result.items()}</code></pre>


> Note: normally a Django model is given a singular name, so UserExercise instead of <s>UserExercises</s>.


> Note: It is normally better to make use of the settings.AUTH_USER_MODEL&nbsp;<sup>[Django-doc]</sup> to refer to the user model, than to use the User model&nbsp;<sup>[Django-doc]</sup> directly. For more information you can see the referencing the User model section of the documentation.

huangapple
  • 本文由 发表于 2023年5月21日 22:56:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76300508.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定