Как передать идентификатор объекта в представление django при обработке нескольких объектов разных моделей в одном представлении

Я пытаюсь создать веб-приложение с панелью инструментов на главной странице, где пользователь может добавлять сохраненные ссылки, напоминания о заметках и т. д. Я понял, как использовать несколько форм в одном и том же представлении для создания разных объектов модели, но я не могу обновить эти объекты. Что я специально пытаюсь сделать, так это иметь одну форму кнопки, и когда пользователь нажимает на эту кнопку (флажок), статус объекта напоминания изменяется на закрытый. Но я не могу найти способ получить этот идентификатор объекта или что-то еще, чтобы запросить его, на мой взгляд.

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

модели.py

class Reminders(models.Model):
    person_id = models.ForeignKey(Person, related_name = "reminder_about", null=True, blank=True, on_delete=models.CASCADE)
    date = models.DateTimeField(null=True)
    status = models.CharField(max_length=150, null=True, blank=True)
    note = models.CharField(max_length=150, null=True, blank=True)
    user_id = models.ForeignKey(Person, related_name = "reminder_for", null=True, blank=True, on_delete=models.CASCADE)

    class Meta:
        verbose_name = 'Reminder'
        verbose_name_plural = 'Reminders'

    def __str__(self):
        return f"{self.status} {self.note}" 

просмотры.py

@login_required
def index(request):
    current_user = request.user
    person = Person.objects.get(user=current_user)
    scheduled_calls = ScheduledCalls.objects.filter(user_id=person.id).order_by("-date")
    reminders = Reminders.objects.filter(user_id=person.id).order_by("-date")
    notes = Notes.objects.filter(user_id=person.id).order_by("-date")
    links = SavedLinks.objects.filter(user_id = person.id)

    if request.method == "POST":
        call_form = _get_form(request, CallForm, "call_form_pre")
        link_form = _get_form(request, LinkForm, "link_form_pre")
        note_form = _get_form(request, NotesForm, "note_form_pre")
        reminder_form = _get_form(request, RemindersForm, "reminder_form_pre")
        remindercheck_form = _get_form(request, RemindersForm, "remindercheck_form_pre")

        if call_form.is_bound and call_form.is_valid():
            call_form.instance.user_id = person
            call_form.save(commit=False)
            call_form.save()
            return redirect("home")

        if link_form.is_bound and link_form.is_valid():
            link_form.instance.user_id = person
            link_form.save(commit=False)
            link_form.save()
            return redirect("home")
        
        if note_form.is_bound and note_form.is_valid():
            note_form.instance.user_id = person
            note_form.save(commit=False)
            note_form.save()
            return redirect("home")
        
        if reminder_form.is_bound and reminder_form.is_valid():
            reminder_form.instance.user_id = person
            reminder_form.save(commit=False)
            reminder_form.save()
            return redirect("home")
        
        #this is the part im stuck with     
        if remindercheck_form.is_bound:
            note = request.POST("note")
            reminder = Reminders.objects.filter(note=note)
            reminder.update(status = "Closed")
        
    return render(request, "main/home.html", {"person" : person, 
                                              "scheduled_calls" : scheduled_calls, 
                                              "reminders" : reminders, 
                                              "notes" : notes,
                                              "links" : links, 
                                              "call_form" : CallForm(prefix = "call_form_pre"),
                                              "link_form" : LinkForm(prefix = "link_form_pre"),
                                              "note_form" : NotesForm(prefix = "note_form_pre"),
                                              "reminder_form" : RemindersForm(prefix = "reminder_form_pre"),
                                              "remindercheck_form" : RemindersForm(prefix = "remindercheck_form_pre"),
                                              })

HTML

<div id = "tabs" style = "overflow-y:scroll; height:14rem;"> 
            {% if reminders %}
                {% for reminder in reminders %}
                <div class = "d-flex align-items-center p-0 my-1">
                  <form action = "" method = "POST">
                    {% csrf_token %}
                    <div class = "form-check">
                      <input id = "remdone" name = "{{remindercheck_form.prefix}}" class = "form-check-input" type = "checkbox" value = "False">
                      <input class = "form-check-label" style = "border: 0px; background-color: white; color: black;" name = "note"
                                value = "{{reminder.note}}" disabled>
                      <input name = "status" type = "text" class = "form-control" value = "Closed" hidden>
                    </div>
                  </form>
                  <script type='text/javascript'>
                    $(document).ready(function() { 
                      $('input[id=remdone]').change(function(){
                           $('form').submit();
                      });
                     });
                   </script>
                </div>
                {% endfor %}
              {% else %}
              <h5 class = "text-center mt-5">You did a good job! No reminders left!</h5>    
              {% endif %}
          </div>

формы.py

class RemindersForm(forms.ModelForm):
    class Meta:
        model = Reminders
        fields = ("note", "person_id", "status")

        widgets = {
            "person_id" : forms.Select(attrs = {'class': 'form-control'}),
            "note" : forms.TextInput(attrs = {'class': 'form-control'}),
            "status" : forms.TextInput(attrs = {'class': 'form-control'}),
            }

    def __init__(self, *args, **kwargs):
        super(RemindersForm, self).__init__(*args, **kwargs)
        self.fields['person_id'].empty_label = " "
        self.fields['person_id'].queryset = Person.objects.all()

Редактировать

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
81
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Сначала вам следует обратить внимание на файл models.py, в котором вы использовали модель Person, которую я не вижу, но, похоже, это модель, настроенная пользователем.

