articles.py 6.75 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


Okhin's avatar
Okhin committed
141
class ArticleEdit(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
142
    model = Article
143
    permission_required = 'rp.can_edit'
Okhin's avatar
Okhin committed
144
    raise_exception = True
145

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

150
151
152
153
154
155
156
    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()
157
158
        elif 'fetch_metadata' in self.request.GET:
            self.object.fetch_metadata()
159
160
161
162

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

163
164
165
166
167
    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
168
169
        elif "view" in self.request.POST:
            self.success_url = reverse("rp:article-view", args=[self.object.id])
170
        elif "publish" in self.request.POST:
171
            self.object.publish()
172
            self.object.save()
173
174
175
176
177
178
179
180
181
182

        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
183
184
        # Change the layout of the tags field
        form.fields["tags"] = TagMultipleChoiceField(
185
            queryset=Tag.objects.all(), required=False)
cynddl's avatar
cynddl committed
186

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