Я пытаюсь создать веб-приложение с панелью инструментов на главной странице, где пользователь может добавлять сохраненные ссылки, напоминания о заметках и т. д. Я понял, как использовать несколько форм в одном и том же представлении для создания разных объектов модели, но я не могу обновить эти объекты. Что я специально пытаюсь сделать, так это иметь одну форму кнопки, и когда пользователь нажимает на эту кнопку (флажок), статус объекта напоминания изменяется на закрытый. Но я не могу найти способ получить этот идентификатор объекта или что-то еще, чтобы запросить его, на мой взгляд.
Я очень новичок в среде 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()
Редактировать
Для большей ясности добавил, как это выглядит в интерфейсе. Когда пользователь щелкает флажок, статус элемента в базе данных должен измениться на закрытый, а элемент должен исчезнуть из списка.
Сначала вам следует обратить внимание на файл 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)
В файле views.py у вас есть 4 одинаковых условных оператора, поэтому я пишу 1 пример из них, и вы можете использовать его для других условных операторов.
Вы можете решить эту проблему, передав идентификатор напоминания в форму, включив его в качестве скрытого поля ввода в форму. Затем, по вашему мнению, вы можете получить объект напоминания на основе идентификатора и обновить его статус.
У меня есть та же проблема, которую я исправляю с помощью этой техники. Таким образом, когда пользователь устанавливает флажок, форма отправляется с идентификатором напоминания, и ваше представление может соответствующим образом обновить объект напоминания. во-первых, вам нужно обновить функцию просмотра с помощью
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 }}">
Спасибо! Это именно то, чего я пытался добиться, но одна вещь, которая до сих пор не работает, заключается в том, что когда я пытаюсь «закрыть» свое напоминание, я могу сделать это только из последнего элемента в списке и в этом порядке. Если я попытаюсь «закрыть» первый элемент или средний элемент в списке, он ничего не сделает. Может быть, у вас есть идеи, почему это может происходить?
ответ на ваш вопрос для закрытия напоминания
поскольку я думаю, что вы уже получили напоминание_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, а все формы элементов имеют одно и то же имя?
Я нашел более простой способ добиться того, что мне нужно. Поскольку мне не нужно было вводить какие-либо данные от пользователя, я полностью отказался от форм, а для «Флажка» использовал 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 %}
Не уверен, правильно ли я понял, если я внесу предложенные изменения во внешний интерфейс, пользователь сможет установить флажок на выбранном элементе (напоминание), и только этот элемент будет обновлен? Я спрашиваю, потому что вы предложили запрашивать пользователя, но все элементы, возвращаемые в цикле for, принадлежат одному и тому же пользователю. Так не будут ли обновлены все предметы?