Как сохранить отношения ManyToMany из ModelForm в Django - PullRequest
2 голосов
/ 04 мая 2011

Я не уверен, чтобы сохранить мои отношения ManyToMany. Я нашел свою точную проблему в этой теме: В Django встроена форма ManyToMany , за исключением того, что вместо моделей Sales и Products у меня есть модели, из которых состоит фильм.

Я попробовал решение, но получил синтаксическую ошибку. Я не понимаю, как Django должен связать EquipmentModel, LightModel и ActorModel с отношением ManyToMany в MovieModel. До сих пор (до того, как попробовать решение другого потока), CharFields, отображаемые в форме для LightModel, EquipmentModel и ActorModel, не связаны с ManyToManyField в MovieModel. Поэтому, когда я сохраняю формы и пытаюсь получить доступ к актерам определенного фильма, я вижу только пустой список. Решение из другого потока, кажется, имеет смысл, так как оно пытается связать модели с отношением ManyToMany в MovieModel, но я не понимаю, откуда Django знает, к какой MovieModel добавить (как он получает правильный идентификатор фильма?).

В примечании, есть ли способ проверить дубликаты фильмов, когда пользователь нажимает кнопку «Отправить» в форме? Я хочу избегать создания дубликатов.

views.py:

def add_movie(request, movieID=""):

    if request.method == "POST":
            form = MovieModelForm(request.POST)
            eform = EquipmentModelForm(request.POST)
            lform = LightModelForm(request.POST)
            aform = ActorModelForm(request.POST)

            print 'checking form'
            print request.POST.items()
            if form.is_valid() and eform.is_valid() and lform.is_valid() and aform.is_valid():
                    print 'form is valid'
                    movie_to_add = form.save()
                    e = eform.save()
                    l = lform.save()
                    a = aform.save()
                    movie_to_add.actors.add(a)
                    movie_to_add.lights.add(l)
                    movie_to_add.equipments.add(e)

            #       return HttpResponseRedirect('/data')
    else:
           # code for create forms ....


    return render_to_response('add_movie.html', {'form':form, 'eform':eform,'lform':lform, 'aform':aform,}, context_instance=RequestContext(request))

Другой код, который может помочь:

forms.py

class LightModelForm(forms.ModelForm):
    class Meta:
            model = LightModel

class ActorModelForm(forms.ModelForm):
    class Meta:
            model = ActorModel

class EquipmentModelForm(forms.ModelForm):
    class Meta:
            model = EquipmentModel

class MovieModelForm(forms.ModelForm):

    class Meta:
            model = MovieModel
            fields = ("title", "rank")

models.py

class EquipmentModel(models.Model):
    equip = models.CharField(max_length=20)

class ActorModel(models.Model):
    actor = models.CharField(max_length=20)

class LightModel(models.Model):
    light = models.CharField(max_length=20)

class MovieModel(models.Model):
    rank = models.DecimalField(max_digits=5000, decimal_places=3)
    title = models.CharField(max_length=20)

    equipments = models.ManyToManyField(EquipmentModel, blank=True, null=True)
    actors = models.ManyToManyField(ActorModel, blank=True, null=True)
    lights = models.ManyToManyField(LightModel, blank=True, null=True)

    def __str__(self):
            return self.title

Редактировать: удалены ненужные init и поля благодаря DTing

Edit2: исправлено!

Ответы [ 2 ]

2 голосов
/ 04 мая 2011

Здесь много чего не так, в дополнение к тому, что сказал spulec.

Ваш models.py выглядит хорошо.

class EquipmentModel(models.Model):
    equip = models.CharField(max_length=20)

class ActorModel(models.Model):
    actor = models.CharField(max_length=20)

class LightModel(models.Model):
    light = models.CharField(max_length=20)

class MovieModel(models.Model):
    rank = models.DecimalField(max_digits=5000, decimal_places=3)
    title = models.CharField(max_length=20)

    equipments = models.ManyToManyField(EquipmentModel, blank=True, null=True)
    actors = models.ManyToManyField(ActorModel, blank=True, null=True)
    lights = models.ManyToManyField(LightModel, blank=True, null=True)

    def __str__(self):
            return self.title

Вам не нужно переопределять__init__ метод в формах, если вы ничего не меняете в init.Вам также не нужно явно указывать поля, если вы хотите включить их все.

class LightModelForm(forms.ModelForm):
    class Meta:
            model = LightModel

class ActorModelForm(forms.ModelForm):
    class Meta:
            model = ActorModel

class EquipmentModelForm(forms.ModelForm):
    class Meta:
            model = EquipmentModel

class MovieModelForm(forms.ModelForm):
    class Meta:
            model = MovieModel
            fields = ("title", "rank")

ваше представление не имеет смысла, если только для каждого фильма, который вы пытаетесь добавить, вы также хотите добавить:

  1. добавить новый фильм в БД, используя отправленные данные поста
  2. создать один объект актера и добавить в БД
  3. создать один объект света и добавить в БД
  4. создайте один объект экипировки и добавьте к БД
  5. , возьмите эти три объекта и добавьте их к отношениям m2m другого фильма.
    • Этот другой фильм - это какой-то фильм, который вы извлекли из urlconf и передали на просмотр, а не тот, который вы только что создали.

Все это кажется немного странным.

Я думаю, вы хотите создать все оборудование, актеров и объекты освещения, чтобы они были в вашемдБ уже, и используйте виджет m2m формы по умолчанию, чтобы выбрать их при добавлении фильма.

так:

forms.py

class MovieModelForm(forms.ModelForm):
    class Meta:
        model = MovieModel

urls.py:

url(r'^add_movie/$', add_movie)

views.py:

def add_movie(request):
    if request.method=='POST':
        form = MovieModelForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponse('success')
    else:
        form = MovieModelForm()

    context = {'form':form }

    return render_to_response('some_template.html', context,context_instance=RequestContext(request))

Вы можете объединить добавление актеров, источников света и оборудования в одну и ту же форму, но для меня это слишком много, чтобы написать прямо сейчас.

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

        if form.is_valid() and eform.is_valid() and lform.is_valid() and aform.is_valid():
                new_movie = form.save()
                e = eform.save()
                l = lform.save()
                a = aform.save()
                new_movie.actors.add(a)
                new_movie.lights.add(l)
                new_movie.equipments.add(e)
0 голосов
/ 04 мая 2011

Измените его на:

movie_to_add = get_object_or_404(MovieModel, id=movieID)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...