Django, как сделать каждого члена поля ManyToMany уникальным? - PullRequest
0 голосов
/ 26 октября 2018

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

Вот как я смоделировал свои отношения (я пропустил много неважных полей и оставил только интересныеиз них):

Вот мой класс кандидата

class Candidate(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
cases = models.ManyToManyField(Case)

Вот мой класс дела

class Case(models.Model):
title = models.CharField(verbose_name="Titre", max_length=1000)
test1_complete = models.BooleanField(verbose_name="Test 1 Complété", default=False)
test2_complete = models.BooleanField(verbose_name="Test 2 Complété", default=False)
test3_complete = models.BooleanField(verbose_name="Test 3 Complété", default=False)
test4_complete = models.BooleanField(verbose_name="Test 4 Complété", default=False)

Затем я создал двух кандидатов и дело на панели пользователя и связалдва пользователя с делом через поле ManyToMany.булевы поля «Завершить тест» ссылаются на то, выполнил ли пользователь каждый набор тестов для текущего случая.

Вот как я получаю для каждого пользователя вариант «Случай» для его изменения:

def fetch_cases_info(request):
first_case = Candidate.objects.filter(user=request.user).values_list("cases", flat=True) 
user_case = Case.objects.get(id=first_case)

Моя проблема в том, что у каждого Кандидата есть один и тот же объект Case, и поэтому, если Пользователь1 завершит тест1 по делу, тогда у каждого Пользователя будет установлено значение true.

Моя цель состоит в том, чтобы при внесении изменений вКейс, сохраненный в поле ManyToMany кандидата, будет вносить изменения только для этого, а не для всех, использующих этот кейс.

Кто-нибудь знает, как смоделировать это отношение?Я бы хотел, чтобы у каждого кандидата было несколько дел, но они должны быть уникальными версиями дела, чтобы я мог изменять его состояние и влиять только на одного кандидата, а не на всех.

Спасибо за ответ.

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

ManyToManyField, если вы не сделаете иначе, создаст третью таблицу, выступающую в роли столяра. Это единственный способ, которым реляционные базы данных знают, как установить отношения «многие ко многим». Логические поля complete принадлежат этой объединяющей таблице, а не любой из двух таблиц "многие ко многим".

Поэтому вместо этого делайте то, что делает Джанго, но вручную: создайте модель (например, для упражнения); скажем, что у каждого кандидата может быть много упражнений, но каждое упражнение принадлежит одному кандидату; каждый случай выполняется во многих упражнениях, но каждое упражнение состоит из одного случая. Затем вставьте свои логические значения в таблицу упражнений. Затем вы можете прикрепить ManyToManyField к through='Exercise', если хотите, чтобы предоставить вам удобный доступ к candidate.cases и наоборот, теперь, когда вы знаете, что он на самом деле делает.

tl; dr: ManyToManyField - это взлом. Сделайте это вручную, чтобы узнать, что происходит (и чтобы иметь возможность использовать объединитель для собственных полей).

0 голосов
/ 26 октября 2018

Вы можете поиграть с параметром through для ManyToManyField, но я бы посоветовал немного изменить схему. Здесь я делаю предположение, но иметь новую колонку для каждого теста, возможно, не лучшая идея (подумайте, можете ли вы в будущем иметь Случаи с меньшим или большим количеством тестов)

class Case(models.Model):
    title = models.CharField(verbose_name="Titre", max_length=1000)

class TestCase(models.Model):
    case = models.ForeignKey(Case)
    number = models.PositiveIntegerField()

class Candidate(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
    completed_tests = models.ManyToManyField(TestCase)

А затем, чтобы узнать, какие тесты были решены для данного случая, выполните

candidate.completed_tests.filter(case=mycase)
...