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()
Я никогда не делал этого, так что это основано на моем понимании документации. Дайте нам знать, если это сработает!