Skip to content

Commit c161f30

Browse files
guy881akki
authored andcommitted
Make compatible Python 3/ Django 1.11 (issue 22) (#65)
* Compatibility with python 3. - add parenthesis to print - cast width and height to int before calling resize - open file in binary mode instead of using FileWrapper - convert messages from map to list - add simple test - test under django 1.7 and 1.8 (for now) * Write file in binary mode, replace patterns in urls to normal tuple, thanks to which admin is working * Update README.md, update examples. * Fix exception caused by old templates settings, replace STATIC_URL with static template tag
1 parent ac2d387 commit c161f30

File tree

9 files changed

+133
-88
lines changed

9 files changed

+133
-88
lines changed

README.md

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ Filemanager
55
Filemanager is a simple Django app to browse files on server.
66
You can also integrate this filemanager with CKEditor.
77

8+
Requirements
9+
------------
10+
11+
* Python (2.7, 3.4, 3.5, 3.6, 3.7)
12+
* Django (1.8, 1.11)
13+
814
Screenshot
915
----------
1016

@@ -18,77 +24,88 @@ Install it by
1824
pip install -e git+https://github.com/IMGIITRoorkee/django-filemanager.git#egg=django-filemanager
1925
</pre>
2026

21-
Add "filemanager" to your INSTALLED_APPS setting like this::
22-
<pre>
27+
Add `"filemanager"` to your `INSTALLED_APPS` setting like this::
28+
```python
2329
INSTALLED_APPS = (
2430
...
2531
'filemanager',
2632
)
27-
</pre>
33+
```
2834

2935
Usage
3036
-----
3137

32-
* As a filemanager : To upload files on server by a user to a directory and let him manage his directory by adding, renaming and deleting files and folders inside it.
38+
* As a filemanager : To upload files on server by a user to a directory and let him manage his directory by adding,
39+
renaming and deleting files and folders inside it.
3340

3441
* Integrating it with CKEditor for the functionality of "Browse Server".
3542

3643

3744
As a filemanager
3845
----------------
3946

40-
In urls.py of your app to make filemanager run at url /abc/
41-
<pre>
47+
In `urls.py` of your app to make filemanager run at url `/abc/`.
48+
```python
49+
from django.conf.urls import url
50+
4251
from filemanager import path_end
4352
from views import view
44-
urlpatterns = patterns(
53+
54+
urlpatterns = (
4555
.
4656
.
47-
url(r'^abc/'+path_end, view, name='view'),
57+
url(r'^abc/' + path_end, view, name='view'),
4858
)
49-
</pre>
59+
```
60+
61+
Then write the view in `views.py` of your app:
62+
```python
63+
from django.conf import settings
5064

51-
And then write the view in views.py of your app
52-
<pre>
5365
from filemanager import FileManager
54-
from settings import MEDIA_ROOT
66+
5567

5668
def view(request, path):
57-
fm = FileManager(MEDIA_ROOT + 'user_folder/')
58-
return fm.render(request, path)
59-
</pre>
60-
And it is done.
69+
extensions = ['html', 'htm', 'zip', 'py', 'css', 'js', 'jpeg', 'jpg', 'png']
70+
fm = FileManager(settings.MEDIA_ROOT, extensions=extensions)
71+
return fm.render(request, path)
72+
```
73+
And it is done, you can find above code in `tests` directory.
6174

6275
Adding constraints to Filemanager :
63-
FileManager \__init__ is defined as
64-
<pre>
65-
def __init__(self, basepath, ckeditor_baseurl='', maxfolders=50, maxspace=5*1024, maxfilesize=1*1024, public_url_base=None, extensions=None):
66-
"""
67-
basepath: User's directory basepath in server.
68-
maxfolders: Maximum number of total nested folders allowed inside the user directory.
69-
maxspace (in KB): Maximum space allowed for the user directory.
70-
maxfilesize (in KB): Limit for the size of an uploaded file allowed in user directory.
71-
extensions: List of extensions allowed. Ex. ['pdf','html'] etc.
72-
public_base_url: A base_url if given there will be an option to copy file url with the given url_base.
73-
"""
74-
</pre>
75-
Hence one should also pass arguments like maxfolders, maxspace, maxfilesize if one doesn't want to use the default ones.
76+
FileManager `__init__` is defined as:
77+
```python
78+
def __init__(self, basepath, ckeditor_baseurl='', maxfolders=50, maxspace=5 * 1024, maxfilesize=1 * 1024,
79+
public_url_base=None, extensions=None):
80+
"""
81+
basepath: User's directory basepath in server.
82+
maxfolders: Maximum number of total nested folders allowed inside the user directory.
83+
maxspace (in KB): Maximum space allowed for the user directory.
84+
maxfilesize (in KB): Limit for the size of an uploaded file allowed in user directory.
85+
extensions: List of extensions allowed. Ex. ['pdf','html'] etc.
86+
public_base_url: A base_url if given there will be an option to copy file url with the given url_base.
87+
"""
88+
```
89+
Hence one should also pass arguments like `maxfolders`, `maxspace`, `maxfilesize` if one doesn't want to use the default ones.
7690
If extensions list is not passed then all file-extensions are allowed for upload.
7791

7892
Integrating with CKEditor
7993
-------------------------
8094

81-
Use filemanager.models.CKEditorField field in you model. Or you can use filemanager.widgets.CKEditorWidget as a widget for CKEditor in forms.
82-
Both classes can take an extra argument filemanager_url while making instances from them.
83-
Suppose you want to run filemanager at url `/abc/` in your app then make changes in urls.py and views.py like above.
84-
Then in CKEditorField or CKEditorWidget pass the url of filemanager as argument filemanager_url.
85-
For example in models.py :
86-
<pre>
95+
Use `filemanager.models.CKEditorField` field in you model. Or you can use `filemanager.widgets.CKEditorWidget` as a
96+
widget for CKEditor in forms.
97+
Both classes can take an extra argument `filemanager_url` while making instances from them.
98+
99+
Suppose you want to run filemanager at url `/abc/` in your app then make changes in `urls.py` and `views.py` like above.
100+
Then in `CKEditorField` or `CKEditorWidget` pass the url of filemanager as argument `filemanager_url`.
101+
For example in `models.py`:
102+
103+
```python
104+
from django.db import models
105+
87106
from filemanager.models import CKEditorField
88107

108+
89109
class MyModel(models.Model):
90-
.
91-
.
92-
content = CKEditorField(filemanager_url='/app/abc/')
93-
</pre>
94-
110+
content = CKEditorField(filemanager_url='/app/abc/')
111+
```

filemanager/__init__.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from django.shortcuts import render
22
from django.http import HttpResponse
3-
from django.core.servers.basehttp import FileWrapper
43
from django import forms
54
from PIL import Image
6-
import settings
5+
from . import settings
76
import mimetypes
87
import os
98
import shutil
@@ -116,7 +115,7 @@ def handle_form(self, form, files):
116115
name
117116
and file_or_dir == 'file'
118117
and (
119-
re.search('\.\.', name)
118+
re.search(r'\.\.', name)
120119
or not re.match(r'[\w\d_ -.]+', name).group(0) == name
121120
)
122121
)
@@ -131,8 +130,8 @@ def handle_form(self, form, files):
131130
if action == 'upload':
132131
for f in files.getlist('ufile'):
133132
file_name_invalid = (
134-
re.search('\.\.', f.name)
135-
or not re.match('[\w\d_ -/.]+', f.name).group(0) == f.name
133+
re.search(r'\.\.', f.name)
134+
or not re.match(r'[\w\d_ -/.]+', f.name).group(0) == f.name
136135
)
137136
if file_name_invalid:
138137
messages.append("File name is not valid : " + f.name)
@@ -184,7 +183,7 @@ def handle_form(self, form, files):
184183
+ path
185184
+ self.rename_if_exists(self.basepath + path, filename)
186185
)
187-
with open(filepath, 'w') as dest:
186+
with open(filepath, 'wb') as dest:
188187
for chunk in f.chunks():
189188
dest.write(chunk)
190189
f.close()
@@ -346,7 +345,7 @@ def handle_form(self, form, files):
346345
if file.endswith(tuple(self.extensions)):
347346
zip_ref.extract(file, directory)
348347
mimetype = magic.from_file(directory + file, mime=True)
349-
print directory + file
348+
print(directory + file)
350349
guessed_exts = mimetypes.guess_all_extensions(mimetype)
351350
guessed_exts = [ext[1:] for ext in guessed_exts]
352351
common = [ext for ext in guessed_exts if ext in self.extensions]
@@ -358,7 +357,7 @@ def handle_form(self, form, files):
358357
)
359358
zip_ref.close()
360359
except Exception as e:
361-
print e
360+
print(e)
362361
messages.append('ERROR : Could not unzip the file.')
363362
if len(messages) == 0:
364363
messages.append('Extraction completed successfully.')
@@ -441,8 +440,8 @@ def media(self, path):
441440
mx = max([width, height])
442441
w, h = width, height
443442
if mx > 60:
444-
w = width*60/mx
445-
h = height*60/mx
443+
w = int(width*60/mx)
444+
h = int(height*60/mx)
446445
img = img.resize((w, h), Image.ANTIALIAS)
447446
response = HttpResponse(content_type="image/png")
448447
response['Cache-Control'] = 'max-age:3600'
@@ -454,11 +453,11 @@ def download(self, path, file_or_dir):
454453
return HttpResponse('Invalid path')
455454
if file_or_dir == 'file':
456455
filepath = self.basepath + '/' + path
457-
wrapper = FileWrapper(open(filepath))
458-
response = HttpResponse(
459-
wrapper,
460-
content_type=mimetypes.guess_type(filepath)[0],
461-
)
456+
with open(filepath, 'rb') as f:
457+
response = HttpResponse(
458+
f.read(),
459+
content_type=mimetypes.guess_type(filepath)[0],
460+
)
462461
response['Content-Length'] = os.path.getsize(filepath)
463462
response['Content-Disposition'] = (
464463
'attachment; filename=' + path.split('/')[-1]
@@ -499,7 +498,7 @@ def render(self, request, path):
499498
'filemanager/index.html',
500499
{
501500
'dir_structure': self.directory_structure(),
502-
'messages': map(str, messages),
501+
'messages': list(map(str, messages)),
503502
'current_id': self.current_id,
504503
'CKEditorFuncNum': CKEditorFuncNum,
505504
'ckeditor_baseurl': self.ckeditor_baseurl,

filemanager/templates/filemanager/index.html

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
{% load static %}
12
<!DOCTYPE html>
23
<html>
34
<head>
4-
<script type="text/javascript" src="{{STATIC_URL}}filemanager/js/jquery/jquery.min.js"></script>
5-
<script type="text/javascript" src="{{STATIC_URL}}filemanager/js/jquery/jquery-migrate.min.js"></script>
6-
<script type="text/javascript" src="{{STATIC_URL}}filemanager/js/jquery/zclip/jquery.zclip.min.js"></script>
7-
<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}filemanager/css/style.css"/>
5+
<script type="text/javascript" src="{% static "filemanager/js/jquery/jquery.min.js" %}"></script>
6+
<script type="text/javascript" src="{% static "filemanager/js/jquery/jquery-migrate.min.js" %}"></script>
7+
<script type="text/javascript" src="{% static "filemanager/js/jquery/zclip/jquery.zclip.min.js" %}"></script>
8+
<link rel="stylesheet" type="text/css" href="{% static "filemanager/css/style.css" %}"/>
89
<!--[if IE]>
910
<script type="text/javascript" src="{{ STATIC_URL }}js/es5-shim.min.js"></script>
1011
<![endif]-->
@@ -23,7 +24,7 @@
2324
var space_consumed = {{space_consumed}};
2425
var max_space = {{max_space}}*1024;
2526
</script>
26-
<script type="text/javascript" src="{{STATIC_URL}}filemanager/js/script.js"></script>
27+
<script type="text/javascript" src="{% static "filemanager/js/script.js"%}"></script>
2728

2829
</head>
2930
<body oncontextmenu='return false;'>
@@ -41,7 +42,7 @@
4142
<input type="text" id="file_or_dir" name="file_or_dir" value="" style="display:none;">
4243
<input type="submit" id="submit" name="submit" value="Submit" style="display:none;">
4344
<label class="control" id="upload-label" for="ufile">
44-
<img src="{{STATIC_URL}}filemanager/images/upload.png" style="width:16px;height:16px" width="100%" height="100%"/>
45+
<img src="{% static "filemanager/images/upload.png"%}" style="width:16px;height:16px" width="100%" height="100%"/>
4546
<span>Upload Files</span>
4647
</label>
4748
</form>
@@ -54,65 +55,65 @@
5455
</div>
5556
<div id="dom-menu" class="menu" style="display:none">
5657
<div id="add-dir" class="menu-option" onclick="do_action('add','dom')">
57-
<img src="{{STATIC_URL}}filemanager/images/add_folder.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Create Folder</span>
58+
<img src="{% static "filemanager/images/add_folder.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Create Folder</span>
5859
</div><hr>
5960
<div id="paste-dir" class="menu-option" onclick="do_action('paste','dom')">
60-
<img src="{{STATIC_URL}}filemanager/images/paste.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Paste</span>
61+
<img src="{% static "filemanager/images/paste.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Paste</span>
6162
</div><hr>
6263
<div id="download-dir" class="menu-option" onclick="do_action('download','dom')">
63-
<img src="{{STATIC_URL}}filemanager/images/download.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Download</span>
64+
<img src="{% static "filemanager/images/download.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Download</span>
6465
</div>
6566
</div>
6667
<div id="dir-menu" class="menu" style="display:none">
6768
<div id="add-dir" class="menu-option" onclick="do_action('add','dir')">
68-
<img src="{{STATIC_URL}}filemanager/images/add_folder.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Create Sub-Folder</span>
69+
<img src="{% static "filemanager/images/add_folder.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Create Sub-Folder</span>
6970
</div><hr>
7071
<div id="cut-dir" class="menu-option" onclick="do_action('cut','dir')">
71-
<img src="{{STATIC_URL}}filemanager/images/cut.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Cut</span>
72+
<img src="{% static "filemanager/images/cut.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Cut</span>
7273
</div><hr>
7374
<div id="copy-dir" class="menu-option" onclick="do_action('copy','dir')">
74-
<img src="{{STATIC_URL}}filemanager/images/copy.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Copy</span>
75+
<img src="{% static "filemanager/images/copy.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Copy</span>
7576
</div><hr>
7677
<div id="paste-dir" class="menu-option" onclick="do_action('paste','dir')">
77-
<img src="{{STATIC_URL}}filemanager/images/paste.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Paste</span>
78+
<img src="{% static "filemanager/images/paste.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Paste</span>
7879
</div><hr>
7980
<div id="rename-dir" class="menu-option" onclick="do_action('rename','dir')">
80-
<img src="{{STATIC_URL}}filemanager/images/rename.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Rename</span>
81+
<img src="{% static "filemanager/images/rename.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Rename</span>
8182
</div><hr>
8283
<div id="download-dir" class="menu-option" onclick="do_action('download','dir')">
83-
<img src="{{STATIC_URL}}filemanager/images/download.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Download</span>
84+
<img src="{% static "filemanager/images/download.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Download</span>
8485
</div><hr>
8586
<div id="delete-dir" class="menu-option" onclick="do_action('delete','dir')">
86-
<img src="{{STATIC_URL}}filemanager/images/delete.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Delete</span>
87+
<img src="{% static "filemanager/images/delete.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Delete</span>
8788
</div>
8889
</div>
8990
<div id="file-menu" class="menu" style="display:none">
9091
<div id="rename-file" class="menu-option" onclick="do_action('rename','file')">
91-
<img src="{{STATIC_URL}}filemanager/images/rename.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Rename</span>
92+
<img src="{% static "filemanager/images/rename.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Rename</span>
9293
</div><hr>
9394
<div id="unzip-file" class="menu-option unzip-menu" onclick="do_action('unzip','file')" style="display:none">
94-
<img src="{{STATIC_URL}}filemanager/images/unzip.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Unzip</span>
95+
<img src="{% static "filemanager/images/unzip.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Unzip</span>
9596
</div><hr class="unzip-menu" style="display:none">
9697
<div id="cut-file" class="menu-option" onclick="do_action('cut','file')">
97-
<img src="{{STATIC_URL}}filemanager/images/cut.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Cut</span>
98+
<img src="{% static "filemanager/images/cut.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Cut</span>
9899
</div><hr>
99100
<div id="copy-file" class="menu-option" onclick="do_action('copy','file')">
100-
<img src="{{STATIC_URL}}filemanager/images/copy.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Copy</span>
101+
<img src="{% static "filemanager/images/copy.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Copy</span>
101102
</div><hr>
102103
<div id="download-file" class="menu-option" onclick="do_action('download','file')">
103-
<img src="{{STATIC_URL}}filemanager/images/download.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Download</span>
104+
<img src="{% static "filemanager/images/download.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Download</span>
104105
</div><hr>
105106
<div id="delete-file" class="menu-option" onclick="do_action('delete','file')">
106-
<img src="{{STATIC_URL}}filemanager/images/delete.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Delete</span>
107+
<img src="{% static "filemanager/images/delete.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Delete</span>
107108
</div>
108109
{% if public_url_base %}
109110
<hr>
110111
<div id="copy-public-link-file" class="menu-option">
111-
<img src="{{STATIC_URL}}filemanager/images/copy_public_link.png" style="width:16px;height:16px" width="100%" height="100%"/><span>Copy public link</span>
112+
<img src="{% static "filemanager/images/copy_public_link.png"%}" style="width:16px;height:16px" width="100%" height="100%"/><span>Copy public link</span>
112113
</div>
113114
{% endif %}
114115
</div> <div id="popup">
115-
<div class="div1"><img src='{{STATIC_URL}}filemanager/images/close.png' onclick="$('#popup').hide();"/>
116+
<div class="div1"><img src="{% static "filemanager/images/close.png"%}" onclick="$('#popup').hide();"/>
116117
<div id="heading"></div></div>
117118
<div class="div2"><input id="input" type="text"></div>
118119
</div>

filemanager/widgets.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django import forms
22
from django.utils.safestring import mark_safe
33

4-
from settings import FILEMANAGER_CKEDITOR_JS
4+
from .settings import FILEMANAGER_CKEDITOR_JS
55

66

77
def filemanager_config(url):

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
django>=1.7,<1.8
1+
django>=1.7,<1.11.99
22
Pillow
33
python-magic # python-magic-bin==0.4.14 for MAC users

0 commit comments

Comments
 (0)