#javascript #django
Вопрос:
В настоящее время я работаю над сетевым проектом CS50Web 4, и я застрял в редактировании сообщения среди многих отображаемых сообщений.
У меня есть представление, в котором отображаются все сообщения, сделанные пользователем.
def profile(request, username):
if request.method == "GET":
user = User.objects.filter(username=username)
profile = Profile.objects.filter(user=user[0]).get()
posts = Post.objects.filter(user=user[0]).order_by('-publish_date')
return render(
request,
'network/profile.html',
{
'posts': page,
'profile': profile,
}
)
И это отображается в шаблоне и html.
{% for post in posts %}
<div class="card text-center">
<div class="card-header">
<a href="{% url 'profile' post.user %}"> {{ post.user }} </a>
</div>
<div class="card-body">
<h5 class="card-title">{{ post.content }}</h5>
<p class="card-text">{{ post.num_likes }}</p>
<a href="#" class="btn btn-primary" onclick="editpost()"> Edit </a>
</div>
<div class="card-footer text-muted">
{{ post.publish_date }}
</div>
</div>
<br>
{% endfor %}
Я понимаю, что мне нужна функция, которая с помощью JS изменяет <h5>
тег и <p>
тег внутри этой конкретной формы, но я знаю, как получить ее только из этого одного сообщения, а не из всех сообщений, создаваемых механизмом шаблонов Djangos.
Как только я смогу их выбрать, я скопирую их информацию в var и изменю стиль, чтобы отображение было не таким, как при создании, я введу данные из var и позволю пользователю изменять их.
Затем будет создана новая <a>
страница для пользователя, чтобы сохранить изменения. На данный момент я подумываю об использовании Ajax для отправки данных обратно на сервер, но я открыт для предложений, если есть лучший вариант.
Я бы загрузил модель для базы данных, но не думаю, что это необходимо для этого. Мы высоко ценим любую помощь или указания.
Ответ №1:
JavaScript, который вы используете в своем шаблоне, дает подсказки о том, как получить доступ к каждому сообщению для пользователя (ie for post in posts
) и установить значения, которые отображаются в h5
элементе (ie post.content
) и p
элементе (ie post.num_likes
) этого сообщения.
Чтобы обновить все это в представлении, вы должны сделать что-то вроде:
posts = Post.objects.filter(user=user[0]).order_by('-publish_date');
for (let post in posts){
post.content = my_new_content;
post.num_likes = my_new_num_likes;
}
return render( // etc...
Или, если вы хотите оставить базовые значения такими, какие они есть, и обновить только значения DOM (шаблона), вы просто измените код обновления шаблона на:
<h5 class="card-title">{{ my_new_content }}</h5>
<p class="card-text">{{ my_new_num_likes }}</p>
Меня смутила эта часть: «…измените стиль, чтобы отображение было не таким, как при создании, я представлю данные…», но если вы пытаетесь получить доступ к элементам DOM после их визуализации, есть несколько полезных связанных методов, документированных в MDN.
В вашей ситуации, если все карты отображаются на одной странице, вы можете сделать что-то вроде:
const
// Defines an array to hold values found in the DOM
oldCardInfoArray = [],
// Collects references to all card elements on the page
cards = document.getElementsByClassName("card"),
// Converts cards to an array, and gets only those cards whose user matches `post.user`
// (Assumes this code has access to some `post` object with a `user` property)
userCards = (Array.from(cards)).filter(
(card) => card.querySelector("a").textContent.trim() == post.user)
);
// Loops through the userCards
for(let userCard of userCards){
const
// Identifies title and text of each card (as `oldTitle` and `oldText`, respectively)
cardTitleElement = userCard.querySelector(".card-title"),
cardTextElement = userCard.querySelector(".card-text"),
oldTitle = cardTitleElement.textContent,
oldText = cardTextElement.textContent,
// Makes an `oldCardInfo` object with two properties, and adds it to the array
oldCardInfo = { oldTitle: oldTitle, oldText: oldText };
oldCardInfoArray.push(oldCardInfo);
}
// Now the array is populated, and we can do something with its contents
for(let card of oldCardInfoArray){
const oldTitle = card.oldTitle;
const oldText = card.oldText;
// Prints the values from each card to the browser console
// (or you could send them to the server, or whatever)
console.log("title: " oldTitle ", text: " oldText);
}
Очевидно, что весь этот код непроверен, но он должен, по крайней мере, дать вам некоторые идеи.
Редактировать:
В ответ на ваш комментарий, чтобы выбрать карточку, содержащую нажатую кнопку, вы можете просто ввести такой код в свою editPost
функцию:
const card = this.closest(".card");
Так что теперь, вместо того, чтобы перебирать карточки , вы сможете работать только с теми элементами внутри карточки, с которыми взаимодействовал пользователь (что происходит так же, как cardTitleElement
и выше).
Или, в качестве альтернативы, вы можете заменить встроенный обработчик событий ( onclick = editPost()
в шаблоне) на прослушиватель событий, либо 1) внутри <script>
элемента в нижней части шаблона, либо 2) непосредственно в существующем коде JavaScript (хотя я не уверен, какая часть Django обрабатывает этот второй подход). Это может выглядеть примерно так:
document.addEventListener("click", editPost);
function editPost(event){ // Listener sees triggering event
const clickedThing = event.target; // Event has useful properties
const userCard = clickedThing.closest(".card");
if(userCard){ // Makes sure button has a `card` ancestor before proceeding
// Now, with the correct card identified, we can collect values from it
const cardTitleElement = userCard.querySelector(".card-title");
const cardTextElement = userCard.querySelector(".card-text");
// ...etc, as described above
}
}
Комментарии:
1. Итак, я понимаю, о чем вы говорите, но я не понимаю, как он узнает, какой пост я выбрал. Он отображает 10 сообщений на странице. Это не вопрос машинного сообщения с пользователями, это вопрос знания того, какое сообщение пользователь выбрал для редактирования среди списка из 10, которые были созданы механизмом шаблонов Djangos. Как я могу получить свой код для извлечения информации из формы, в которой был нажат Бот?