Упорядочивание 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, которые могут быть связаны с разными наборами данных, и он не знает, какой порядок выбрать.
Есть ли способ заставить этот кверисет работать подобным образом?
- Получите все хранилища данных, удовлетворяющие критериям, указанным в init формы (все те, которые связаны с проектами, чьи группы имеют права на их изменение)
- Из этого списка проверьте, не связаны ли уже какие-либо из них с этим набором данных, и если да, то упорядочьте их по значению 'order' в сквозной таблице, не показывая дубликаты.
Я видел здесь сообщение, которое было похоже, и они использовали annotate для получения максимального значения поля. Я попробовал сделать это следующим образом:
DataRepository.object.annotate(max_order=Max('datasetdatarepository__order')).order_by('max_order')
Это не работает, потому что не гарантируется получение правильного поля datarepository (того, которое связано с этим набором данных). Теперь оно просто берет то, которое имеет наибольшее значение. А мне нужно быть связанным с текущим набором данных или не быть включенным.
Кроме того, он должен возвращать queryset, поэтому я не могу преобразовать его в какой-либо другой тип объекта.