Пользовательская проверка ModelForm в Django - PullRequest
0 голосов
/ 14 марта 2019

Я работаю над приложением Django для регистрации продаж.Я создал три модели: Project, Employee и Sale.

Модели проекта и сотрудников следующие:

class Project(models.Model):
    project_id = models.IntegerField(primary_key = True)
    name = models.CharField(max_length = 100, unique = True)

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

class Employee(models.Model):
    employee_id = models.IntegerField(primary_key = True)
    name = models.CharField(max_length = 50)
    email = models.CharField(max_length = 40)

class Meta:
    ordering = ['name']

def __str__(self):
    return self.name

Тогда модель продажи:

class Sale(models.Model):
    sale_name = models.CharField(max_length = 30)
    project = models.ForeignKey('Project', on_delete = models.CASCADE)

    proactive_seller = models.ManyToManyField(Employee, related_name = 'proactive')

    participants = models.ManyToManyField(Employee, related_name = 'participant')

    doers = models.ManyToManyField(Employee, related_name = 'doer')

    start_date = models.DateField()
    end_date = models.DateField()

    def __str__(self):
        return self.sale_name

Таким образом, каждый объект продажи содержит информацию о том, к какому проекту относится продажа, какой сотрудник был проактивным / ведущим продавцом, какие сотрудники участвовали в продаже, а также какие сотрудники будут заниматься фактическим проектом.

В моем forms.py я хочу убедиться, что продажи уникальны в том смысле, что я хочу вызвать ошибку, если пользователь пытается ввести продажу, которая уже имеет тот же проект, ту же дату и тех же исполнителей, т.е.исполнители не могут быть выделены для проекта более одного раза за один раз.

Мой файл forms.py в настоящее время выглядит следующим образом:

class SaleForm(ModelForm):
    class Meta:
        model = Sale
        widgets = {
        'start_date': DatePickerInput(), 
        'end_date': DatePickerInput(), 
    }

Я попробовал следующее:

    def clean(self):
        cleaned_data = super.clean()
        start = cleaned_data.get('start_date')
        end = cleaned_data.get('end_date')
        doers = cleaned_data.get('doers')
        project = cleaned_data.get('project')
        if start and end and doers and project:
            queryset = Sale.objects.all()
            # Filter based on project
            q = queryset.filter(project__name=project, start_date = start, end_date = end)
            for employee in doers:
                q = q.filter(doers__name=employee)
            if q.count() > 1:
                raise forms.ValidationError('Sale has already been registered.')

Однако проверка не работает должным образом: мне все еще разрешено распределять «сотрудников» в один и тот же «проект» в одно и то же время (т. Е. Даты начала и окончания).

Помощь очень ценится.

1 Ответ

0 голосов
/ 16 марта 2019

То, что вы пытаетесь сделать, это проверять каждый экземпляр отношения M2M для данного экземпляра.Это может быть довольно сложно сделать.Что должно быть достаточно, так это отфильтровать продажи с тем же числом исполнителей и отфильтровать продажи, в которых есть другой исполнитель.

from django.db.models import F, OuterRef, Exists, Q

q = queryset.filter(project__name=project, start_date=start, end_date = end)
other_doers = Employee.objects.filter(
     # Exclude any employee with the name of the doers on this project.
     # We only want other doers.
     ~Q(name__in=[e.name for e in doers]),
     # This links the subquery to the main query (Sale)
     doer=OuterRef('id'),
)
q = q.annotate(
    # Get the count of doers per sale
    doer_count=Count('doers__id', distinct=True),
    # Check if other doers are in the project
    has_other_doer=Exists(other_doers)
).filter(
    # Only look for sales with the same number of doers
    doer_count=len(doers),
    # Filter out sales that contain other doers
    has_other_doer=False,
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...