Изменение одного из многих постов с помощью JS и Django?

#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. Как я могу получить свой код для извлечения информации из формы, в которой был нажат Бот?