~widelands-dev/widelands-website/trunk

« back to all changes in this revision

Viewing changes to wlmaps/forms.py

  • Committer: Holger Rapp
  • Date: 2019-06-21 18:34:42 UTC
  • mfrom: (540.1.3 update_ops_script)
  • Revision ID: sirver@gmx.de-20190621183442-y2ulybzr0rdvfefd
Adapt the update script for the new server.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python -tt
2
2
# encoding: utf-8
3
3
 
 
4
import json
 
5
from subprocess import check_call, CalledProcessError
 
6
 
4
7
from django import forms
5
 
 
6
 
class UploadMapForm(forms.Form):
7
 
    mapfile = forms.FileField()
8
 
    comment = forms.CharField(required=False)
9
 
 
 
8
from django.forms import ModelForm
 
9
from django.core.files.storage import default_storage
 
10
from django.conf import settings
 
11
 
 
12
from wlmaps.models import Map
 
13
import os
 
14
 
 
15
class UploadMapForm(ModelForm):
 
16
    """
 
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)
 
22
 
 
23
    The filename of uploaded maps may contain bad characters which must be handled.
 
24
 
 
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
 
28
    minimap.
 
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.
 
31
    """
 
32
 
 
33
    class Meta:
 
34
        model = Map
 
35
        fields = ['file', 'uploader_comment']
 
36
 
 
37
    def clean(self):
 
38
        cleaned_data = super(UploadMapForm, self).clean()
 
39
 
 
40
        mem_file_obj = cleaned_data.get('file')
 
41
        if not mem_file_obj:
 
42
            # no clean file => abort
 
43
            return cleaned_data
 
44
 
 
45
        try:
 
46
            # Try to make a safe filename
 
47
            safe_name = default_storage.get_valid_name(mem_file_obj.name)
 
48
            file_path = settings.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']
 
54
            return cleaned_data
 
55
 
 
56
        try:
 
57
            # call map info tool to generate minimap and json info file
 
58
            old_cwd = os.getcwd()
 
59
            os.chdir(settings.WIDELANDS_SVN_DIR)
 
60
            check_call(['wl_map_info', saved_file])
 
61
 
 
62
            # TODO(shevonar): delete file because it will be saved again when
 
63
            # the model is saved. File should not be saved twice
 
64
            default_storage.delete(saved_file)
 
65
            os.chdir(old_cwd)
 
66
        except CalledProcessError:
 
67
            self._errors['file'] = self.error_class(
 
68
                ['The map file could not be processed.'])
 
69
            del cleaned_data['file']
 
70
            return cleaned_data
 
71
 
 
72
        mapinfo = json.load(open(saved_file + '.json'))
 
73
 
 
74
        if Map.objects.filter(name=mapinfo['name']):
 
75
            self._errors['file'] = self.error_class(
 
76
                ['A map with the same name already exists.'])
 
77
            del cleaned_data['file']
 
78
            return cleaned_data
 
79
 
 
80
        # Add information to the map
 
81
        self.instance.name = mapinfo['name']
 
82
        self.instance.author = mapinfo['author']
 
83
        self.instance.w = mapinfo['width']
 
84
        self.instance.h = mapinfo['height']
 
85
        self.instance.nr_players = mapinfo['nr_players']
 
86
        self.instance.descr = mapinfo['description']
 
87
        self.instance.hint = mapinfo['hint']
 
88
        self.instance.world_name = mapinfo['world_name']
 
89
 
 
90
        # mapinfo["minimap"] is an absolute path.
 
91
        # We partition it to get the correct file path
 
92
        minimap_path = mapinfo['minimap'].partition(settings.MEDIA_ROOT)[2]
 
93
        self.instance.minimap = '/' + minimap_path
 
94
 
 
95
        # the json file is no longer needed
 
96
        default_storage.delete(saved_file + '.json')
 
97
 
 
98
        return cleaned_data
 
99
 
 
100
    def save(self, *args, **kwargs):
 
101
        map = super(UploadMapForm, self).save(*args, **kwargs)
 
102
        if kwargs['commit']:
 
103
            map.save()
 
104
        return map
 
105
 
 
106
 
 
107
class EditCommentForm(ModelForm):
 
108
 
 
109
    class Meta:
 
110
        model = Map
 
111
        fields = ['uploader_comment', ]