Как создать django форму или страницу добавления / редактирования формы для редактирования нескольких записей - PullRequest
0 голосов
/ 12 апреля 2020

Для одного из моих проектов с открытым исходным кодом мне нужно создать ОДНУ страницу добавления / редактирования, чтобы можно было редактировать несколько записей одним сохранением.

Репо - это клон IMDB, созданный для целей обучения. Пользователь может добавить свои любимые жанры в свой профиль. Затем формируется страница редактирования для отображения списка этих избранных жанров и фильмов в этом жанре. (A для l oop здесь) Пользователь может добавлять к этим фильмам заметки, параметры списка просмотра и т. Д. (НЕ ФОРМАТ)

Однако код не работает должным образом. Страница не может быть сохранена и может быть изменен только первый флажок списка.

Нет ошибок.

ПРИМЕЧАНИЕ:

# users/templates/user-movies-with_loop.html

{% extends 'base.html' %}{% load crispy_forms_tags %}
<!-- Title -->
{% block htitle %}Your movies from favorite genres{% endblock %}
{% block title %}Your movies from favorite genres{% endblock %}

{% block content %}
<div class="card card-signin">
  {% include 'users/profile-menu.html' %}
  <h3 class="card-title text-center my-4">Take notes for your movies <small></small></h3>
  <hr class="mb-1">
  <div class="card-body">
    <form method="POST">
      {% csrf_token %}
      {% for genre in user.genres.all %}
        <h2 for="genre" name="genre" value="{{ genre.id }}">{{ genre.name }}</h2>
        {% for movie in genre.movies.all %}
          <div class="ml-5">
            <h4>{{ movie.title }}</h4>
            {{ form|crispy }}  
          </div>      
          <input type="hidden" name="user" value="{{ user.id }}">
          <input type="hidden" name="movie" value="{{ movie.id }}">

        {% empty %}
        <p class="alert alert-danger">The genre you have selected on your profile doesn't have any movies!</p>
        {% endfor %}  
      {% empty %}

      <p class="alert alert-danger">You should select genres with movies from your profile to edit here!</p>
      {% endfor %}

      <input class="btn btn-lg btn-primary btn-block text-uppercase" type="submit" value="Submit">  
    </form>
  </div>
</div>
{% endblock %}
# users.forms.py
...
class UserMovieFormWithLoop(ModelForm):
    genre = forms.HiddenInput(attrs={'disabled': True})
    class Meta:
        model = UserMovie
        fields = ('user', 'movie', 'note', 'watched', 'watch_list')
        widgets = {
            'user': forms.HiddenInput,
            'movie': forms.HiddenInput,
            'watched': forms.CheckboxInput(),
        }
...     
# users.models.py
...
class UserMovie(models.Model):
    """
        Users have notes about their favorite movies.
    """
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    movie = models.ForeignKey('movies.Movie', default=1, on_delete=models.CASCADE)
    note = models.CharField(max_length=250, null=True, blank=True)
    watched = models.BooleanField(default=False, verbose_name='Have you seen before?')
    watch_list = models.BooleanField(default=False, verbose_name='Add to Watch List?')

    def __str__(self):
        return f'{self.user.username} ({self.movie.title})'
...     
# users.views.py
...
class UserMovieViewWithLoop(LoginRequiredMixin, CreateView):
    model = UserMovie
    template_name = 'users/user-movies-with_loop.html'
    form_class = UserMovieFormWithLoop
    success_message = 'your form has been submitted.'
    success_url = reverse_lazy('users:user_movies2')

    def form_valid(self, form):
        user = self.request.user
        movie_counter = Movie.objects.filter(genres__in=user.genres.all()).count()
        f = form.save(commit=False)
        f.user = user
        for i in range(movie_counter):
            f.pk = None
            f.save()
        return super().form_valid(form)

    def get_context_data(self, **kwargs):      
        context = super(UserMovieViewWithLoop, self).get_context_data(**kwargs)
        context['form'] = self.form_class
        return context

    def get_object(self):
        user = self.request.user
        return UserMovie.objects.get(user=user)
...
...