Как сравнить, какие значения разделяют две модели/наборы поколений в представлении для последующего отображения в шаблоне?

Я пытаюсь сравнить все things в ModelOne с ModelTwo, проверить, какие things находятся или не находятся в одной или другой модели, затем поместить это в контекст представления для отображения в шаблоне.

class Things(model.Model):
    name = models.CharField()


class ModelOne(models.Model):
    things = models.ManyToManyField(Things)


class ModelTwo(models.Model):
    things = models.ManyToManyField(Things)

Как бы вы это сделали? Спасибо за ваше время и помощь, это очень ценно.

one_instance = ModelOne.objects.get(id=one_id)
two_instance = ModelTwo.objects.get(id=two_id)

one_thing_ids = set(one_instance.things.values_list("id", flat=True))
two_thing_ids = set(two_instance.things.values_list("id", flat=True))

shared_thing_ids = one_thing_ids & two_thing_ids
thing_ids_in_one_not_in_two = one_thing_ids - two_thing_ids
thing_ids_in_two_not_in_one = two_thing_ids - one_thing_ids

shared_things = Thing.objects.filter(id__in=shared_thing_ids)

Затем вы можете передать shared_things queryset в шаблон для отображения.

Если ваша модель Thing имеет только поле name и имена уникальны, мы можем немного упростить модель, изменив ее:

class Things(model.Model):
    name = models.CharField(unique=True)

или даже:

class Things(model.Model):
    name = models.CharField(primary_key=True, unique=True)

(в этом случае таблица db не будет иметь столбца id, он не нужен)

В любом случае мы можем избавиться от лишнего запроса Thing в конце:

one_instance = ModelOne.objects.get(id=one_id)
two_instance = ModelTwo.objects.get(id=two_id)

one_thing_names = set(one_instance.things.values_list("name", flat=True))
two_thing_names = set(two_instance.things.values_list("name", flat=True))

shared_thing_names = one_thing_names & two_thing_names
thing_names_in_one_not_in_two = one_thing_names - two_thing_names
thing_names_in_two_not_in_one = two_thing_names - one_thing_names

...и просто передавать в шаблон наборы строковых имен.

Вернуться на верх