Упорядочивание Many-To-Many Custom через таблицу, теперь поле имеет дубликаты

Как видно из названия, когда я пытаюсь сделать заказ по моей пользовательской сквозной таблице, поле теперь показывает дубликаты. Похоже, что происходит левое внешнее соединение, отображающее все поля с обеих сторон вместо того, чтобы показывать только уникальные значения, и distinct(), похоже, ничего не делает. Я использую sqlite3, а distinct('field-name') не поддерживается sqlite3. Вот сокращенное изложение моего кода, показывающее только релевантные поля:

# Models
class DataRepository(Base):
    class Meta:
        ordering = ('-updated_at',)
    name = models.CharField(max_length=100, unique=True)

class Dataset(models.Model):
    class Meta:
        ordering = ('-updated_at',)
    name = models.CharField(max_length=100, unique=True)  # Dataset name must be unique across BrainSTEM
    datarepositories = models.ManyToManyField(DataRepository, through="DatasetDatarepository", blank=True)  # Data repositories where the data from this dataset is stored. Create private data repositories [here]

class DatasetDatarepository(models.Model):
    class Meta:
        ordering = ('order',)
        unique_together = (('dataset', 'datarepository'),)
    dataset = models.ForeignKey(Dataset, on_delete=models.CASCADE)
    datarepository = models.ForeignKey(DataRepository, on_delete=models.CASCADE)
    order = models.PositiveIntegerField(null=True, blank=True, default=0)

# Admin
class DatasetAdmin(admin.ModelAdmin):
    fieldsets = (
        (None, {'fields': (
            'name',
            'datarepositories',
        )}),
    )
    form = DatasetForm

# Form
class DatasetForm(forms.ModelForm):
    class Meta:
        model = Dataset
        fields = [
            "name",
            "datarepositories",
        ]
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
       if self.fields.get('datarepositories', None):
            datarepositories = self.fields.get("datarepositories")
            dr = DataRepository.objects.none()
            projects = self.instance.projects.all()
            for project in projects:
                for group in get_groups_with_perms(project):
                    dr |= get_objects_for_group(group, 'change_datarepository', DataRepository, accept_global_perms=False)
            datarepositories.queryset = dr.order_by('datasetdatarepository')

Последняя строка, когда я ее закомментирую, не будет показывать дубликаты. В противном случае он показывает дубликаты. Вероятно, это происходит потому, что Django не знает, существует ли ассоциат или нет, поэтому он делает левое внешнее объединение. Проблема в том, что в него попадают все экземпляры поля datarepository, которые могут быть связаны с разными наборами данных, и он не знает, какой порядок выбрать.

Есть ли способ заставить этот кверисет работать подобным образом?

  1. Получите все хранилища данных, удовлетворяющие критериям, указанным в init формы (все те, которые связаны с проектами, чьи группы имеют права на их изменение)
  2. Из этого списка проверьте, не связаны ли уже какие-либо из них с этим набором данных, и если да, то упорядочьте их по значению 'order' в сквозной таблице, не показывая дубликаты.

Я видел здесь сообщение, которое было похоже, и они использовали annotate для получения максимального значения поля. Я попробовал сделать это следующим образом:

DataRepository.object.annotate(max_order=Max('datasetdatarepository__order')).order_by('max_order')

Это не работает, потому что не гарантируется получение правильного поля datarepository (того, которое связано с этим набором данных). Теперь оно просто берет то, которое имеет наибольшее значение. А мне нужно быть связанным с текущим набором данных или не быть включенным.

Кроме того, он должен возвращать queryset, поэтому я не могу преобразовать его в какой-либо другой тип объекта.

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