7
7
from django import forms
8
8
from django.forms import ModelForm
9
9
from django.core.files.storage import default_storage
10
from django.core.files.base import ContentFile
12
11
from settings import MEDIA_ROOT
13
12
from wlmaps.models import Map
16
15
class UploadMapForm(ModelForm):
17
We have to handle here three different kind of files:
18
1. The map which is uploaded
19
2. The files created by 'wl_map_info'
20
a. The json file containing infos of the map
21
b. The image of the minimap (png)
23
The filename of uploaded maps may contain bad characters which must be handled.
25
If a map get deleted in the database, the underlying files (.wmf, .png) still exists. Uploading
26
a map with the same name does not overwrite the existing file(s), instead they get a
27
name in form of 'filename_<random_chars>.wmf(.png)'. This is importand for linking the correct
29
The map file and the minimap (png) have different random characters in such a case, because the map
30
get saved twice: One time for the call to wl_map_info, and when the model is saved.
23
38
cleaned_data = super(UploadMapForm, self).clean()
25
file = cleaned_data.get('file')
40
mem_file_obj = cleaned_data.get('file')
27
42
# no clean file => abort
28
43
return cleaned_data
30
name = MEDIA_ROOT + 'wlmaps/maps/' + file.name
31
default_storage.save(name, ContentFile(file.read()))
46
# Try to make a safe filename
47
safe_name = default_storage.get_valid_name(mem_file_obj.name)
48
file_path = MEDIA_ROOT + 'wlmaps/maps/' + safe_name
49
saved_file = default_storage.save(file_path, mem_file_obj)
50
except UnicodeEncodeError:
51
self._errors['file'] = self.error_class(
52
['The filename contains characters which cannot be handled. Please rename and upload again.'])
53
del cleaned_data['file']
33
57
# call map info tool to generate minimap and json info file
34
check_call(['wl_map_info', name])
58
check_call(['wl_map_info', saved_file])
35
60
# TODO(shevonar): delete file because it will be saved again when
36
61
# the model is saved. File should not be saved twice
37
default_storage.delete(name)
62
default_storage.delete(saved_file)
38
63
except CalledProcessError:
39
64
self._errors['file'] = self.error_class(
40
65
['The map file could not be processed.'])
41
66
del cleaned_data['file']
42
67
return cleaned_data
44
mapinfo = json.load(open(name + '.json'))
69
mapinfo = json.load(open(saved_file + '.json'))
46
71
if Map.objects.filter(name=mapinfo['name']):
47
72
self._errors['file'] = self.error_class(
57
82
self.instance.nr_players = mapinfo['nr_players']
58
83
self.instance.descr = mapinfo['description']
59
84
self.instance.hint = mapinfo['hint']
61
85
self.instance.world_name = mapinfo['world_name']
62
# mapinfo["minimap"] is an absolute path and cannot be used.
63
self.instance.minimap = '/wlmaps/maps/' + file.name + '.png'
87
# mapinfo["minimap"] is an absolute path.
88
# We partition it to get the correct file path
89
minimap_path = mapinfo['minimap'].partition(MEDIA_ROOT)[2]
90
self.instance.minimap = '/' + minimap_path
65
92
# the json file is no longer needed
66
default_storage.delete(name + '.json')
93
default_storage.delete(saved_file + '.json')
68
95
return cleaned_data
70
97
def save(self, *args, **kwargs):