Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
thalia
concrexit
Commits
e69d6c57
Commit
e69d6c57
authored
May 28, 2019
by
Sébastiaan Versteeg
Browse files
Merge branch 'fix-579' into 'master'
Add documentation to the partners app Closes
#579
See merge request
!1272
parents
ae42a29f
396d05d8
Changes
11
Hide whitespace changes
Inline
Side-by-side
website/partners/admin.py
View file @
e69d6c57
...
...
@@ -6,11 +6,15 @@ from utils.translation import TranslatedModelAdmin
class
PartnerImageInline
(
admin
.
StackedInline
):
"""Class to show partner images inline in the admin."""
model
=
PartnerImage
@
admin
.
register
(
Partner
)
class
PartnerAdmin
(
admin
.
ModelAdmin
):
"""Class to show partners in the admin."""
prepopulated_fields
=
{
"slug"
:
(
"name"
,)}
list_display
=
(
'name'
,
'is_active'
,
'is_main_partner'
,)
inlines
=
(
PartnerImageInline
,)
...
...
@@ -31,12 +35,16 @@ class PartnerAdmin(admin.ModelAdmin):
@
admin
.
register
(
VacancyCategory
)
class
VacancyCategoryAdmin
(
TranslatedModelAdmin
):
"""Class to show vacancy categories in the admin."""
prepopulated_fields
=
{
"slug"
:
(
"name_en"
,)}
fields
=
[
'name'
,
'slug'
]
@
admin
.
register
(
Vacancy
)
class
VacancyAdmin
(
admin
.
ModelAdmin
):
"""Class to show vacancies in the admin."""
list_display
=
(
'title'
,
'partner'
,
'company_name'
,
'expiration_date'
)
fieldsets
=
(
...
...
@@ -60,6 +68,8 @@ class VacancyAdmin(admin.ModelAdmin):
@
admin
.
register
(
PartnerEvent
)
class
PartnerEventAdmin
(
TranslatedModelAdmin
):
"""Class to show partner events in the admin."""
fields
=
[
'partner'
,
'other_partner'
,
'title'
,
'description'
,
'location'
,
'start'
,
'end'
,
'url'
,
'published'
]
list_display
=
(
'title'
,
'start'
,
'end'
,
...
...
website/partners/api/serializers.py
View file @
e69d6c57
...
...
@@ -8,7 +8,11 @@ from partners.models import PartnerEvent, Partner
class
PartnerEventCalendarJSSerializer
(
CalenderJSSerializer
):
"""Partner event calender serializer."""
class
Meta
(
CalenderJSSerializer
.
Meta
):
"""Meta class for partner event calendar serializer."""
model
=
PartnerEvent
def
_title
(
self
,
instance
):
...
...
@@ -17,27 +21,39 @@ class PartnerEventCalendarJSSerializer(CalenderJSSerializer):
return
"{} ({})"
.
format
(
instance
.
title
,
instance
.
other_partner
)
def
_background_color
(
self
,
instance
):
"""Return the color of the background."""
return
'black'
def
_text_color
(
self
,
instance
):
"""Return the color of the text."""
return
'#E62272'
def
_url
(
self
,
instance
):
"""Return the url of the partner event."""
return
instance
.
url
def
_target_blank
(
self
,
instance
):
"""Return whether the anchor tag should have 'target="_blank"'."""
return
True
class
PartnerSerializer
(
serializers
.
ModelSerializer
):
"""Partner serializer."""
class
Meta
:
"""Meta class for partner serializer."""
model
=
Partner
fields
=
(
'pk'
,
'name'
,
'link'
,
'company_profile'
,
'address'
,
'zip_code'
,
'city'
,
'logo'
)
class
PartnerEventSerializer
(
serializers
.
ModelSerializer
):
"""Partner events serializer."""
class
Meta
:
"""Meta class for partner events serializer."""
model
=
PartnerEvent
fields
=
(
'pk'
,
'title'
,
'description'
,
'start'
,
'end'
,
'location'
,
'url'
)
...
...
@@ -45,4 +61,5 @@ class PartnerEventSerializer(serializers.ModelSerializer):
description
=
serializers
.
SerializerMethodField
(
'_description'
)
def
_description
(
self
,
instance
):
"""Return description of partner event."""
return
unescape
(
strip_tags
(
instance
.
description
))
website/partners/api/viewsets.py
View file @
e69d6c57
...
...
@@ -15,11 +15,14 @@ from utils.snippets import extract_date_range
class
PartnerViewset
(
viewsets
.
ReadOnlyModelViewSet
):
"""View set for partners."""
serializer_class
=
PartnerSerializer
queryset
=
Partner
.
objects
.
filter
(
is_active
=
True
)
@
action
(
detail
=
False
,
permission_classes
=
(
IsAuthenticatedOrReadOnly
,))
def
calendarjs
(
self
,
request
):
"""Return response with serialized partner event calender data."""
start
,
end
=
extract_date_range
(
request
)
queryset
=
PartnerEvent
.
objects
.
filter
(
...
...
@@ -33,6 +36,8 @@ class PartnerViewset(viewsets.ReadOnlyModelViewSet):
class
PartnerEventViewset
(
viewsets
.
ReadOnlyModelViewSet
):
"""View set for partner events."""
queryset
=
PartnerEvent
.
objects
.
filter
(
end__gte
=
timezone
.
now
(),
published
=
True
)
permission_classes
=
[
IsAuthenticated
]
...
...
website/partners/apps.py
View file @
e69d6c57
...
...
@@ -3,5 +3,7 @@ from django.utils.translation import gettext_lazy as _
class
PartnersConfig
(
AppConfig
):
"""Appconfig for partners app."""
name
=
'partners'
verbose_name
=
_
(
'Partners'
)
website/partners/emails.py
View file @
e69d6c57
...
...
@@ -8,6 +8,7 @@ from partners.models import Vacancy
def
send_vacancy_expiration_notifications
(
dry_run
=
False
):
"""Send a notification about expiring vacancies."""
# Select vacencies that expire in roughly a month, wherefor
# a mail hasn't been sent yet to Mr/Mrs Extern
expired_vacancies
=
Vacancy
.
objects
.
filter
(
...
...
website/partners/management/commands/sendvacancyexpirationnotification.py
View file @
e69d6c57
...
...
@@ -4,8 +4,10 @@ from partners import emails
class
Command
(
BaseCommand
):
"""Command class for sendvacancyexpirationnotification command."""
def
add_arguments
(
self
,
parser
):
"""Add --dry-run argument to command."""
parser
.
add_argument
(
'--dry-run'
,
action
=
'store_true'
,
...
...
@@ -15,5 +17,6 @@ class Command(BaseCommand):
)
def
handle
(
self
,
*
args
,
**
options
):
"""Call the function to handle the sending of emails."""
emails
.
send_vacancy_expiration_notifications
(
bool
(
options
[
'dry-run'
]))
website/partners/models.py
View file @
e69d6c57
...
...
@@ -9,6 +9,8 @@ from utils.translation import ModelTranslateMeta, MultilingualField
class
Partner
(
models
.
Model
):
"""Model describing partner."""
is_active
=
models
.
BooleanField
(
default
=
False
)
is_main_partner
=
models
.
BooleanField
(
default
=
False
)
name
=
models
.
CharField
(
max_length
=
255
)
...
...
@@ -42,12 +44,19 @@ class Partner(models.Model):
city
=
models
.
CharField
(
max_length
=
100
)
def
save
(
self
,
*
args
,
**
kwargs
):
"""Save a partner and set main partner."""
if
self
.
is_main_partner
:
self
.
_reset_main_partner
()
super
(
Partner
,
self
).
save
(
*
args
,
**
kwargs
)
def
_reset_main_partner
(
self
):
"""
Reset the main partner status.
If this partner is not main partner,
remove the main partner status from the main partner.
"""
try
:
current_main_partner
=
Partner
.
objects
.
get
(
is_main_partner
=
True
)
if
self
!=
current_main_partner
:
...
...
@@ -57,16 +66,22 @@ class Partner(models.Model):
pass
def
__str__
(
self
):
"""Return the name of the partner."""
return
self
.
name
def
get_absolute_url
(
self
):
"""Return the url of the partner page."""
return
reverse
(
'partners:partner'
,
args
=
(
self
.
slug
,))
class
Meta
:
"""Meta class for partner model."""
ordering
=
(
'name'
,)
class
PartnerImage
(
models
.
Model
):
"""Model to save partner image."""
partner
=
models
.
ForeignKey
(
Partner
,
on_delete
=
models
.
CASCADE
,
...
...
@@ -75,21 +90,29 @@ class PartnerImage(models.Model):
image
=
models
.
ImageField
(
upload_to
=
'public/partners/images/'
)
def
__str__
(
self
):
"""Return string representation of partner name."""
return
ugettext
(
'image of {}'
).
format
(
self
.
partner
.
name
)
class
VacancyCategory
(
models
.
Model
,
metaclass
=
ModelTranslateMeta
):
"""Model describing vacancy categories."""
name
=
MultilingualField
(
models
.
CharField
,
max_length
=
30
)
slug
=
models
.
SlugField
()
def
__str__
(
self
):
"""Return the category name."""
return
self
.
name
class
Meta
:
"""Meta class for vacancy category model."""
verbose_name_plural
=
_
(
'Vacancy Categories'
)
class
Vacancy
(
models
.
Model
):
"""Model describing vacancies."""
title
=
models
.
CharField
(
max_length
=
255
)
description
=
HTMLField
()
link
=
models
.
CharField
(
...
...
@@ -122,28 +145,30 @@ class Vacancy(models.Model):
remarks
=
HTMLField
(
blank
=
True
,
help_text
=
_
(
'not shown on the page'
))
def
get_company_name
(
self
):
"""Return company or partner name."""
if
self
.
partner
:
return
self
.
partner
.
name
return
self
.
company_name
def
get_company_logo
(
self
):
"""Return company or partner logo."""
if
self
.
partner
:
return
self
.
partner
.
logo
return
self
.
company_logo
def
__str__
(
self
):
"""Return vacancy partner or company and title."""
return
'{} — {}'
.
format
(
self
.
get_company_name
(),
self
.
title
)
class
Meta
:
verbose_name_plural
=
_
(
'Vacancies'
)
def
get_absolute_url
(
self
):
"""Return partner or vacancy url."""
url
=
reverse
(
'partners:vacancies'
)
if
self
.
partner
:
url
=
reverse
(
'partners:partner'
,
args
=
(
self
.
partner
.
slug
,))
return
'{}#vacancy-{}'
.
format
(
url
,
self
.
pk
)
def
clean
(
self
):
"""Validate the vacancy."""
super
().
clean
()
errors
=
{}
...
...
@@ -172,8 +197,15 @@ class Vacancy(models.Model):
if
errors
:
raise
ValidationError
(
errors
)
class
Meta
:
"""Meta class for vacancy model."""
verbose_name_plural
=
_
(
'Vacancies'
)
class
PartnerEvent
(
models
.
Model
,
metaclass
=
ModelTranslateMeta
):
"""Model describing partner event."""
partner
=
models
.
ForeignKey
(
Partner
,
on_delete
=
models
.
CASCADE
,
...
...
@@ -210,6 +242,7 @@ class PartnerEvent(models.Model, metaclass=ModelTranslateMeta):
published
=
models
.
BooleanField
(
_
(
"published"
),
default
=
False
)
def
clean
(
self
):
"""Validate the partner event."""
super
().
clean
()
errors
=
{}
if
((
not
self
.
partner
and
not
self
.
other_partner
)
or
...
...
@@ -224,4 +257,5 @@ class PartnerEvent(models.Model, metaclass=ModelTranslateMeta):
raise
ValidationError
(
errors
)
def
__str__
(
self
):
"""Return the event title."""
return
self
.
title
website/partners/sitemaps.py
View file @
e69d6c57
...
...
@@ -5,29 +5,40 @@ from . import models
class
StaticViewSitemap
(
sitemaps
.
Sitemap
):
"""Sitemap generator for static partner views."""
changefreq
=
'daily'
def
items
(
self
):
"""Return static partner view names."""
return
[
'partners:index'
,
'partners:vacancies'
]
def
location
(
self
,
item
):
"""Return view url."""
return
reverse
(
item
)
class
PartnerSitemap
(
sitemaps
.
Sitemap
):
"""Sitemap generator for partners."""
def
items
(
self
):
"""Return all active partners."""
return
models
.
Partner
.
objects
.
filter
(
is_active
=
True
)
def
location
(
self
,
item
):
"""Return the partner url."""
return
item
.
get_absolute_url
()
class
VacancySitemap
(
sitemaps
.
Sitemap
):
"""Sitemap generator for vacancies."""
def
items
(
self
):
"""Return all vacancies."""
return
models
.
Vacancy
.
objects
.
all
()
def
location
(
self
,
item
):
"""Return the vacancy url."""
return
item
.
get_absolute_url
()
...
...
website/partners/templatetags/partner_banners.py
View file @
e69d6c57
...
...
@@ -10,6 +10,7 @@ register = template.Library()
@
register
.
inclusion_tag
(
'partners/banners.html'
,
takes_context
=
True
)
def
render_partner_banners
(
context
):
"""Render the partner banner."""
request
=
context
[
'request'
]
all_partners
=
Partner
.
objects
.
filter
(
is_active
=
True
).
order_by
(
'id'
)
ids
=
[
partner
.
id
for
partner
in
all_partners
]
...
...
website/partners/templatetags/partner_cards.py
View file @
e69d6c57
...
...
@@ -11,6 +11,7 @@ register = template.Library()
@
register
.
inclusion_tag
(
'includes/grid_item.html'
)
def
partner_card
(
partner
):
"""Return grid item showing partner."""
image_url
=
''
if
partner
.
logo
:
image_url
=
get_thumbnail_url
(
partner
.
logo
,
...
...
@@ -30,6 +31,7 @@ def partner_card(partner):
@
register
.
inclusion_tag
(
'includes/grid_item.html'
)
def
partner_image_card
(
image
):
"""Return grid item showing partner image."""
class_name
=
'partner-image-card'
image_url
=
get_thumbnail_url
(
image
,
settings
.
THUMBNAIL_SIZES
[
'medium'
])
...
...
@@ -45,6 +47,7 @@ def partner_image_card(image):
@
register
.
inclusion_tag
(
'partners/vacancy_card.html'
)
def
vacancy_card
(
vacancy
):
"""Return grid item showing vacancy."""
image_url
=
None
if
vacancy
.
get_company_logo
():
image_url
=
get_thumbnail_url
(
vacancy
.
get_company_logo
(),
...
...
website/partners/views.py
View file @
e69d6c57
...
...
@@ -7,6 +7,7 @@ from partners.models import Partner, Vacancy, VacancyCategory
def
index
(
request
):
"""View to show overview page of partners."""
partners
=
Partner
.
objects
.
filter
(
is_active
=
True
,
is_main_partner
=
False
)
try
:
main_partner
=
Partner
.
objects
.
get
(
...
...
@@ -24,6 +25,7 @@ def index(request):
def
partner
(
request
,
slug
):
"""View to show partner page."""
partner
=
get_object_or_404
(
Partner
,
slug
=
slug
)
context
=
{
'partner'
:
partner
,
...
...
@@ -33,6 +35,7 @@ def partner(request, slug):
def
vacancies
(
request
):
"""View to show vacancies."""
context
=
{
'vacancies'
:
Vacancy
.
objects
.
exclude
(
expiration_date__lte
=
timezone
.
now
().
date
()).
order_by
(
'?'
),
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment