Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
99a3eb47b8
@ -1,9 +1,14 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from .models import File
|
from .models import File, ImageFile
|
||||||
|
|
||||||
|
|
||||||
class FileForm(forms.ModelForm):
|
class FileForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = File
|
model = File
|
||||||
exclude = ['user',]
|
exclude = ['user',]
|
||||||
|
|
||||||
|
class ImageFileForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = ImageFile
|
||||||
|
exclude = ['user',]
|
||||||
|
36
apps/files/migrations/0003_auto_20180526_1547.py
Normal file
36
apps/files/migrations/0003_auto_20180526_1547.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.6 on 2018-05-26 15:47
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('files', '0002_file_user'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ImageFile',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('file', models.FileField(upload_to='.')),
|
||||||
|
('caption', models.CharField(default=None, max_length=240, null=True, verbose_name='Image caption')),
|
||||||
|
('credit', models.CharField(default=None, max_length=240, null=True, verbose_name='Image credit')),
|
||||||
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='imagefile', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='file',
|
||||||
|
name='user',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='file', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
25
apps/files/migrations/0004_auto_20180530_0308.py
Normal file
25
apps/files/migrations/0004_auto_20180530_0308.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.6 on 2018-05-30 03:08
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('files', '0003_auto_20180526_1547'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='imagefile',
|
||||||
|
name='caption',
|
||||||
|
field=models.CharField(blank=True, default=None, max_length=240, null=True, verbose_name='Image caption'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='imagefile',
|
||||||
|
name='credit',
|
||||||
|
field=models.CharField(blank=True, default=None, max_length=240, null=True, verbose_name='Image credit'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,5 +1,6 @@
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from apps.map.models import CaseStudy, CaseStudyDraft
|
from apps.map.models import CaseStudy, CaseStudyDraft
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ class BaseFile(models.Model):
|
|||||||
upload_to='.',
|
upload_to='.',
|
||||||
)
|
)
|
||||||
user = models.ForeignKey(
|
user = models.ForeignKey(
|
||||||
User, related_name='files'
|
User, related_name='%(class)s'
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -21,3 +22,21 @@ class BaseFile(models.Model):
|
|||||||
|
|
||||||
class File(BaseFile):
|
class File(BaseFile):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ImageFile(BaseFile):
|
||||||
|
caption = models.CharField(
|
||||||
|
verbose_name=_("Image caption"),
|
||||||
|
max_length=240,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
credit = models.CharField(
|
||||||
|
verbose_name=_("Image credit"),
|
||||||
|
max_length=240,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
@ -213,6 +213,9 @@ class MultipleFilesWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
window.images = new MultipleFilesWidget(
|
||||||
|
document.querySelector('[data-field=images_files]')
|
||||||
|
)
|
||||||
window.official_project_documents = new MultipleFilesWidget(
|
window.official_project_documents = new MultipleFilesWidget(
|
||||||
document.querySelector('[data-field=official_project_documents_files]')
|
document.querySelector('[data-field=official_project_documents_files]')
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from .views import FileUploadView, FileDeleteView
|
from .views import FileUploadView, FileDeleteView, ImageFileUploadView
|
||||||
|
|
||||||
app_name = 'files'
|
app_name = 'files'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^upload/$', FileUploadView.as_view(), name='upload'),
|
url(r'^upload/$', FileUploadView.as_view(), name='upload'),
|
||||||
|
url(r'^upload/image/$', ImageFileUploadView.as_view(), name='upload'),
|
||||||
url(r'^delete/(?P<pk>\d+)/$', FileDeleteView.as_view(), name='delete'),
|
url(r'^delete/(?P<pk>\d+)/$', FileDeleteView.as_view(), name='delete'),
|
||||||
]
|
]
|
||||||
|
@ -4,8 +4,9 @@ from django.http import JsonResponse
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.views.generic import FormView, DetailView
|
from django.views.generic import FormView, DetailView
|
||||||
|
|
||||||
from .forms import FileForm
|
from .forms import ImageFileForm, FileForm
|
||||||
from .models import File
|
from .models import ImageFile, File
|
||||||
|
|
||||||
|
|
||||||
class FileUploadView(LoginRequiredMixin, FormView):
|
class FileUploadView(LoginRequiredMixin, FormView):
|
||||||
model = File
|
model = File
|
||||||
@ -26,6 +27,11 @@ class FileUploadView(LoginRequiredMixin, FormView):
|
|||||||
return JsonResponse({'is_valid': False, 'errors': form.errors})
|
return JsonResponse({'is_valid': False, 'errors': form.errors})
|
||||||
|
|
||||||
|
|
||||||
|
class ImageFileUploadView(FileUploadView):
|
||||||
|
model = ImageFile
|
||||||
|
form_class = ImageFileForm
|
||||||
|
|
||||||
|
|
||||||
class FileDeleteView(LoginRequiredMixin, DetailView):
|
class FileDeleteView(LoginRequiredMixin, DetailView):
|
||||||
model = File
|
model = File
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ from crispy_forms.bootstrap import Tab, TabHolder, PrependedText, FormActions
|
|||||||
from dal import autocomplete
|
from dal import autocomplete
|
||||||
from leaflet.forms.widgets import LeafletWidget
|
from leaflet.forms.widgets import LeafletWidget
|
||||||
|
|
||||||
from apps.files.models import File
|
from apps.files.models import File, ImageFile
|
||||||
|
|
||||||
from .models import CaseStudy, SpatialRefSys
|
from .models import CaseStudy, SpatialRefSys
|
||||||
from .widgets import CommaSeparatedTextInput
|
from .widgets import CommaSeparatedTextInput
|
||||||
@ -71,9 +71,6 @@ class ShortCaseStudyForm(BaseCaseStudyForm):
|
|||||||
'project_status',
|
'project_status',
|
||||||
'synopsis',
|
'synopsis',
|
||||||
'full_description',
|
'full_description',
|
||||||
'image',
|
|
||||||
'image_caption',
|
|
||||||
'image_credit',
|
|
||||||
'video',
|
'video',
|
||||||
'media_coverage_mainstream',
|
'media_coverage_mainstream',
|
||||||
'media_coverage_independent',
|
'media_coverage_independent',
|
||||||
@ -88,6 +85,19 @@ class BootstrapClearableFileInput(forms.ClearableFileInput):
|
|||||||
class LongCaseStudyForm(BaseCaseStudyForm):
|
class LongCaseStudyForm(BaseCaseStudyForm):
|
||||||
"""Long version of the CaseStudy form."""
|
"""Long version of the CaseStudy form."""
|
||||||
|
|
||||||
|
images = forms.FileField(
|
||||||
|
widget=BootstrapClearableFileInput(attrs={
|
||||||
|
'url': reverse_lazy('files:upload'),
|
||||||
|
'field': 'images_files',
|
||||||
|
}), required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
images_files = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=ImageFile.objects.all(),
|
||||||
|
widget=CommaSeparatedTextInput(),
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
official_project_documents = forms.FileField(
|
official_project_documents = forms.FileField(
|
||||||
widget=BootstrapClearableFileInput(attrs={
|
widget=BootstrapClearableFileInput(attrs={
|
||||||
'url': reverse_lazy('files:upload'),
|
'url': reverse_lazy('files:upload'),
|
||||||
@ -201,9 +211,8 @@ class LongCaseStudyForm(BaseCaseStudyForm):
|
|||||||
'project_status',
|
'project_status',
|
||||||
'synopsis',
|
'synopsis',
|
||||||
'full_description',
|
'full_description',
|
||||||
'image',
|
'images',
|
||||||
'image_caption',
|
'images_files',
|
||||||
'image_credit',
|
|
||||||
'video',
|
'video',
|
||||||
'video_caption',
|
'video_caption',
|
||||||
'video_credit',
|
'video_credit',
|
||||||
|
21
apps/map/migrations/0065_casestudy_images.py
Normal file
21
apps/map/migrations/0065_casestudy_images.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.6 on 2018-05-26 15:47
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('files', '0003_auto_20180526_1547'),
|
||||||
|
('map', '0064_auto_20180526_1536'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='images',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='image_for', to='files.ImageFile', verbose_name='Images'),
|
||||||
|
),
|
||||||
|
]
|
36
apps/map/migrations/0066_copy_images_to_imagefiles.py
Normal file
36
apps/map/migrations/0066_copy_images_to_imagefiles.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.6 on 2018-05-26 15:48
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def copy_images(apps, schema_editor):
|
||||||
|
CaseStudy = apps.get_model('map', 'CaseStudy')
|
||||||
|
ImageFile = apps.get_model('files', 'ImageFile')
|
||||||
|
User = apps.get_model('auth', 'User')
|
||||||
|
|
||||||
|
for case_study in CaseStudy.objects.all():
|
||||||
|
author = case_study.author
|
||||||
|
if author is None:
|
||||||
|
author = User.objects.get(username='root')
|
||||||
|
|
||||||
|
imagefile = ImageFile(
|
||||||
|
file=case_study.image,
|
||||||
|
caption=case_study.image_caption,
|
||||||
|
credit=case_study.image_credit,
|
||||||
|
user=author
|
||||||
|
)
|
||||||
|
imagefile.save()
|
||||||
|
case_study.images.add(imagefile)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0065_casestudy_images'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(copy_images, migrations.RunPython.noop),
|
||||||
|
]
|
27
apps/map/migrations/0067_remove_old_images.py
Normal file
27
apps/map/migrations/0067_remove_old_images.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.6 on 2018-05-29 05:20
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0066_copy_images_to_imagefiles'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='image',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='image_caption',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='casestudy',
|
||||||
|
name='image_credit',
|
||||||
|
),
|
||||||
|
]
|
22
apps/map/migrations/0068_casestudydraft_created.py
Normal file
22
apps/map/migrations/0068_casestudydraft_created.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.6 on 2018-05-30 02:52
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('map', '0067_remove_old_images'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casestudydraft',
|
||||||
|
name='created',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
@ -20,8 +20,13 @@ class CaseStudyDraft(models.Model):
|
|||||||
User, on_delete=models.CASCADE
|
User, on_delete=models.CASCADE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
data = models.TextField()
|
data = models.TextField()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{0.author.username}, {0.created:%Y-%m-%d %H:%M}".format(self)
|
||||||
|
|
||||||
|
|
||||||
class SpatialRefSys(connection.ops.spatial_ref_sys()):
|
class SpatialRefSys(connection.ops.spatial_ref_sys()):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -442,25 +447,12 @@ class CaseStudy(models.Model):
|
|||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# 1.15.1
|
# 1.15.1, 1.15.2, 1.15.3
|
||||||
image = models.ImageField(
|
images = models.ManyToManyField(
|
||||||
verbose_name=_("Image")
|
'files.ImageFile',
|
||||||
)
|
related_name='image_for',
|
||||||
|
verbose_name=_("Images"),
|
||||||
# 1.15.2
|
blank=True
|
||||||
image_caption = models.CharField(
|
|
||||||
verbose_name=_("Image caption"),
|
|
||||||
max_length=240,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 1.15.3
|
|
||||||
image_credit = models.CharField(
|
|
||||||
verbose_name=_("Image credit(s)"),
|
|
||||||
max_length=240,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 1.16.1
|
# 1.16.1
|
||||||
|
@ -63,6 +63,7 @@ class BaseForm(LoginRequiredMixin, CreateView):
|
|||||||
form.cleaned_data.pop('official_project_documents', None)
|
form.cleaned_data.pop('official_project_documents', None)
|
||||||
form.cleaned_data.pop('other_documents', None)
|
form.cleaned_data.pop('other_documents', None)
|
||||||
form.cleaned_data.pop('shapefiles', None)
|
form.cleaned_data.pop('shapefiles', None)
|
||||||
|
form.cleaned_data.pop('images', None)
|
||||||
|
|
||||||
self.object = form.save()
|
self.object = form.save()
|
||||||
|
|
||||||
@ -76,6 +77,9 @@ class BaseForm(LoginRequiredMixin, CreateView):
|
|||||||
'shapefiles_files', []
|
'shapefiles_files', []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.object.author = self.request.user
|
||||||
|
self.object.save()
|
||||||
|
|
||||||
self.send_email()
|
self.send_email()
|
||||||
|
|
||||||
# Delete the corresponding draft
|
# Delete the corresponding draft
|
||||||
|
Loading…
Reference in New Issue
Block a user