Completed
Pull Request — master (#155)
by Bart
27s
created

FooterLink   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 7
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 1
c 1
b 0
f 0
dl 0
loc 7
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
A __str__() 0 2 1
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
logger = logging.getLogger(__name__)
10
11
from PIL import Image
12
13
from django.contrib.contenttypes.fields import GenericForeignKey
14
from django.contrib.contenttypes.models import ContentType
15
from django.core.exceptions import ValidationError
16
from django.db import models
17
from django.db.models import Q
18
from django.utils.translation import ugettext_lazy as _
19
from django.utils.encoding import force_text
20
from django.utils import timezone
21
from django.conf import settings
22
23
from mezzanine.blog.models import BlogCategory, BlogPost
24
from mezzanine.core.fields import FileField
25
from mezzanine.core.fields import RichTextField
26
from mezzanine.core.models import Orderable, RichText, SiteRelated
27
from mezzanine.core.models import CONTENT_STATUS_PUBLISHED
28
from mezzanine.pages.models import Page
29
30
31
class FooterLinks(SiteRelated):
32
    title = models.CharField(max_length=100, blank=True, default="")
33
34
    def __str__(self):
35
        return self.title
36
37
38
class FooterLink(SiteRelated, Orderable):
39
    title = models.CharField(max_length=100, blank=True, default="")
40
    url = models.CharField(max_length=500, blank=True, default="")
41
    footer_links = models.ForeignKey(FooterLinks, blank=True, null=True)
42
43
    def __str__(self):
44
        return self.title
45
46
47
class FooterInfo(SiteRelated):
48
    title = models.CharField(max_length=100, blank=True, default="")
49
    content = RichTextField()
50
51
    def __str__(self):
52
        return self.title
53
54
55
class Footer(SiteRelated):
56
    links_left = models.OneToOneField(FooterLinks, auto_created=True, related_name="links_left")
57
    links_middle = models.OneToOneField(FooterLinks, auto_created=True, related_name="links_right")
58
    info_right = models.OneToOneField(FooterInfo, auto_created=True)
59
60
    class Meta:
61
        verbose_name = "Footer"
62
        verbose_name_plural = "Footer"
63
64
65
def validate_header_image(imagepath):
66
    """ Validates the resolution of a header image. """
67
    absolute_imagepath = os.path.join(settings.MEDIA_ROOT, str(imagepath))
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 < 1000:
74
        raise ValidationError('Image resolution is too low. It should be at least 1000px wide. The selected image is %i x %i. Please find a larger image.' % (width, height))
75
76
77
78
class PageHeaderImageWidget(SiteRelated):
79
    """ Page header image. """
80
    name = models.CharField(max_length=1000, blank=True, null=False, default="")
81
    page = models.ForeignKey(Page, blank=False, null=True)
82
    image = FileField(max_length=200, format="Image", validators=[validate_header_image])
83
84
85
class PageItem(SiteRelated):
86
    page = models.ForeignKey(Page, blank=False, null=True)
87
    visible = models.BooleanField(default=False)
88
89
    class Meta:
90
        abstract = True
91
92
93
class SidebarAgenda(PageItem):
94
    SITE = 'SI'
95
    ALL = 'AL'
96
    MAIN = 'MA'
97
    MAIN_AND_SITE = 'SM'
98
99
    EVENT_CHOICES = (
100
        (SITE, 'Site'),
101
        (ALL, 'All'),
102
        (MAIN, 'Main site'),
103
        (MAIN_AND_SITE, 'Main and site'),
104
    )
105
106
    type = models.CharField(max_length=2, choices=EVENT_CHOICES)
107
108
    class Meta:
109
        verbose_name = "Sidebar Agenda Item"
110
111
    def get_name(self):
112
        if self.type == self.MAIN_AND_SITE:
113
            return 'Events for current and main site'
114
        elif self.type == self.ALL:
115
            return 'Events for all sites'
116
        elif self.type == self.SITE:
117
            return 'Events for current site'
118
        elif self.type == self.MAIN:
119
            return 'Events for main site'
120
        assert False
121
122
    def __str__(self):
123
        return self.get_name()
124
125
126
class SidebarTwitter(PageItem):
127
128
    class Meta:
129
        verbose_name = "Sidebar Twitter Item"
130
131
132
class SidebarSocial(PageItem):
133
134
    class Meta:
135
        verbose_name = "Sidebar Social Media Item"
136
137
138
class SidebarRichText(PageItem):
139
    content = RichTextField()
140
141
    class Meta:
142
        verbose_name = "Sidebar RichText Item"
143
144
145
class SidebarLink(PageItem, Orderable):
146
    title = models.CharField(max_length=100, blank=True, default="")
147
    url = models.CharField(max_length=500, blank=True, default="")
148
149
150
class ActionBanner(PageItem):
151
    title = models.CharField(max_length=500, blank=True, default="")
152
    content = RichTextField()
153
    image = FileField(max_length=300, format="Image")
154
    button_title = models.CharField(max_length=500, blank=True, default="")
155
    button_url = models.CharField(max_length=500, blank=True, default="")
156
157
158
def validate_vision_image(imagepath):
159
    """ Validates the aspect ratio of a vision image. """
160
    absolute_imagepath = os.path.join(settings.MEDIA_ROOT, str(imagepath))
161
    im = Image.open(absolute_imagepath)
162
    width, height = im.size
163
    aspect_ratio = width/height
164
    if abs(aspect_ratio-1.5) > 0.1:
165
        raise ValidationError('Image aspect ratio should be 1.5 (for example 300x200px or 600x400px), selected image is %i x %i. Please resize the image.' % (width, height))
166
167
168
class VisionPage(Page, RichText):
169
    """
170
    """
171
    image = FileField(max_length=300, format="Image", blank=True, default="", validators=[validate_vision_image])
172
173
    class Meta:
174
        verbose_name = 'VisionPage'
175
176
177
class VisionsPage(Page, RichText):
178
    """
179
    """
180
    vision_pages = models.ManyToManyField(VisionPage)
181
182
    class Meta:
183
        verbose_name = 'VisionsPage'
184
185
186
class HomePage(Page, RichText):
187
    """
188
    Page model for the site homepage.
189
    Only works properly when url points to the homepage '/' as url.
190
    """
191
    header_title = models.CharField(max_length=300, blank=True, default="")
192
    header_subtitle = models.CharField(max_length=500, blank=True, default="")
193
    news_category = models.ForeignKey(BlogCategory, null=True, blank=True)
194
    vision_pages = models.ManyToManyField(VisionPage)
195
196
    @property
197
    def blog_posts(self):
198
        return get_public_blogposts(self.news_category)
199
200
    class Meta:
201
        verbose_name = 'Homepage'
202
203
204
205
class BlogCategoryPage(Page, RichText):
206
    """
207
    Model for a page that displays a list of posts in a single blog category.
208
    """
209
210
    blog_category = models.ForeignKey(BlogCategory, null=False, blank=False)
211
    show_excerpt = models.BooleanField(default=False, null=False, blank=False,
212
                                       help_text='Show only the first paragraph of a blog post.')
213
214
    class Meta:
215
        verbose_name = "Blog category page"
216
        verbose_name_plural = "Blog category pages"
217
218
219
def get_public_blogposts(blog_category):
220
    """ Returns all blogposts for a given category that are published and not expired. """
221
    blog_posts = BlogPost.objects.all().filter(categories=blog_category).filter(status=CONTENT_STATUS_PUBLISHED)
222
    return blog_posts.filter(publish_date__lte=timezone.now()).filter(Q(expiry_date__isnull=True)
223
                                                                      | Q(expiry_date__gte=timezone.now()))
224