处理同一视图中的多个不同模型对象时如何将对象 ID 传递给 Django 视图

问题描述 投票:0回答:4

我正在尝试制作在主页上有仪表板的网络应用程序,用户可以在其中添加保存的链接、注释提醒等。我想出了如何在同一视图中使用多个表单来创建不同的模型对象,但我无法更新那些对象。我特别想做的是拥有一个按钮表单,当用户单击该按钮(复选框)时,提醒对象状态更改为关闭。但是在我看来,我找不到获取该对象 ID 或任何查询它的方法。

我是 Django 框架的新手,这可能很明显,但我找不到任何对我有帮助的信息,我尝试了很多变体来实现这一点,但到目前为止没有任何效果。

models.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}" 

views.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>

forms.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()

编辑

为了更清楚地添加它在前端的外观。当用户单击复选框时,数据库中的项目状态应更改为已关闭,并且项目应从列表中消失。

django django-views django-templates django-queryset
4个回答
1
投票

我想出了一个更简单的方法来实现我所需要的。因为我不需要用户的任何输入,所以我完全放弃了表单,对于“复选框”,使用带有状态处理视图的链接的 href。 View 没有只渲染重定向,所以点击后我停留在我想要的同一页面上,但项目状态实际上改变了点击项目,因为我传递了它的 ID 以从 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 %}

1
投票

您可以通过将提醒 id 作为表单中的隐藏输入字段包含在表单中来解决此问题。然后,在您的视图中,您可以根据 id 检索提醒对象并更新其状态。

我确实有同样的问题,之前我使用这种技术修复过。这样,当用户单击该复选框时,将提交带有提醒 id 的表单,并且您的视图可以相应地更新提醒对象。 首先你需要更新你的视图函数

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 }}">

0
投票

首先你要注意models.py文件,你用的是Person模型,我看不到,但它似乎是一个用户定制的模型。

您不需要为每个提醒添加 id,因此您可以像这样重新编码 models.py:

models.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()
方法:

views.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)

0
投票

回答你关闭提醒的问题

因为我认为您已经获得了 reminder_id 现在使用此 reminder_id 删除/关闭适当的提醒。修改后的代码会是这样

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

我认为这会按你的需要工作

© www.soinside.com 2019 - 2024. All rights reserved.