validate_header_image()   A
last analyzed

Complexity

Conditions 5

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
dl 0
loc 15
rs 9.1832
c 2
b 0
f 0
1
"""
2
Models that extend mezzanine Pages and add JD specific data.
3
"""
4
5
from datetime import datetime
6
import os
7
from string import punctuation
8
import logging
9
10
from PIL import Image
11
12
from django.core.exceptions import ValidationError
13
from django.db import models
14
from django.db.models import Q
15
from django.utils import timezone
16
from django.conf import settings
17
18
from mezzanine.blog.models import BlogCategory, BlogPost
19
from mezzanine.core.fields import FileField
20
from mezzanine.core.fields import RichTextField
21
from mezzanine.core.models import Orderable, RichText, SiteRelated
22
from mezzanine.core.models import CONTENT_STATUS_PUBLISHED
23
from mezzanine.pages.models import Page
24
25
logger = logging.getLogger(__name__)
26
27
28
class FooterLinks(SiteRelated):
29
    title = models.CharField(max_length=100, blank=True, default="")
30
31
    def __str__(self):
32
        return self.title
33
34
35
class FooterLink(SiteRelated, Orderable):
36
    title = models.CharField(max_length=100, blank=True, default="")
37
    url = models.CharField(max_length=500, blank=True, default="")
38
    footer_links = models.ForeignKey(FooterLinks, blank=True, null=True)
39
40
    def __str__(self):
41
        return self.title
42
43
44
class FooterInfo(SiteRelated):
45
    title = models.CharField(max_length=100, blank=True, default="")
46
    content = RichTextField()
47
48
    def __str__(self):
49
        return self.title
50
51
52
class Footer(SiteRelated):
53
    links_left = models.OneToOneField(FooterLinks, auto_created=True, related_name="links_left")
54
    links_middle = models.OneToOneField(FooterLinks, auto_created=True, related_name="links_right")
55
    info_right = models.OneToOneField(FooterInfo, auto_created=True)
56
57
    class Meta:
58
        verbose_name = "Footer"
59
        verbose_name_plural = "Footer"
60
61
62
def validate_header_image(imagepath):
63
    """ Validates the resolution of a header image. """
64
    absolute_imagepath = os.path.join(settings.MEDIA_ROOT, str(imagepath))
65
    if not os.path.exists(absolute_imagepath):
66
        raise ValidationError(
67
            'The file for this header does not exist anymore. Please remove or replace this header before saving the page.')
68
    im = Image.open(absolute_imagepath)
69
    width, height = im.size
70
    aspect_ratio = width/height
71
    if aspect_ratio < 2.0:
72
        raise ValidationError('Image aspect ratio should be at least 2 (for example 2000x1000px). The selected image is %i x %i. Please resize the image.' % (width, height))
73
    if width < 1500:
74
        raise ValidationError('Image resolution is too low. Width should at least be 1500px. The selected image is %i x %i. Please find a larger image.' % (width, height))
75
    if height < 250:
76
        raise ValidationError('Image resolution is too low. Height should at least be 250px. The selected image is %i x %i. Please find a larger image.' % (width, height))
77
78
79
class PageHeaderImage(SiteRelated):
80
    """ Page header image. """
81
    name = models.CharField(max_length=1000, blank=True, null=False, default="")
82
    page = models.ForeignKey(Page, blank=False, null=True)
83
    image = FileField(max_length=200, format="Image", validators=[validate_header_image])
84
85
86
class PageItem(SiteRelated):
87
    page = models.ForeignKey(Page, blank=False, null=True)
88
    visible = models.BooleanField(default=True)
89
90
    class Meta:
91
        abstract = True
92
93
94
class SidebarAgenda(PageItem):
95
    SITE = 'SI'
96
    ALL = 'AL'
97
    MAIN = 'MA'
98
    MAIN_AND_SITE = 'SM'
99
100
    EVENT_CHOICES = (
101
        (SITE, 'Site'),
102
        (ALL, 'All'),
103
        (MAIN, 'Main site'),
104
        (MAIN_AND_SITE, 'Main and site'),
105
    )
106
107
    type = models.CharField(max_length=2, choices=EVENT_CHOICES)
108
109
    class Meta:
110
        verbose_name = "Sidebar Agenda Item"
111
112
    def get_name(self):
113
        if self.type == self.MAIN_AND_SITE:
114
            return 'Events for current and main site'
115
        elif self.type == self.ALL:
116
            return 'Events for all sites'
117
        elif self.type == self.SITE:
118
            return 'Events for current site'
119
        elif self.type == self.MAIN:
120
            return 'Events for main site'
121
        assert False
122
123
    def __str__(self):
124
        return self.get_name()
125
126
127
class SidebarTwitter(PageItem):
128
129
    class Meta:
130
        verbose_name = "Sidebar Twitter Item"
131
132
133
class SidebarSocial(PageItem):
134
135
    @property
136
    def urls(self):
137
        smulrs = SocialMediaUrls.objects.all()
138
        if smulrs.exists():
139
            return smulrs[0]
140
        return None
141
142
    class Meta:
143
        verbose_name = "Sidebar Social Media Item"
144
145
146
class SidebarRichText(PageItem):
147
    title = models.CharField(max_length=100, blank=True, default="")
148
    content = RichTextField()
149
150
    class Meta:
151
        verbose_name = "Sidebar RichText Item"
152
153
    def __str__(self):
154
        return self.title
155
156
157
class SidebarLink(PageItem, Orderable):
158
    title = models.CharField(max_length=100, blank=True, default="")
159
    url = models.CharField(max_length=500, blank=True, default="")
160
161
162
class ActionBanner(PageItem):
163
    title = models.CharField(max_length=500, blank=True, default="")
164
    content = RichTextField()
165
    image = FileField(max_length=300, format="Image")
166
    button_title = models.CharField(max_length=500, blank=True, default="")
167
    button_url = models.CharField(max_length=500, blank=True, default="")
168
169
    def __str__(self):
170
        return self.title
171
172
173
def validate_images_aspect_ratio(imagepath, required_aspect_ratio, max_difference):
174
    """ Validates the aspect ratio of an image. """
175
    absolute_imagepath = os.path.join(settings.MEDIA_ROOT, str(imagepath))
176
    im = Image.open(absolute_imagepath)
177
    width, height = im.size
178
    aspect_ratio = width/height
179
    if abs(aspect_ratio - required_aspect_ratio) > max_difference:
180
        raise ValidationError('Image aspect ratio should be %i, selected image is %i x %i. Please resize the image.' % (required_aspect_ratio, width, height))
181
182
183
def validate_vision_image(imagepath):
184
    validate_images_aspect_ratio(imagepath, required_aspect_ratio=1.5, max_difference=0.1)
185
186
187
class VisionPage(Page, RichText):
188
    """
189
    """
190
    image = FileField(max_length=300, format="Image", blank=True, default="", validators=[validate_vision_image])
191
192
    class Meta:
193
        verbose_name = 'Standpunt pagina'
194
        verbose_name_plural = "Standpunt pagina's"
195
196
197
class VisionsPage(Page, RichText):
198
    """
199
    """
200
    vision_pages = models.ManyToManyField(VisionPage, blank=True, verbose_name="Standpunt pagina's")
201
202
    class Meta:
203
        verbose_name = 'Standpunten pagina'
204
        verbose_name_plural = "Standpunten pagina's"
205
206
207
def validate_organisation_image(imagepath):
208
    validate_images_aspect_ratio(imagepath, required_aspect_ratio=1.5, max_difference=0.1)
209
210
211
class OrganisationPartPage(Page, RichText):
212
    """
213
    """
214
    image = FileField(max_length=300, format="Image", blank=True, default="", validators=[validate_organisation_image])
215
216
    class Meta:
217
        verbose_name = 'Organisatie-onderdeel pagina'
218
        verbose_name_plural = "Organisatie-onderdeel pagina's"
219
220
221
class OrganisationPage(Page, RichText):
222
    """
223
    """
224
    organisation_part_pages = models.ManyToManyField(OrganisationPartPage, blank=True, verbose_name="Organisatie onderdelen")
225
226
    class Meta:
227
        verbose_name = 'Organisatie pagina'
228
        verbose_name_plural = "Organisatie pagina's"
229
230
231 View Code Duplication
class OrganisationMember(SiteRelated):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
232
    """
233
    """
234
    name = models.CharField(max_length=200, blank=False, default="")
235
    content = RichTextField(blank=True, default="")
236
    image = FileField(max_length=300, format="Image", blank=True, default="")
237
    email = models.EmailField(blank=True, default="")
238
    facebook_url = models.URLField(blank=True, default="")
239
    twitter_url = models.URLField(blank=True, default="")
240
241
    class Meta:
242
        verbose_name = 'Organisatie lid'
243
        verbose_name_plural = "Organisatie leden"
244
245
    def __str__(self):
246
        return self.name
247
248
249
class OrganisationPartMember(SiteRelated):
250
    member = models.ForeignKey(OrganisationMember)
251
    organisation_part = models.ForeignKey(OrganisationPartPage, null=True, blank=True)
252
    role = models.CharField(max_length=200, blank=True, default="")
253
254
    class Meta:
255
        verbose_name = 'Organisatie functie'
256
        verbose_name_plural = "Organisatie functies"
257
258
    def __str__(self):
259
        return self.role + ' - ' + self.member.name
260
261
262
class HomePage(Page, RichText):
263
    """
264
    Page model for the site homepage.
265
    Only works properly when url points to the homepage '/' as url.
266
    """
267
    header_title = models.CharField(max_length=300, blank=True, default="")
268
    header_subtitle = models.CharField(max_length=500, blank=True, default="")
269
    news_category = models.ForeignKey(BlogCategory, null=True, blank=True)
270
    vision_pages = models.ManyToManyField(VisionPage, blank=True, verbose_name="Standpunt pagina's")
271
272
    @property
273
    def blog_posts(self):
274
        return get_public_blogposts(self.news_category)[:4]
275
276
    class Meta:
277
        verbose_name = 'Home pagina'
278
        verbose_name_plural = "Home pagina's"
279
280
281
class BlogCategoryPage(Page, RichText):
282
    """
283
    Model for a page that displays a list of posts in a single blog category.
284
    """
285
286
    blog_category = models.ForeignKey(BlogCategory, null=False, blank=False)
287
    show_excerpt = models.BooleanField(default=False, null=False, blank=False,
288
                                       help_text='Show only the first paragraph of a blog post.')
289
290
    class Meta:
291
        verbose_name = "Blog categorie pagina"
292
        verbose_name_plural = "Blog categorie pagina's"
293
294
295
def get_public_blogposts(blog_category):
296
    """ Returns all blogposts for a given category that are published and not expired. """
297
    blog_posts = BlogPost.objects.all().filter(categories=blog_category).filter(status=CONTENT_STATUS_PUBLISHED)
298
    return blog_posts.filter(publish_date__lte=timezone.now()).filter(Q(expiry_date__isnull=True)
299
                                                                      | Q(expiry_date__gte=timezone.now()))
300
301
302 View Code Duplication
class SocialMediaUrls(SiteRelated):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
303
    facebook_url = models.URLField(max_length=300, blank=True, default="")
304
    twitter_url = models.URLField(max_length=300, blank=True, default="")
305
    youtube_url = models.URLField(max_length=300, blank=True, default="")
306
    linkedin_url = models.URLField(max_length=300, blank=True, default="")
307
    instagram_url = models.URLField(max_length=300, blank=True, default="")
308
309
    class Meta:
310
        verbose_name = "Social media urls"
311
        verbose_name_plural = "Social media urls"
312
313
314
class WordLidPage(Page, RichText):
315
    """
316
    """
317
318
    class Meta:
319
        verbose_name = 'Word lid pagina'
320
        verbose_name_plural = "Standpunt pagina's"
321
322
323
class ThatsWhyItem(PageItem, Orderable):
324
    title = models.CharField(max_length=100, blank=True, default="")
325
326
    class Meta:
327
        verbose_name = "That's why item"
328
        verbose_name_plural = "That's why items"
329
330
    def __str__(self):
331
        return self.title
332
333