Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
AE UTBM
Sith
Commits
8e3eb1e2
Commit
8e3eb1e2
authored
Aug 22, 2016
by
Skia
🤘
Browse files
Some templating and add webcam support for profile editing
parent
4cbfd586
Pipeline
#134
failed with stage
in 2 minutes and 49 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
core/static/core/js/webcam.js
0 → 100644
View file @
8e3eb1e2
// WebcamJS v1.0
// Webcam library for capturing JPEG/PNG images in JavaScript
// Attempts getUserMedia, falls back to Flash
// Author: Joseph Huckaby: http://github.com/jhuckaby
// Based on JPEGCam: http://code.google.com/p/jpegcam/
// Copyright (c) 2012 Joseph Huckaby
// Licensed under the MIT License
/* Usage:
<div id="my_camera" style="width:320px; height:240px;"></div>
<div id="my_result"></div>
<script language="JavaScript">
Webcam.attach( '#my_camera' );
function take_snapshot() {
var data_uri = Webcam.snap();
document.getElementById('my_result').innerHTML =
'<img src="'+data_uri+'"/>';
}
</script>
<a href="javascript:void(take_snapshot())">Take Snapshot</a>
*/
var
Webcam
=
{
version
:
'
1.0.0
'
,
// globals
protocol
:
location
.
protocol
.
match
(
/https/i
)
?
'
https
'
:
'
http
'
,
swfURL
:
''
,
// URI to webcam.swf movie (defaults to cwd)
loaded
:
false
,
// true when webcam movie finishes loading
live
:
false
,
// true when webcam is initialized and ready to snap
userMedia
:
true
,
// true when getUserMedia is supported natively
params
:
{
width
:
0
,
height
:
0
,
dest_width
:
0
,
// size of captured image
dest_height
:
0
,
// these default to width/height
image_format
:
'
jpeg
'
,
// image format (may be jpeg or png)
jpeg_quality
:
90
,
// jpeg image quality from 0 (worst) to 100 (best)
force_flash
:
false
// force flash mode
},
hooks
:
{
load
:
null
,
live
:
null
,
uploadcomplete
:
null
,
uploadprogress
:
null
,
error
:
function
(
msg
)
{
alert
(
"
Webcam.js Error:
"
+
msg
);
}
},
// callback hook functions
init
:
function
()
{
// initialize, check for getUserMedia support
navigator
.
getUserMedia
=
navigator
.
getUserMedia
||
navigator
.
webkitGetUserMedia
||
navigator
.
mozGetUserMedia
||
navigator
.
msGetUserMedia
;
window
.
URL
=
window
.
URL
||
window
.
webkitURL
||
window
.
mozURL
||
window
.
msURL
;
this
.
userMedia
=
this
.
userMedia
&&
!!
navigator
.
getUserMedia
&&
!!
window
.
URL
;
// Older versions of firefox (< 21) apparently claim support but user media does not actually work
if
(
navigator
.
userAgent
.
match
(
/Firefox
\D
+
(\d
+
)
/
))
{
if
(
parseInt
(
RegExp
.
$1
,
10
)
<
21
)
this
.
userMedia
=
null
;
}
},
attach
:
function
(
elem
)
{
// create webcam preview and attach to DOM element
// pass in actual DOM reference, ID, or CSS selector
if
(
typeof
(
elem
)
==
'
string
'
)
{
elem
=
document
.
getElementById
(
elem
)
||
document
.
querySelector
(
elem
);
}
if
(
!
elem
)
{
return
this
.
dispatch
(
'
error
'
,
"
Could not locate DOM element to attach to.
"
);
}
this
.
container
=
elem
;
if
(
!
this
.
params
.
width
)
this
.
params
.
width
=
elem
.
offsetWidth
;
if
(
!
this
.
params
.
height
)
this
.
params
.
height
=
elem
.
offsetHeight
;
// set defaults for dest_width / dest_height if not set
if
(
!
this
.
params
.
dest_width
)
this
.
params
.
dest_width
=
this
.
params
.
width
;
if
(
!
this
.
params
.
dest_height
)
this
.
params
.
dest_height
=
this
.
params
.
height
;
// if force_flash is set, disable userMedia
if
(
this
.
params
.
force_flash
)
this
.
userMedia
=
null
;
if
(
this
.
userMedia
)
{
// setup webcam video container
var
video
=
document
.
createElement
(
'
video
'
);
video
.
setAttribute
(
'
autoplay
'
,
'
autoplay
'
);
video
.
style
.
width
=
''
+
this
.
params
.
dest_width
+
'
px
'
;
video
.
style
.
height
=
''
+
this
.
params
.
dest_height
+
'
px
'
;
// adjust scale if dest_width or dest_height is different
var
scaleX
=
this
.
params
.
width
/
this
.
params
.
dest_width
;
var
scaleY
=
this
.
params
.
height
/
this
.
params
.
dest_height
;
if
((
scaleX
!=
1.0
)
||
(
scaleY
!=
1.0
))
{
elem
.
style
.
overflow
=
'
visible
'
;
video
.
style
.
webkitTransformOrigin
=
'
0px 0px
'
;
video
.
style
.
mozTransformOrigin
=
'
0px 0px
'
;
video
.
style
.
msTransformOrigin
=
'
0px 0px
'
;
video
.
style
.
oTransformOrigin
=
'
0px 0px
'
;
video
.
style
.
transformOrigin
=
'
0px 0px
'
;
video
.
style
.
webkitTransform
=
'
scaleX(
'
+
scaleX
+
'
) scaleY(
'
+
scaleY
+
'
)
'
;
video
.
style
.
mozTransform
=
'
scaleX(
'
+
scaleX
+
'
) scaleY(
'
+
scaleY
+
'
)
'
;
video
.
style
.
msTransform
=
'
scaleX(
'
+
scaleX
+
'
) scaleY(
'
+
scaleY
+
'
)
'
;
video
.
style
.
oTransform
=
'
scaleX(
'
+
scaleX
+
'
) scaleY(
'
+
scaleY
+
'
)
'
;
video
.
style
.
transform
=
'
scaleX(
'
+
scaleX
+
'
) scaleY(
'
+
scaleY
+
'
)
'
;
}
// add video element to dom
elem
.
appendChild
(
video
);
this
.
video
=
video
;
// create offscreen canvas element to hold pixels later on
var
canvas
=
document
.
createElement
(
'
canvas
'
);
canvas
.
width
=
this
.
params
.
dest_width
;
canvas
.
height
=
this
.
params
.
dest_height
;
var
context
=
canvas
.
getContext
(
'
2d
'
);
this
.
context
=
context
;
this
.
canvas
=
canvas
;
// ask user for access to their camera
var
self
=
this
;
navigator
.
getUserMedia
({
"
audio
"
:
false
,
"
video
"
:
true
},
function
(
stream
)
{
// got access, attach stream to video
video
.
src
=
window
.
URL
.
createObjectURL
(
stream
)
||
stream
;
Webcam
.
stream
=
stream
;
Webcam
.
loaded
=
true
;
Webcam
.
live
=
true
;
Webcam
.
dispatch
(
'
load
'
);
Webcam
.
dispatch
(
'
live
'
);
},
function
(
err
)
{
return
self
.
dispatch
(
'
error
'
,
"
Could not access webcam.
"
);
});
}
else
{
// flash fallback
elem
.
innerHTML
=
this
.
getSWFHTML
();
}
},
reset
:
function
()
{
// shutdown camera, reset to potentially attach again
if
(
this
.
userMedia
)
{
try
{
this
.
stream
.
stop
();
}
catch
(
e
)
{;}
delete
this
.
stream
;
delete
this
.
canvas
;
delete
this
.
context
;
delete
this
.
video
;
}
this
.
container
.
innerHTML
=
''
;
delete
this
.
container
;
this
.
loaded
=
false
;
this
.
live
=
false
;
},
set
:
function
()
{
// set one or more params
// variable argument list: 1 param = hash, 2 params = key, value
if
(
arguments
.
length
==
1
)
{
for
(
var
key
in
arguments
[
0
])
{
this
.
params
[
key
]
=
arguments
[
0
][
key
];
}
}
else
{
this
.
params
[
arguments
[
0
]
]
=
arguments
[
1
];
}
},
on
:
function
(
name
,
callback
)
{
// set callback hook
// supported hooks: onLoad, onError, onLive
name
=
name
.
replace
(
/^on/i
,
''
).
toLowerCase
();
if
(
typeof
(
this
.
hooks
[
name
])
==
'
undefined
'
)
throw
"
Event type not supported:
"
+
name
;
this
.
hooks
[
name
]
=
callback
;
},
dispatch
:
function
()
{
// fire hook callback, passing optional value to it
var
name
=
arguments
[
0
].
replace
(
/^on/i
,
''
).
toLowerCase
();
var
args
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
);
if
(
this
.
hooks
[
name
])
{
if
(
typeof
(
this
.
hooks
[
name
])
==
'
function
'
)
{
// callback is function reference, call directly
this
.
hooks
[
name
].
apply
(
this
,
args
);
}
else
if
(
typeof
(
this
.
hooks
[
name
])
==
'
array
'
)
{
// callback is PHP-style object instance method
this
.
hooks
[
name
][
0
][
this
.
hooks
[
name
][
1
]].
apply
(
this
.
hooks
[
name
][
0
],
args
);
}
else
if
(
window
[
this
.
hooks
[
name
]])
{
// callback is global function name
window
[
this
.
hooks
[
name
]
].
apply
(
window
,
args
);
}
return
true
;
}
return
false
;
// no hook defined
},
setSWFLocation
:
function
(
url
)
{
// set location of SWF movie (defaults to webcam.swf in cwd)
this
.
swfURL
=
url
;
},
getSWFHTML
:
function
()
{
// Return HTML for embedding flash based webcam capture movie
var
html
=
''
;
// make sure we aren't running locally (flash doesn't work)
if
(
location
.
protocol
.
match
(
/file/
))
{
return
'
<h1 style="color:red">Sorry, the Webcam.js Flash fallback does not work from local disk. Please upload it to a web server first.</h1>
'
;
}
// set default swfURL if not explicitly set
if
(
!
this
.
swfURL
)
{
// find our script tag, and use that base URL
var
base_url
=
''
;
var
scpts
=
document
.
getElementsByTagName
(
'
script
'
);
for
(
var
idx
=
0
,
len
=
scpts
.
length
;
idx
<
len
;
idx
++
)
{
var
src
=
scpts
[
idx
].
getAttribute
(
'
src
'
);
if
(
src
&&
src
.
match
(
/
\/
webcam
(\.
min
)?\.
js/
))
{
base_url
=
src
.
replace
(
/
\/
webcam
(\.
min
)?\.
js.*$/
,
''
);
idx
=
len
;
}
}
if
(
base_url
)
this
.
swfURL
=
base_url
+
'
/webcam.swf
'
;
else
this
.
swfURL
=
'
webcam.swf
'
;
}
// if this is the user's first visit, set flashvar so flash privacy settings panel is shown first
if
(
window
.
localStorage
&&
!
localStorage
.
getItem
(
'
visited
'
))
{
this
.
params
.
new_user
=
1
;
localStorage
.
setItem
(
'
visited
'
,
1
);
}
// construct flashvars string
var
flashvars
=
''
;
for
(
var
key
in
this
.
params
)
{
if
(
flashvars
)
flashvars
+=
'
&
'
;
flashvars
+=
key
+
'
=
'
+
escape
(
this
.
params
[
key
]);
}
html
+=
'
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" type="application/x-shockwave-flash" codebase="
'
+
this
.
protocol
+
'
://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="
'
+
this
.
params
.
width
+
'
" height="
'
+
this
.
params
.
height
+
'
" id="webcam_movie_obj" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="
'
+
this
.
swfURL
+
'
" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="
'
+
flashvars
+
'
"/><embed id="webcam_movie_embed" src="
'
+
this
.
swfURL
+
'
" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="
'
+
this
.
params
.
width
+
'
" height="
'
+
this
.
params
.
height
+
'
" name="webcam_movie_embed" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="
'
+
flashvars
+
'
"></embed></object>
'
;
return
html
;
},
getMovie
:
function
()
{
// get reference to movie object/embed in DOM
if
(
!
this
.
loaded
)
return
this
.
dispatch
(
'
error
'
,
"
Flash Movie is not loaded yet
"
);
var
movie
=
document
.
getElementById
(
'
webcam_movie_obj
'
);
if
(
!
movie
||
!
movie
.
_snap
)
movie
=
document
.
getElementById
(
'
webcam_movie_embed
'
);
if
(
!
movie
)
this
.
dispatch
(
'
error
'
,
"
Cannot locate Flash movie in DOM
"
);
return
movie
;
},
snap
:
function
()
{
// take snapshot and return image data uri
if
(
!
this
.
loaded
)
return
this
.
dispatch
(
'
error
'
,
"
Webcam is not loaded yet
"
);
if
(
!
this
.
live
)
return
this
.
dispatch
(
'
error
'
,
"
Webcam is not live yet
"
);
if
(
this
.
userMedia
)
{
// native implementation
this
.
context
.
drawImage
(
this
.
video
,
0
,
0
,
this
.
params
.
dest_width
,
this
.
params
.
dest_height
);
return
this
.
canvas
.
toDataURL
(
'
image/
'
+
this
.
params
.
image_format
,
this
.
params
.
jpeg_quality
/
100
);
}
else
{
// flash fallback
var
raw_data
=
this
.
getMovie
().
_snap
();
return
'
data:image/
'
+
this
.
params
.
image_format
+
'
;base64,
'
+
raw_data
;
}
},
configure
:
function
(
panel
)
{
// open flash configuration panel -- specify tab name:
// "camera", "privacy", "default", "localStorage", "microphone", "settingsManager"
if
(
!
panel
)
panel
=
"
camera
"
;
this
.
getMovie
().
_configure
(
panel
);
},
flashNotify
:
function
(
type
,
msg
)
{
// receive notification from flash about event
switch
(
type
)
{
case
'
flashLoadComplete
'
:
// movie loaded successfully
this
.
loaded
=
true
;
this
.
dispatch
(
'
load
'
);
break
;
case
'
cameraLive
'
:
// camera is live and ready to snap
this
.
live
=
true
;
this
.
dispatch
(
'
live
'
);
break
;
case
'
error
'
:
// Flash error
this
.
dispatch
(
'
error
'
,
msg
);
break
;
default
:
// catch-all event, just in case
// console.log("webcam flash_notify: " + type + ": " + msg);
break
;
}
},
b64ToUint6
:
function
(
nChr
)
{
// convert base64 encoded character to 6-bit integer
// from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
return
nChr
>
64
&&
nChr
<
91
?
nChr
-
65
:
nChr
>
96
&&
nChr
<
123
?
nChr
-
71
:
nChr
>
47
&&
nChr
<
58
?
nChr
+
4
:
nChr
===
43
?
62
:
nChr
===
47
?
63
:
0
;
},
base64DecToArr
:
function
(
sBase64
,
nBlocksSize
)
{
// convert base64 encoded string to Uintarray
// from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
var
sB64Enc
=
sBase64
.
replace
(
/
[^
A-Za-z0-9
\+\/]
/g
,
""
),
nInLen
=
sB64Enc
.
length
,
nOutLen
=
nBlocksSize
?
Math
.
ceil
((
nInLen
*
3
+
1
>>
2
)
/
nBlocksSize
)
*
nBlocksSize
:
nInLen
*
3
+
1
>>
2
,
taBytes
=
new
Uint8Array
(
nOutLen
);
for
(
var
nMod3
,
nMod4
,
nUint24
=
0
,
nOutIdx
=
0
,
nInIdx
=
0
;
nInIdx
<
nInLen
;
nInIdx
++
)
{
nMod4
=
nInIdx
&
3
;
nUint24
|=
this
.
b64ToUint6
(
sB64Enc
.
charCodeAt
(
nInIdx
))
<<
18
-
6
*
nMod4
;
if
(
nMod4
===
3
||
nInLen
-
nInIdx
===
1
)
{
for
(
nMod3
=
0
;
nMod3
<
3
&&
nOutIdx
<
nOutLen
;
nMod3
++
,
nOutIdx
++
)
{
taBytes
[
nOutIdx
]
=
nUint24
>>>
(
16
>>>
nMod3
&
24
)
&
255
;
}
nUint24
=
0
;
}
}
return
taBytes
;
},
upload
:
function
(
image_data_uri
,
target_url
,
callback
,
form_elem_name
=
'
webcam
'
,
csrf
=
null
)
{
// submit image data to server using binary AJAX
if
(
callback
)
Webcam
.
on
(
'
uploadComplete
'
,
callback
);
// detect image format from within image_data_uri
var
image_fmt
=
''
;
if
(
image_data_uri
.
match
(
/^data
\:
image
\/(\w
+
)
/
))
image_fmt
=
RegExp
.
$1
;
else
throw
"
Cannot locate image format in Data URI
"
;
// extract raw base64 data from Data URI
var
raw_image_data
=
image_data_uri
.
replace
(
/^data
\:
image
\/\w
+
\;
base64
\,
/
,
''
);
// contruct use AJAX object
var
http
=
new
XMLHttpRequest
();
http
.
open
(
"
POST
"
,
target_url
,
true
);
// setup progress events
if
(
http
.
upload
&&
http
.
upload
.
addEventListener
)
{
http
.
upload
.
addEventListener
(
'
progress
'
,
function
(
e
)
{
if
(
e
.
lengthComputable
)
{
var
progress
=
e
.
loaded
/
e
.
total
;
Webcam
.
dispatch
(
'
uploadProgress
'
,
progress
,
e
);
}
},
false
);
}
// completion handler
http
.
onload
=
function
()
{
Webcam
.
dispatch
(
'
uploadComplete
'
,
http
.
status
,
http
.
responseText
,
http
.
statusText
);
};
// create a blob and decode our base64 to binary
var
blob
=
new
Blob
(
[
this
.
base64DecToArr
(
raw_image_data
)
],
{
type
:
'
image/
'
+
image_fmt
}
);
// stuff into a form, so servers can easily receive it as a standard file upload
var
form
=
new
FormData
();
if
(
csrf
)
form
.
append
(
csrf
.
name
,
csrf
.
value
);
form
.
append
(
form_elem_name
,
blob
,
form_elem_name
+
"
.
"
+
image_fmt
.
replace
(
/e/
,
''
)
);
// send data to server
http
.
send
(
form
);
}
};
Webcam
.
init
();
core/templates/core/base.jinja
View file @
8e3eb1e2
...
...
@@ -96,6 +96,7 @@ $('.select_date').datepicker({
}).
datepicker
(
$
.
datepicker
.
regional
[
"
{{
request.LANGUAGE_CODE
}}
"
]
);
$
(
document
).
keydown
(
function
(
e
)
{
if
(
$
(
e
.
target
).
is
(
'
input
'
))
{
return
}
if
(
$
(
e
.
target
).
is
(
'
textarea
'
))
{
return
}
if
(
e
.
keyCode
==
83
)
{
$
(
"
#search
"
).
focus
();
return
false
;
...
...
core/templates/core/user_edit.jinja
View file @
8e3eb1e2
...
...
@@ -10,9 +10,21 @@
{%
csrf_token
%}
{%
for
field
in
form
%}
<p>
{{
field.errors
}}
<label
for=
"
{{
field.name
}}
"
>
{{
field.label
}}
{%
-
if
field.name
==
"profile_pict"
and
form.instance.profile_pict
-
%}
{%
-
if
field.name
==
"profile_pict"
-
%}
<br>
{%
trans
%}
Current profile:
{%
endtrans
%}
{%
if
form.instance.profile_pict
%}
<img
src=
"
{{
form.instance.profile_pict.get_download_url
()
}}
"
title=
"
{%
trans
%}
Profile
{%
endtrans
%}
"
/><br>
{%
if
user.is_in_group
(
settings.SITH_MAIN_BOARD_GROUP
)
%}
<a
href=
"
{{
url
(
'core:file_delete'
,
file_id
=
form.instance.profile_pict.id
,
popup
=
""
)
}}
"
>
{%
trans
%}
Delete
{%
endtrans
%}
</a>
{%
endif
%}
{%
else
%}
<img
src=
"
{{
static
(
'core/img/unknown.jpg'
)
}}
"
title=
"-"
crossOrigin=
"Anonymous"
id=
"new_profile"
/><br>
<div
id=
"take_picture"
>
<div
id=
"camera_canvas"
style=
"width:320; height:240; margin: 0px auto;"
></div>
<a
href=
"javascript:void(take_snapshot())"
>
{%
trans
%}
Take picture
{%
endtrans
%}
</a>
</div>
<p>
{%
endif
%}
<br>
{%
-
elif
field.name
==
"avatar_pict"
and
form.instance.avatar_pict
-
%}
<br>
{%
trans
%}
Current avatar:
{%
endtrans
%}
<img
src=
"
{{
form.instance.avatar_pict.get_download_url
()
}}
"
title=
"
{%
trans
%}
Avatar
{%
endtrans
%}
"
/><br>
...
...
@@ -34,6 +46,39 @@
</form>
{%
endblock
%}
{%
block
script
%}
{{
super
()
}}
{%
if
not
form.instance.profile_pict
%}
<script
src=
"
{{
static
(
'core/js/webcam.js'
)
}}
"
></script>
<script
language=
"JavaScript"
>
Webcam
.
set
({
width
:
320
,
height
:
240
,
dest_width
:
320
,
dest_height
:
240
,
image_format
:
'
jpeg
'
,
jpeg_quality
:
90
,
force_flash
:
false
});
Webcam
.
attach
(
'
#camera_canvas
'
);
function
take_snapshot
()
{
var
data_uri
=
Webcam
.
snap
();
var
url
=
"
{{
url
(
'core:user_profile_upload'
,
user_id
=
form.instance.id
)
}}
"
;
Webcam
.
upload
(
data_uri
,
url
,
function
(
code
,
text
)
{
if
(
code
==
200
)
{
$
(
'
#new_profile
'
).
attr
(
'
src
'
,
data_uri
);
$
(
'
#take_picture
'
).
remove
();
$
(
'
#id_profile_pict
'
).
remove
();
}
else
{
console
.
log
(
"
Unknown error:
"
);
console
.
log
(
text
);
}
},
"
new_profile_pict
"
,
{
name
:
'
csrfmiddlewaretoken
'
,
value
:
'
{{
csrf_token
}}
'
});
}
</script>
{%
endif
%}
{%
endblock
%}
core/urls.py
View file @
8e3eb1e2
...
...
@@ -31,6 +31,7 @@ urlpatterns = [
url
(
r
'^user/(?P<user_id>[0-9]+)/mini$'
,
UserMiniView
.
as_view
(),
name
=
'user_profile_mini'
),
url
(
r
'^user/(?P<user_id>[0-9]+)/$'
,
UserView
.
as_view
(),
name
=
'user_profile'
),
url
(
r
'^user/(?P<user_id>[0-9]+)/edit$'
,
UserUpdateProfileView
.
as_view
(),
name
=
'user_edit'
),
url
(
r
'^user/(?P<user_id>[0-9]+)/profile_upload$'
,
UserUploadProfilePictView
.
as_view
(),
name
=
'user_profile_upload'
),
url
(
r
'^user/(?P<user_id>[0-9]+)/groups$'
,
UserUpdateGroupView
.
as_view
(),
name
=
'user_groups'
),
url
(
r
'^user/tools/$'
,
UserToolsView
.
as_view
(),
name
=
'user_tools'
),
url
(
r
'^user/(?P<user_id>[0-9]+)/account$'
,
UserAccountView
.
as_view
(),
name
=
'user_account'
),
...
...
core/utils.py
0 → 100644
View file @
8e3eb1e2
# Image utils
from
io
import
BytesIO
from
PIL
import
Image
def
scale_dimension
(
width
,
height
,
long_edge
):
if
width
>
height
:
ratio
=
long_edge
*
1.
/
width
else
:
ratio
=
long_edge
*
1.
/
height
return
int
(
width
*
ratio
),
int
(
height
*
ratio
)
def
resize_image
(
im
,
edge
,
format
):
# TODO move that into a utils file
from
django.core.files.base
import
ContentFile
(
w
,
h
)
=
im
.
size
(
width
,
height
)
=
scale_dimension
(
w
,
h
,
long_edge
=
edge
)
content
=
BytesIO
()
im
.
resize
((
width
,
height
),
Image
.
ANTIALIAS
).
save
(
fp
=
content
,
format
=
format
,
dpi
=
[
72
,
72
])
return
ContentFile
(
content
.
getvalue
())
core/views/forms.py
View file @
8e3eb1e2
...
...
@@ -83,26 +83,10 @@ class RegisteringForm(UserCreationForm):
user
.
save
()
return
user
# Image utils
from
core.utils
import
resize_image
from
io
import
BytesIO
from
PIL
import
Image
def
scale_dimension
(
width
,
height
,
long_edge
):
if
width
>
height
:
ratio
=
long_edge
*
1.
/
width
else
:
ratio
=
long_edge
*
1.
/
height
return
int
(
width
*
ratio
),
int
(
height
*
ratio
)
def
resize_image
(
im
,
edge
,
format
):
from
django.core.files.base
import
ContentFile
(
w
,
h
)
=
im
.
size
(
width
,
height
)
=
scale_dimension
(
w
,
h
,
long_edge
=
edge
)
content
=
BytesIO
()
im
.
resize
((
width
,
height
),
Image
.
ANTIALIAS
).
save
(
fp
=
content
,
format
=
format
,
dpi
=
[
72
,
72
])
return
ContentFile
(
content
.
getvalue
())
class
UserProfileForm
(
forms
.
ModelForm
):
"""
Form handling the user profile, managing the files
...
...
core/views/user.py
View file @
8e3eb1e2
# This file contains all the views that concern the user model
from
django.shortcuts
import
render
,
redirect
,
get_object_or_404
from
django.contrib.auth
import
logout
as
auth_logout
,
views
from
django.utils.translation
import
ugettext
as
_
from
django.core.urlresolvers
import
reverse
from
django.core.exceptions
import
PermissionDenied
,
ObjectDoesNotExist
from
django.core.exceptions
import
PermissionDenied
,
ObjectDoesNotExist
,
ValidationError
from
django.http
import
Http404
from
django.views.generic.edit
import
UpdateView
from
django.views.generic
import
ListView
,
DetailView
,
TemplateView
...
...
@@ -16,7 +17,7 @@ import logging
from
core.views
import
CanViewMixin
,
CanEditMixin
,
CanEditPropMixin
from
core.views.forms
import
RegisteringForm
,
UserPropForm
,
UserProfileForm
from
core.models
import
User
from
core.models
import
User
,
SithFile
def
login
(
request
):
"""
...
...
@@ -160,6 +161,35 @@ class UserListView(ListView):
model
=
User
template_name
=
"core/user_list.jinja"
class
UserUploadProfilePictView
(
CanEditMixin
,
DetailView
):
"""
Handle the upload of the profile picture taken with webcam in navigator
"""
model
=
User
pk_url_kwarg
=
"user_id"
template_name
=
"core/user_edit.jinja"
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
from
core.utils
import
resize_image
from
io
import
BytesIO
from
PIL
import
Image
self
.
object
=
self
.
get_object
()
if
self
.
object
.
profile_pict
:
raise
ValidationError
(
_
(
"User already has a profile picture"
))
print
(
request
.
FILES
[
'new_profile_pict'
])
f
=
request
.
FILES
[
'new_profile_pict'
]
parent
=
SithFile
.
objects
.
filter
(
parent
=
None
,
name
=
"profiles"
).
first
()
name
=
str
(
self
.
object
.
id
)
+
"_profile.jpg"
# Webcamejs uploads JPGs
im
=
Image
.
open
(
BytesIO
(
f
.
read
()))
new_file
=
SithFile
(
parent
=
parent
,
name
=
name
,
file
=
resize_image
(
im
,
400
,
f
.
content_type
.
split
(
'/'
)[
-
1
]),
owner
=
self
.
object
,
is_folder
=
False
,
mime_type
=
f
.
content_type
,
size
=
f
.
_size
)
new_file
.
file
.
name
=
name
new_file
.
save
()
self
.
object
.
profile_pict
=
new_file
self
.
object
.
save
()
return
redirect
(
"core:user_edit"
,
user_id
=
self
.
object
.
id
)
class
UserUpdateProfileView
(
CanEditMixin
,
UpdateView
):
"""
Edit a user's profile
...
...
counter/migrations/0020_auto_20160821_0307.py
0 → 100644
View file @
8e3eb1e2
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals