Browse Source

Add photos to a panorama (for automatic pano generation). WIP

Baptiste Jonglez 10 years ago
parent
commit
65b3ba1a0e
6 changed files with 82 additions and 4 deletions
  1. 13 2
      panorama/admin.py
  2. 25 0
      panorama/forms.py
  3. 25 0
      panorama/migrations/0005_panoramaphoto.py
  4. 12 0
      panorama/models.py
  5. 6 2
      panorama/views.py
  6. 1 0
      requirements.txt

+ 13 - 2
panorama/admin.py

@@ -5,7 +5,7 @@ import os
 
 from django.contrib import admin
 
-from .models import Panorama, ReferencePoint, Reference
+from .models import Panorama, PanoramaPhoto, ReferencePoint, Reference
 from .utils import path_exists
 
 
@@ -15,10 +15,21 @@ class ReferenceInline(admin.TabularInline):
     extra = 1
 
 
+@admin.register(PanoramaPhoto)
+class PanoramaPhotoAdmin(admin.ModelAdmin):
+    model = PanoramaPhoto
+
+
+class PanoramaPhotoInline(admin.StackedInline):
+    model = PanoramaPhoto
+    fk_name = "panorama"
+    extra = 0
+
+
 @admin.register(Panorama)
 class PanoramaAdmin(admin.ModelAdmin):
     model = Panorama
-    inlines = (ReferenceInline, )
+    inlines = (PanoramaPhotoInline, ReferenceInline)
     list_display = ('name', 'has_tiles', 'latitude', 'longitude', 'altitude', 'loop')
     fields = ('name', ('image', 'image_width', 'image_height'),
               'loop', ('latitude', 'longitude'), 'altitude')

+ 25 - 0
panorama/forms.py

@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals, division, print_function
+
+from django.forms import ModelForm
+
+from multiupload.fields import MultiFileField
+
+from .models import Panorama, PanoramaPhoto
+
+
+class PanoramaUploadForm(ModelForm):
+    """Custom form, providing a MultiFileField widget that allows to add
+    multiple photos at the same time.
+    """
+    photos = MultiFileField(min_num=1, max_num=25, max_file_size=1024*1024*100)
+
+    def save(self, commit=True):
+        instance = super(PanoramaUploadForm, self).save(commit)
+        for each in self.cleaned_data['photos']:
+            PanoramaPhoto.objects.create(photo=each, panorama=instance)
+        return instance
+
+    class Meta:
+        model = Panorama
+        fields = ('name', 'image', 'loop', 'latitude', 'longitude', 'altitude')

+ 25 - 0
panorama/migrations/0005_panoramaphoto.py

@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('panorama', '0004_auto_20150310_1906'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='PanoramaPhoto',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('photo', models.ImageField(upload_to='photos', verbose_name='photo')),
+                ('panorama', models.ForeignKey(related_name='photos', verbose_name='panorama', to='panorama.Panorama')),
+            ],
+            options={
+            },
+            bases=(models.Model,),
+        ),
+    ]

+ 12 - 0
panorama/models.py

@@ -114,6 +114,7 @@ class ReferencePoint(Point):
 class Panorama(ReferencePoint):
     loop = models.BooleanField(default=False, verbose_name="360° panorama",
                                help_text="Whether the panorama loops around the edges")
+    # Panorama
     image = models.ImageField(verbose_name="image", upload_to="pano",
                               width_field="image_width",
                               height_field="image_height")
@@ -194,6 +195,17 @@ class Panorama(ReferencePoint):
         return "Panorama : " + self.name
 
 
+@python_2_unicode_compatible
+class PanoramaPhoto(models.Model):
+    """Photo used to assemble a panorama automatically."""
+    panorama = models.ForeignKey(Panorama, verbose_name="panorama", related_name="photos")
+    # Maybe use a lambda for upload_to, to upload to "photos/<panorama_id>/"
+    photo = models.ImageField(verbose_name="photo", upload_to="photos")
+
+    def __str__(self):
+        return "{} ({})".format(self.panorama.name, self.photo.name)
+
+
 class Reference(models.Model):
     """A reference is made of a Panorama, a Reference Point, and the position
     (x, y) of the reference point inside the image.  With enough

+ 6 - 2
panorama/views.py

@@ -7,17 +7,21 @@ from django.http import HttpResponse, JsonResponse
 from django.shortcuts import render, get_object_or_404
 from django.views.generic import CreateView, DetailView, RedirectView, ListView
 
-from .models import Panorama, ReferencePoint
+from .models import Panorama, PanoramaPhoto, ReferencePoint
+from .forms import PanoramaUploadForm
 
 
 class PanoramaUpload(CreateView):
     model = Panorama
-    fields = ('name', 'image', 'loop', 'latitude', 'longitude', 'altitude')
+    form_class = PanoramaUploadForm
+    # Handled by the PanoramaUploadForm class
+    #fields = ('name', 'image', 'loop', 'latitude', 'longitude', 'altitude')
     template_name = "panorama/new.html"
 
     def get_success_url(self):
         return reverse_lazy("panorama:gen_tiles", kwargs={"pk": self.object.id})
 
+
 class PanoramaView(DetailView):
     model = Panorama
     template_name = "panorama/view.html"

+ 1 - 0
requirements.txt

@@ -1,4 +1,5 @@
 Django==1.7.4
 djangorestframework==3.0.5
+django-multiupload==0.3
 Pillow==2.7.0
 celery==3.1.18