Django отношения "многие ко многим" в модели одного класса

У меня есть modelclass 'Mapset' с formclass 'MapSetForm' и у меня есть имя поля many to many, потому что я хочу сделать отношения, где Mapset может иметь много Mapset, но mapset не должен иметь отношения к самому себе.

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

Вопрос: Как я могу удалить этот набор карт из списка?

class MapSetForm(forms.modelform)

class Meta:
model = MapSet
fields = [
'name',
'dependencies',
...
]
def __init__(self, *args, **kwargs):
    n = kwargs.pop('dependencies', [])
    super(MapSetForm,self).__init__(*args, **kwargs)
    self.fields['name'].queryset = MapSet.objects.filter(name = n)

view:

class MapsetUpdateView(guardian.mixins.PermissionRequiredMixin, UpdateView):

model = MapSet
form_class = MapSetForm()
permission_required = 'webksv.change_mapset'
return_403 = True

модель:

class MapSet(models.Model): """Model class for MapSets.

name = models.CharField(
    'Name',
    max_length=50,
    unique=True,
    validators=[alphanumeric])
visibility = models.ForeignKey(Visibility, models.DO_NOTHING)
verbose_name = models.CharField('Langname', max_length=256)
description = models.TextField('Beschreibung', blank=True)
dependencies = models.ManyToManyField(
    'self',
    blank=True,
    symmetrical=False)

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

mapset.dependencies.remove( mapset)

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

qs = Mapset.objects.exclude( pk=mapset.pk).filter( ...)

Что касается формы, то поскольку вы не знаете заранее, какой набор карт будет выбран, вы не можете исключить его из результатов dependencies. Поэтому вам нужно избавиться от него в логике form_valid вашего представления: Если вы хотите сообщить пользователю о самозависимости как об ошибке:

def form_valid( self, form):
    # if you do want to report an error to the user
    
    name = form.cleaned_data['name']
    dependencies = form.cleaned_data['dependencies'] 
    # according to the doc, dependencies is a queryset of selected instances
    # so this should work
    if dependencies.filter( name=name).exists():
        form.add_error('dependencies', "You can't add a mapset to its own dependencies")
        return self.form_invalid( form)
    form.save()
    return HttpResponseRedirect( self.get_success_url() )

Если дальнейшая фильтрация набора запросов невозможна, вы можете перебирать объекты, которые он возвращает

     if( any( [name == dep.name for dep in dependencies] )):
         form.add_error( ...

А если вы просто хотите удалить себя из собственных зависимостей, не жалуясь на пользователя

    instance = form.save( commit = false)
    instance.dependencies.remove( instance)
    instance.save()
   

Я никогда не делал этого, так что это основано на моем понимании документации. Дайте нам знать, если это сработает!

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