articles.py 6.7 KB
Newer Older
1
2
from django.http import HttpResponseRedirect
from django.views.generic.detail import DetailView
3
from django.views.generic.list import ListView
4
from django.views.generic.edit import UpdateView
5
from django.utils.translation import ugettext_lazy as _
cynddl's avatar
cynddl committed
6
from django.urls import reverse, reverse_lazy
cynddl's avatar
cynddl committed
7
from django.db.models import Count
Thibaut Broggi's avatar
Thibaut Broggi committed
8
from django.db.models import Q
9
10
from django import forms

11
12
from django.contrib.auth.mixins import (LoginRequiredMixin,
                                        PermissionRequiredMixin)
13

14
from crispy_forms.helper import FormHelper
cynddl's avatar
cynddl committed
15
from crispy_forms.layout import Layout, Field, Div, HTML
16
17
from crispy_forms.bootstrap import AppendedText

cynddl's avatar
cynddl committed
18
19
from taggit.models import Tag
from rp.forms import TagMultipleChoiceField
20

luxcem's avatar
luxcem committed
21
22
23
from rp.models import Article


24
25
26
27
28
29
class ArticleFilterMixin:
    """
    This mixin allows to filter views using various parameters in the query
    string.
    """
    archive = 'both'
30
31
    quote = 'both'
    speak = 'both'
cynddl's avatar
cynddl committed
32

33
    def get_queryset(self):
34
        qs = super().get_queryset()
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
        # Tags filtering
        self.quote = self.request.GET.get('quote', self.quote)
        self.speak = self.request.GET.get('speak', self.speak)
        self.archive = self.request.GET.get('archive', self.archive)

        if self.speak != 'both':
            if self.speak == 'true':
                qs = qs.filter(speak=True)
            else:
                qs = qs.filter(speak=False)

        if self.quote != 'both':
            if self.quote == 'true':
                qs = qs.filter(quote=True)
            else:
                qs = qs.filter(quote=False)

        if self.archive != 'both':
            if self.archive == 'true':
                qs = qs.filter(archive=True)
            else:
                qs = qs.filter(archive=False)

Thibaut Broggi's avatar
Thibaut Broggi committed
58
59
60
61
        search_keywords = self.request.GET.get('q', '')
        if search_keywords != '':
            qs = qs.filter(Q(title__icontains=search_keywords)
                           | Q(extracts__icontains=search_keywords))
Thibaut Broggi's avatar
Thibaut Broggi committed
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
        return qs

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context["search"] = self.request.GET.get('q', '')
        context["archive"] = self.request.GET.get('archive', self.archive)
        context["speak"] = self.request.GET.get('speak', self.speak)
        context["quote"] = self.request.GET.get('quote', self.quote)

        return context


class ArticleList(ArticleFilterMixin, ListView):
    model = Article
    paginate_by = 10
    template_name = "rp/article_list_public.html"
    filter_lang = None
    filter_tag = None
    archive = 'false'  # We do not want to display archived items by default

    def get_queryset(self):
        qs = super().get_queryset()

        if self.filter_lang in ["EN", "FR"]:
            qs = qs.filter(lang=self.filter_lang)
        else:
            qs = qs.filter()

cynddl's avatar
cynddl committed
92
93
94
95
        filter_tag = self.kwargs.get("filter_tag", self.filter_tag)
        if filter_tag is not None:
            qs = qs.filter(tags__name__in=[filter_tag])

96
        return qs.order_by('-created_at')
cynddl's avatar
cynddl committed
97
98
99
100

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

101
102
        qs = Tag.objects.annotate(
                num_times=Count('taggit_taggeditem_items')).all()
cynddl's avatar
cynddl committed
103
104
105
106
        qs = qs.order_by('-num_times')
        context["tags"] = qs

        return context
107
108


109
class ArticleListFlux(LoginRequiredMixin, ArticleFilterMixin, ListView):
luxcem's avatar
luxcem committed
110
    model = Article
cynddl's avatar
cynddl committed
111
112
113
114
    paginate_by = 10

    def get_queryset(self):
        filter_view = self.kwargs.get("filter_view", "draft")
115
        qs = super().get_queryset()
cynddl's avatar
cynddl committed
116

117
        if filter_view in ["published", "draft", "rejected"]:
118
            qs = qs.filter(status=filter_view.upper())
cynddl's avatar
cynddl committed
119
        else:
120
            qs = qs.filter(status="NEW")
cynddl's avatar
cynddl committed
121
122
123
124
125
126

        return qs.order_by('-created_at')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["filter_view"] = self.kwargs.get("filter_view", "draft")
127
        context["nb_draft"] = Article.objects.filter(status="DRAFT").count()
cynddl's avatar
cynddl committed
128
        return context
129
130


131
class ArticleDetailView(LoginRequiredMixin, DetailView):
132
133
134
135
136
137
138
139
140
    model = Article
    preview = False

    def get_context_data(self, **kwargs):
        context = super(ArticleDetailView, self).get_context_data(**kwargs)
        context['is_preview'] = self.preview
        return context


141
class ArticleEdit(PermissionRequiredMixin, UpdateView):
142
    model = Article
143
    permission_required = 'rp.can_edit'
144

145
146
    fields = ['screenshot', 'url', 'lang', 'title', 'tags', 'extracts',
              'quote', 'speak', 'archive']
cynddl's avatar
cynddl committed
147
    success_url = reverse_lazy("rp:article-list")
148

149
150
151
152
153
154
155
    def get(self, request, **kwargs):
        self.object = self.get_object()

        if 'fetch_content' in self.request.GET:
            self.object.fetch_content()
        elif 'fetch_image' in self.request.GET:
            self.object.fetch_image()
156
157
        elif 'fetch_metadata' in self.request.GET:
            self.object.fetch_metadata()
158
159
160
161

        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

162
163
164
165
166
    def form_valid(self, form):
        self.object = form.save()

        if "preview" in self.request.POST:
            self.success_url = reverse("rp:article-preview", args=[self.object.id])
cynddl's avatar
cynddl committed
167
168
        elif "view" in self.request.POST:
            self.success_url = reverse("rp:article-view", args=[self.object.id])
169
        elif "publish" in self.request.POST:
170
            self.object.publish()
171
            self.object.save()
172
173
174
175
176
177
178
179
180
181

        return HttpResponseRedirect(self.get_success_url())

    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        form.fields["screenshot"].widget = forms.widgets.FileInput()

        form.helper = FormHelper()
        form.helper.form_tag = False

cynddl's avatar
cynddl committed
182
183
        # Change the layout of the tags field
        form.fields["tags"] = TagMultipleChoiceField(
184
            queryset=Tag.objects.all(), required=False)
cynddl's avatar
cynddl committed
185

186
187
188
189
190
        left_layout = Div(
            Div(
                Field('title', wrapper_class='col-sm-10'),
                Field('lang', wrapper_class='col-sm-2'),
                css_class="row"),
191
192
193
            AppendedText(
                'url',
                _('<a href="%s">Go to link</a>') % form.initial['url']),
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
            'tags',
            'extracts',
            css_class="col-sm-8")

        right_layout = Div(
            'screenshot',
            HTML(
                """
                {% if form.screenshot.value %}
                <img class="img-responsive mb-4"
                     src="/media/{{ form.screenshot.value }}">
                {% endif %}
                """
            ),
            css_class="col-sm-4")

        form.helper.layout = Layout(
            Div(left_layout, right_layout, css_class="row"))

        return form