Вам не нужно добавлять идентификатор для каждого напоминания, поэтому вы можете перекодировать models.py следующим образом:

модели.py

class Reminders(models.Model):
    user = models.ForeignKey(Person, related_name = "reminder_about", null=True, blank=True, on_delete=models.CASCADE)
    date = models.DateTimeField(null=True)
    status = models.CharField(max_length=150, null=True, blank=True)
    note = models.CharField(max_length=150, null=True, blank=True)
    person = models.ForeignKey(Person, related_name = "reminder_for", null=True, blank=True, on_delete=models.CASCADE)

    class Meta:
        verbose_name = 'Reminder'
        verbose_name_plural = 'Reminders'

    def __str__(self):
        return f"{self.status} {self.note}"

затем в вашем файле view.py вам нужно очистить код и использовать пользовательский объект для заполнения внешнего ключа в другой модели.

также, если вы хотите обновить каждую модель в вашем файле views.py, сделайте запрос к базе данных и используйте метод update() следующим образом:

просмотры.py

if note_form.is_bound and note_form.is_valid():
    new_note_set = models.Note.objects.filter(user=request.user).update(person=person)
    new_note_set.save()

для конечной точки обычно разработчики django определяют переменную и называют ее context:

context = {
            ...
            "person" : person, 
            "scheduled_calls" : scheduled_calls, 
            ...
        }

return render(request, 'template.html', context)

Не уверен, правильно ли я понял, если я внесу предложенные изменения во внешний интерфейс, пользователь сможет установить флажок на выбранном элементе (напоминание), и только этот элемент будет обновлен? Я спрашиваю, потому что вы предложили запрашивать пользователя, но все элементы, возвращаемые в цикле for, принадлежат одному и тому же пользователю. Так не будут ли обновлены все предметы?

Satten 30.03.2023 13:41

В файле views.py у вас есть 4 одинаковых условных оператора, поэтому я пишу 1 пример из них, и вы можете использовать его для других условных операторов.

PicoDev 30.03.2023 15:02

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

У меня есть та же проблема, которую я исправляю с помощью этой техники. Таким образом, когда пользователь устанавливает флажок, форма отправляется с идентификатором напоминания, и ваше представление может соответствующим образом обновить объект напоминания. во-первых, вам нужно обновить функцию просмотра с помощью

if remindercheck_form.is_bound:
    reminder_id = request.POST.get("reminder_id") 
    reminder = get_object_or_404(Reminders, id=reminder_id)
    reminder.status = "Closed" 
    reminder.save() 

Вам также необходимо импортировать get_object_or_400 как

from django.shortcuts import get_object_or_404

и в шаблоне html добавьте поле ввода следующим образом

<input type = "hidden" name = "reminder_id" value = "{{ reminder.id }}">

Спасибо! Это именно то, чего я пытался добиться, но одна вещь, которая до сих пор не работает, заключается в том, что когда я пытаюсь «закрыть» свое напоминание, я могу сделать это только из последнего элемента в списке и в этом порядке. Если я попытаюсь «закрыть» первый элемент или средний элемент в списке, он ничего не сделает. Может быть, у вас есть идеи, почему это может происходить?

Satten 30.03.2023 14:00

ответ на ваш вопрос для закрытия напоминания

поскольку я думаю, что вы уже получили напоминание_id, теперь используйте этот напоминание, чтобы удалить/закрыть нужное напоминание. Модифицированный код будет таким

if remindercheck_form.is_bound:
        note = request.POST("note")
        reminder = Reminders.objects.filter(note=note, id=reminder_id)
        reminder.update(status = "Closed")

Я думаю, это будет работать так, как вам нужно

Я попытался проверить, почему он закрывает неправильное напоминание, и заметил, что значение напоминания в html возвращается правильно, но когда я добавил печать в консоль, значение напоминания, переданное для просмотра при нажатии кнопки отправки, отличается от того, что я получаю в html. Не уверен, почему это происходит. Может ли это быть потому, что сама html-форма генерируется в цикле for, а все формы элементов имеют одно и то же имя?

Satten 31.03.2023 09:18
Ответ принят как подходящий

Я нашел более простой способ добиться того, что мне нужно. Поскольку мне не нужно было вводить какие-либо данные от пользователя, я полностью отказался от форм, а для «Флажка» использовал href со ссылкой, которая имеет вид обработки статуса. Представление не имеет только перенаправления рендеринга, поэтому при нажатии я остаюсь на той же странице, что и хотел, но статус элемента фактически изменяется для элемента, по которому щелкнули, поскольку я передаю его идентификатор для просмотра с URL-адреса.

#views.py
def reminder_update(request, reminder_id):
    item = Reminders.objects.get(pk=reminder_id)
    item.status = True
    item.save()
    return redirect("home")
    
#urls.py
path("reminder/<reminder_id>", views.reminder_update, 
name = "reminder_update")
    
#html
{% if reminders %}
    {% for reminder in reminders %}
        <div>
            <a style = "text-decoration: none;" href = "{% url 
'reminder_update' reminder.id %}">
            <img src = "{% static 'images/elements/Checkbox.png' %}"
             alt = ""
             width = "17"
             style = "cursor: pointer; padding-bottom: 0.1rem; margin-right: 
0.5rem;"/>
             </a>
             {{reminder.note}}    
        </div>
    {% endfor %}
{% else %}

Другие вопросы по теме