Я хотел бы манипулировать данными из представлений в / render (html) в Django - PullRequest
0 голосов
/ 25 мая 2020

У меня есть это представление с использованием generi c в django, и мне нужно манипулировать им. Но кажется, что всякий раз, когда я пытался использовать setattr , он не манипулирует / не заменяет данные в queryset .

view.py

class ArticleListView(ListView): #using the Generic ListView in django
    template_name = 'article/article_list_view.html'
    queryset = Article.objects.all()[:5]

    def get(self, request, *args, **kwargs):
        setattr(self.queryset[0], 'title', 'something') #Trying to change the title in the first element
        print(getattr(self.queryset[0], 'title')) #it outputs the old value
        return super().get(request, *args, **kwargs)

article_list_view. html

{% extends 'base.html' %}

{% block content %}
{% for instance in object_list %}
    <h5>{{instance.title}}</h5>
    {% autoescape off %}                                                                                                                                                                                                                      
        <p>{{instance.content| capfirst}}</p>
    {% endautoescape %}
{% endfor %}
{% endblock content %}

Есть идеи, как решить эту проблему? Или, может быть, потому, что он был неизменным?

1 Ответ

1 голос
/ 26 мая 2020

Это проблема, потому что, согласно документации Django по набору запросов , «QuerySet может быть сконструирован, отфильтрован, нарезан и, как правило, передан, не затрагивая базу данных». Первое, что мы с вами попробовали, это захватить первый объект из набора запросов и установить атрибут. Это не помогает, потому что сам набор запросов не оценивается, пока вы не выполните итерацию по нему: {% for instance in object_list %}. Когда это произойдет, экземпляр модели будет снова извлечен из базы данных.

Лучшее решение, которое я вижу, - это принудительная оценка набора запросов перед обновлением экземпляра модели.

class ArticleListView(ListView):
    template_name = 'article/article_list_view.html'
    queryset = Article.objects.all()[:5]

    def get_context_data(self, *, object_list=None, **kwargs):
        # Overwriting this method to receive exactly the same arguments as the original
        # https://github.com/django/django/blob/3.0.6/django/views/generic/list.py#L113
        if object_list is None:
            object_list = self.object_list

        if not isinstance(object_list, tuple):  # Force the queryset into a tuple so it's evaluated
            object_list = tuple(object_list)

        object_list[0].title = 'something'  # Update the instance's title
        return super().get_context_data(object_list=object_list, **kwargs)

Это имеет обратную сторону: article_list не будет доступен в контексте, если вы явно не установите context_object_name = 'article_list' в своем представлении, но вы уже не использовали эту переменную.

Я тестировал некоторые части этот код, чтобы убедиться, что моя теория верна, но я не запускал код целиком, поэтому вам, возможно, придется немного подправить, чтобы заставить его работать именно так, как вы этого хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...