Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
ea8a56da
Commit
ea8a56da
authored
Jan 04, 2013
by
Brian Wilson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add id generation and validation
parent
e32dfcf0
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
162 additions
and
86 deletions
+162
-86
common/djangoapps/student/migrations/0022_add_more_fields_to_test_center_user.py
+37
-23
common/djangoapps/student/models.py
+102
-35
common/djangoapps/student/views.py
+19
-13
lms/templates/dashboard.html
+1
-1
lms/templates/test_center_register.html
+3
-14
No files found.
common/djangoapps/student/migrations/0022_add_more_fields_to_test_center_user.py
View file @
ea8a56da
...
@@ -8,29 +8,15 @@ from django.db import models
...
@@ -8,29 +8,15 @@ from django.db import models
class
Migration
(
SchemaMigration
):
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
def
forwards
(
self
,
orm
):
# Adding field 'TestCenterUser.upload_status'
db
.
add_column
(
'student_testcenteruser'
,
'upload_status'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
default
=
''
,
max_length
=
20
,
blank
=
True
),
keep_default
=
False
)
# Adding field 'TestCenterUser.uploaded_at'
db
.
add_column
(
'student_testcenteruser'
,
'uploaded_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
null
=
True
,
db_index
=
True
),
keep_default
=
False
)
# Adding field 'TestCenterUser.upload_error_message'
db
.
add_column
(
'student_testcenteruser'
,
'upload_error_message'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
default
=
''
,
max_length
=
512
,
blank
=
True
),
keep_default
=
False
)
# Adding model 'TestCenterRegistration'
# Adding model 'TestCenterRegistration'
db
.
create_table
(
'student_testcenterregistration'
,
(
db
.
create_table
(
'student_testcenterregistration'
,
(
(
'id'
,
self
.
gf
(
'django.db.models.fields.AutoField'
)(
primary_key
=
True
)),
(
'id'
,
self
.
gf
(
'django.db.models.fields.AutoField'
)(
primary_key
=
True
)),
(
'testcenter_user'
,
self
.
gf
(
'django.db.models.fields.related.ForeignKey'
)(
default
=
None
,
to
=
orm
[
'student.TestCenterUser'
]
,
unique
=
True
)),
(
'testcenter_user'
,
self
.
gf
(
'django.db.models.fields.related.ForeignKey'
)(
default
=
None
,
to
=
orm
[
'student.TestCenterUser'
])),
(
'course_id'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
128
,
db_index
=
True
)),
(
'course_id'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
128
,
db_index
=
True
)),
(
'created_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
auto_now_add
=
True
,
db_index
=
True
,
blank
=
True
)),
(
'created_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
auto_now_add
=
True
,
db_index
=
True
,
blank
=
True
)),
(
'updated_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
auto_now
=
True
,
db_index
=
True
,
blank
=
True
)),
(
'updated_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
auto_now
=
True
,
db_index
=
True
,
blank
=
True
)),
(
'user_updated_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
db_index
=
True
)),
(
'user_updated_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
db_index
=
True
)),
(
'client_authorization_id'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
unique
=
True
,
max_length
=
20
,
db_index
=
True
)),
(
'exam_series_code'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
15
,
db_index
=
True
)),
(
'exam_series_code'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
15
,
db_index
=
True
)),
(
'eligibility_appointment_date_first'
,
self
.
gf
(
'django.db.models.fields.DateField'
)(
db_index
=
True
)),
(
'eligibility_appointment_date_first'
,
self
.
gf
(
'django.db.models.fields.DateField'
)(
db_index
=
True
)),
(
'eligibility_appointment_date_last'
,
self
.
gf
(
'django.db.models.fields.DateField'
)(
db_index
=
True
)),
(
'eligibility_appointment_date_last'
,
self
.
gf
(
'django.db.models.fields.DateField'
)(
db_index
=
True
)),
...
@@ -42,8 +28,35 @@ class Migration(SchemaMigration):
...
@@ -42,8 +28,35 @@ class Migration(SchemaMigration):
))
))
db
.
send_create_signal
(
'student'
,
[
'TestCenterRegistration'
])
db
.
send_create_signal
(
'student'
,
[
'TestCenterRegistration'
])
# Adding field 'TestCenterUser.upload_status'
db
.
add_column
(
'student_testcenteruser'
,
'upload_status'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
db_index
=
True
,
default
=
''
,
max_length
=
20
,
blank
=
True
),
keep_default
=
False
)
# Adding field 'TestCenterUser.uploaded_at'
db
.
add_column
(
'student_testcenteruser'
,
'uploaded_at'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
db_index
=
True
,
null
=
True
,
blank
=
True
),
keep_default
=
False
)
# Adding field 'TestCenterUser.upload_error_message'
db
.
add_column
(
'student_testcenteruser'
,
'upload_error_message'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
default
=
''
,
max_length
=
512
,
blank
=
True
),
keep_default
=
False
)
# Adding index on 'TestCenterUser', fields ['company_name']
db
.
create_index
(
'student_testcenteruser'
,
[
'company_name'
])
# Adding unique constraint on 'TestCenterUser', fields ['client_candidate_id']
db
.
create_unique
(
'student_testcenteruser'
,
[
'client_candidate_id'
])
def
backwards
(
self
,
orm
):
def
backwards
(
self
,
orm
):
# Removing unique constraint on 'TestCenterUser', fields ['client_candidate_id']
db
.
delete_unique
(
'student_testcenteruser'
,
[
'client_candidate_id'
])
# Removing index on 'TestCenterUser', fields ['company_name']
db
.
delete_index
(
'student_testcenteruser'
,
[
'company_name'
])
# Deleting model 'TestCenterRegistration'
# Deleting model 'TestCenterRegistration'
db
.
delete_table
(
'student_testcenterregistration'
)
db
.
delete_table
(
'student_testcenterregistration'
)
...
@@ -126,17 +139,17 @@ class Migration(SchemaMigration):
...
@@ -126,17 +139,17 @@ class Migration(SchemaMigration):
'accommodation_code'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'64'
,
'blank'
:
'True'
}),
'accommodation_code'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'64'
,
'blank'
:
'True'
}),
'accommodation_request'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'1024'
,
'blank'
:
'True'
}),
'accommodation_request'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'1024'
,
'blank'
:
'True'
}),
'client_authorization_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'20'
,
'db_index'
:
'True'
}),
'client_authorization_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'20'
,
'db_index'
:
'True'
}),
'uploaded_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
}),
'course_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'db_index'
:
'True'
}),
'course_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'db_index'
:
'True'
}),
'created_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'created_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'eligibility_appointment_date_first'
:
(
'django.db.models.fields.DateField'
,
[],
{
'db_index'
:
'True'
}),
'eligibility_appointment_date_first'
:
(
'django.db.models.fields.DateField'
,
[],
{
'db_index'
:
'True'
}),
'eligibility_appointment_date_last'
:
(
'django.db.models.fields.DateField'
,
[],
{
'db_index'
:
'True'
}),
'eligibility_appointment_date_last'
:
(
'django.db.models.fields.DateField'
,
[],
{
'db_index'
:
'True'
}),
'exam_series_code'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'15'
,
'db_index'
:
'True'
}),
'exam_series_code'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'15'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'testcenter_user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'default'
:
'None'
,
'to'
:
"orm['student.TestCenterUser']"
,
'unique'
:
'True'
}),
'testcenter_user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'default'
:
'None'
,
'to'
:
"orm['student.TestCenterUser']"
}),
'updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'upload_error_message'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'512'
,
'blank'
:
'True'
}),
'upload_error_message'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'512'
,
'blank'
:
'True'
}),
'upload_status'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'20'
,
'blank'
:
'True'
}),
'upload_status'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'20'
,
'blank'
:
'True'
}),
'uploaded_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
,
'db_index'
:
'True'
}),
'user_updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
})
'user_updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
})
},
},
'student.testcenteruser'
:
{
'student.testcenteruser'
:
{
...
@@ -146,9 +159,8 @@ class Migration(SchemaMigration):
...
@@ -146,9 +159,8 @@ class Migration(SchemaMigration):
'address_3'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'40'
,
'blank'
:
'True'
}),
'address_3'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'40'
,
'blank'
:
'True'
}),
'candidate_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'null'
:
'True'
,
'db_index'
:
'True'
}),
'candidate_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'null'
:
'True'
,
'db_index'
:
'True'
}),
'city'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'db_index'
:
'True'
}),
'city'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'db_index'
:
'True'
}),
'client_candidate_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
,
'db_index'
:
'True'
}),
'client_candidate_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'50'
,
'db_index'
:
'True'
}),
'company_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
,
'blank'
:
'True'
}),
'company_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'50'
,
'blank'
:
'True'
}),
'uploaded_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
,
'db_index'
:
'True'
}),
'country'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'3'
,
'db_index'
:
'True'
}),
'country'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'3'
,
'db_index'
:
'True'
}),
'created_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'created_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'extension'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'8'
,
'blank'
:
'True'
}),
'extension'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'8'
,
'blank'
:
'True'
}),
...
@@ -166,7 +178,8 @@ class Migration(SchemaMigration):
...
@@ -166,7 +178,8 @@ class Migration(SchemaMigration):
'suffix'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'suffix'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'upload_error_message'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'512'
,
'blank'
:
'True'
}),
'upload_error_message'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'512'
,
'blank'
:
'True'
}),
'upload_status'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'20'
,
'blank'
:
'True'
}),
'upload_status'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'20'
,
'blank'
:
'True'
}),
'uploaded_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
,
'null'
:
'True'
,
'blank'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'default'
:
'None'
,
'to'
:
"orm['auth.User']"
,
'unique'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'default'
:
'None'
,
'to'
:
"orm['auth.User']"
,
'unique'
:
'True'
}),
'user_updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
})
'user_updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
})
},
},
...
@@ -194,4 +207,4 @@ class Migration(SchemaMigration):
...
@@ -194,4 +207,4 @@ class Migration(SchemaMigration):
}
}
}
}
complete_apps
=
[
'student'
]
complete_apps
=
[
'student'
]
\ No newline at end of file
common/djangoapps/student/models.py
View file @
ea8a56da
...
@@ -40,6 +40,7 @@ import hashlib
...
@@ -40,6 +40,7 @@ import hashlib
import
json
import
json
import
logging
import
logging
import
uuid
import
uuid
from
random
import
randint
from
django.conf
import
settings
from
django.conf
import
settings
...
@@ -47,10 +48,12 @@ from django.contrib.auth.models import User
...
@@ -47,10 +48,12 @@ from django.contrib.auth.models import User
from
django.db
import
models
from
django.db
import
models
from
django.db.models.signals
import
post_save
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
django.dispatch
import
receiver
from
django.forms
import
ModelForm
from
django.forms
import
ModelForm
,
forms
import
comment_client
as
cc
import
comment_client
as
cc
from
django_comment_client.models
import
Role
from
django_comment_client.models
import
Role
from
feedparser
import
binascii
import
os
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -160,7 +163,7 @@ class TestCenterUser(models.Model):
...
@@ -160,7 +163,7 @@ class TestCenterUser(models.Model):
candidate_id
=
models
.
IntegerField
(
null
=
True
,
db_index
=
True
)
candidate_id
=
models
.
IntegerField
(
null
=
True
,
db_index
=
True
)
# Unique ID we assign our user for the Test Center.
# Unique ID we assign our user for the Test Center.
client_candidate_id
=
models
.
CharField
(
max_length
=
50
,
db_index
=
True
)
client_candidate_id
=
models
.
CharField
(
unique
=
True
,
max_length
=
50
,
db_index
=
True
)
# Name
# Name
first_name
=
models
.
CharField
(
max_length
=
30
,
db_index
=
True
)
first_name
=
models
.
CharField
(
max_length
=
30
,
db_index
=
True
)
...
@@ -191,10 +194,10 @@ class TestCenterUser(models.Model):
...
@@ -191,10 +194,10 @@ class TestCenterUser(models.Model):
fax_country_code
=
models
.
CharField
(
max_length
=
3
,
blank
=
True
)
fax_country_code
=
models
.
CharField
(
max_length
=
3
,
blank
=
True
)
# Company
# Company
company_name
=
models
.
CharField
(
max_length
=
50
,
blank
=
True
)
company_name
=
models
.
CharField
(
max_length
=
50
,
blank
=
True
,
db_index
=
True
)
# Confirmation
# Confirmation
upload_status
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
)
# 'Error' or 'Accepted'
upload_status
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
db_index
=
True
)
# 'Error' or 'Accepted'
uploaded_at
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
db_index
=
True
)
uploaded_at
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
db_index
=
True
)
upload_error_message
=
models
.
CharField
(
max_length
=
512
,
blank
=
True
)
upload_error_message
=
models
.
CharField
(
max_length
=
512
,
blank
=
True
)
...
@@ -217,26 +220,21 @@ class TestCenterUser(models.Model):
...
@@ -217,26 +220,21 @@ class TestCenterUser(models.Model):
return
False
return
False
# def update(self, dict):
@staticmethod
# # leave user and client_candidate_id as before
def
_generate_candidate_id
():
# self.user_updated_at = datetime.now()
NUM_DIGITS
=
12
# for fieldname in TestCenterUser.user_provided_fields():
return
u"edX
%0
d"
%
randint
(
1
,
10
**
NUM_DIGITS
-
1
)
# binascii.hexlify(os.urandom(8))
# self.__setattr__(fieldname, dict[fieldname])
# @staticmethod
# def create(user, dict):
# testcenter_user = TestCenterUser(user=user)
# testcenter_user.update(dict)
# # testcenter_user.candidate_id remains unset
# # TODO: assign an ID of our own:
# testcenter_user.client_candidate_id = 'edx' + unique_id_for_user(user) # some unique value
@staticmethod
@staticmethod
def
create
(
user
):
def
create
(
user
):
testcenter_user
=
TestCenterUser
(
user
=
user
)
testcenter_user
=
TestCenterUser
(
user
=
user
)
# testcenter_user.candidate_id remains unset
# testcenter_user.candidate_id remains unset
# assign an ID of our own:
# assign an ID of our own:
testcenter_user
.
client_candidate_id
=
'edx'
+
unique_id_for_user
(
user
)
# some unique value
cand_id
=
TestCenterUser
.
_generate_candidate_id
()
while
TestCenterUser
.
objects
.
filter
(
client_candidate_id
=
cand_id
)
.
exists
():
cand_id
=
TestCenterUser
.
_generate_candidate_id
()
testcenter_user
.
client_candidate_id
=
cand_id
return
testcenter_user
class
TestCenterUserForm
(
ModelForm
):
class
TestCenterUserForm
(
ModelForm
):
class
Meta
:
class
Meta
:
...
@@ -251,6 +249,60 @@ class TestCenterUserForm(ModelForm):
...
@@ -251,6 +249,60 @@ class TestCenterUserForm(ModelForm):
new_user
.
user_updated_at
=
datetime
.
now
()
new_user
.
user_updated_at
=
datetime
.
now
()
new_user
.
save
()
new_user
.
save
()
# add validation:
@staticmethod
def
can_encode_as_latin
(
fieldvalue
):
try
:
fieldvalue
.
encode
(
'iso-8859-1'
)
except
UnicodeEncodeError
:
return
False
return
True
def
check_country_code
(
self
,
fieldname
):
code
=
self
.
cleaned_data
[
fieldname
]
if
code
and
len
(
code
)
!=
3
:
raise
forms
.
ValidationError
(
u'Must be three characters (ISO 3166-1): e.g. USA, CAN, MNG'
)
return
code
def
clean_country
(
self
):
return
self
.
check_country_code
(
'country'
)
def
clean_phone_country_code
(
self
):
return
self
.
check_country_code
(
'phone_country_code'
)
def
clean_fax_country_code
(
self
):
return
self
.
check_country_code
(
'fax_country_code'
)
def
clean
(
self
):
cleaned_data
=
super
(
TestCenterUserForm
,
self
)
.
clean
()
# check for interactions between fields:
if
'country'
in
cleaned_data
:
country
=
cleaned_data
.
get
(
'country'
)
if
country
==
'USA'
or
country
==
'CAN'
:
if
'state'
in
cleaned_data
and
len
(
cleaned_data
[
'state'
])
==
0
:
self
.
_errors
[
'state'
]
=
self
.
error_class
([
u'Required if country is USA or CAN.'
])
del
cleaned_data
[
'state'
]
if
'postal_code'
in
cleaned_data
and
len
(
cleaned_data
[
'postal_code'
])
==
0
:
self
.
_errors
[
'postal_code'
]
=
self
.
error_class
([
u'Required if country is USA or CAN.'
])
del
cleaned_data
[
'postal_code'
]
if
'fax'
in
cleaned_data
and
len
(
cleaned_data
[
'fax'
])
>
0
and
'fax_country_code'
in
cleaned_data
and
len
(
cleaned_data
[
'fax_country_code'
])
==
0
:
self
.
_errors
[
'fax_country_code'
]
=
self
.
error_class
([
u'Required if fax is specified.'
])
del
cleaned_data
[
'fax_country_code'
]
# check encoding for all fields:
cleaned_data_fields
=
[
fieldname
for
fieldname
in
cleaned_data
]
for
fieldname
in
cleaned_data_fields
:
if
not
TestCenterUserForm
.
can_encode_as_latin
(
cleaned_data
[
fieldname
]):
self
.
_errors
[
fieldname
]
=
self
.
error_class
([
u'Must only use characters in Latin-1 encoding'
])
del
cleaned_data
[
fieldname
]
# Always return the full collection of cleaned data.
return
cleaned_data
ACCOMODATION_CODES
=
(
ACCOMODATION_CODES
=
(
...
@@ -282,7 +334,7 @@ class TestCenterRegistration(models.Model):
...
@@ -282,7 +334,7 @@ class TestCenterRegistration(models.Model):
# to find an exam registration, we key off of the user and course_id.
# to find an exam registration, we key off of the user and course_id.
# If multiple exams per course are possible, we would also need to add the
# If multiple exams per course are possible, we would also need to add the
# exam_series_code.
# exam_series_code.
testcenter_user
=
models
.
ForeignKey
(
TestCenterUser
,
unique
=
True
,
default
=
None
)
testcenter_user
=
models
.
ForeignKey
(
TestCenterUser
,
default
=
None
)
course_id
=
models
.
CharField
(
max_length
=
128
,
db_index
=
True
)
course_id
=
models
.
CharField
(
max_length
=
128
,
db_index
=
True
)
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
,
db_index
=
True
)
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
,
db_index
=
True
)
...
@@ -295,7 +347,7 @@ class TestCenterRegistration(models.Model):
...
@@ -295,7 +347,7 @@ class TestCenterRegistration(models.Model):
user_updated_at
=
models
.
DateTimeField
(
db_index
=
True
)
user_updated_at
=
models
.
DateTimeField
(
db_index
=
True
)
# "client_authorization_id" is the client's unique identifier for the authorization.
# "client_authorization_id" is the client's unique identifier for the authorization.
# This must be present for an update or delete to be sent to Pearson.
# This must be present for an update or delete to be sent to Pearson.
#
client_authorization_id = models.CharField(max_length=20, unique=True, db_index=True)
client_authorization_id
=
models
.
CharField
(
max_length
=
20
,
unique
=
True
,
db_index
=
True
)
# information about the test, from the course policy:
# information about the test, from the course policy:
exam_series_code
=
models
.
CharField
(
max_length
=
15
,
db_index
=
True
)
exam_series_code
=
models
.
CharField
(
max_length
=
15
,
db_index
=
True
)
...
@@ -311,7 +363,7 @@ class TestCenterRegistration(models.Model):
...
@@ -311,7 +363,7 @@ class TestCenterRegistration(models.Model):
# Confirmation
# Confirmation
upload_status
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
)
# 'Error' or 'Accepted'
upload_status
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
)
# 'Error' or 'Accepted'
uploaded_at
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
db_index
=
True
)
uploaded_at
=
models
.
DateTimeField
(
null
=
True
,
db_index
=
True
)
upload_error_message
=
models
.
CharField
(
max_length
=
512
,
blank
=
True
)
upload_error_message
=
models
.
CharField
(
max_length
=
512
,
blank
=
True
)
@property
@property
...
@@ -331,25 +383,26 @@ class TestCenterRegistration(models.Model):
...
@@ -331,25 +383,26 @@ class TestCenterRegistration(models.Model):
registration
.
eligibility_appointment_date_first
=
exam_info
.
get
(
'First_Eligible_Appointment_Date'
)
registration
.
eligibility_appointment_date_first
=
exam_info
.
get
(
'First_Eligible_Appointment_Date'
)
registration
.
eligibility_appointment_date_last
=
exam_info
.
get
(
'Last_Eligible_Appointment_Date'
)
registration
.
eligibility_appointment_date_last
=
exam_info
.
get
(
'Last_Eligible_Appointment_Date'
)
# accommodation_code remains blank for now, along with Pearson confirmation
# accommodation_code remains blank for now, along with Pearson confirmation
registration
.
user_updated_at
=
datetime
.
now
()
registration
.
client_authorization_id
=
registration
.
_create_client_authorization_id
()
#registration.client_authorization_id = registration._create_client_authorization_id()
return
registration
return
registration
@staticmethod
def
_generate_authorization_id
():
NUM_DIGITS
=
12
return
u"edX
%0
d"
%
randint
(
1
,
10
**
NUM_DIGITS
-
1
)
# binascii.hexlify(os.urandom(8))
def
_create_client_authorization_id
(
self
):
def
_create_client_authorization_id
(
self
):
"""
"""
Return a unique id for a registration, suitable for
inserting into
Return a unique id for a registration, suitable for
using as an authorization code
e.g. personalized survey link
s.
for Pearson. It must fit within 20 character
s.
"""
"""
# include the secret key as a salt, and to make the ids unique across
# generate a random value, and check to see if it already is in use here
# different LMS installs. Then add in (user, course, exam), which should
auth_id
=
TestCenterRegistration
.
_generate_authorization_id
()
# be unique.
while
TestCenterRegistration
.
objects
.
filter
(
client_authorization_id
=
auth_id
)
.
exists
():
h
=
hashlib
.
md5
()
auth_id
=
TestCenterRegistration
.
_generate_authorization_id
()
h
.
update
(
settings
.
SECRET_KEY
)
return
auth_id
h
.
update
(
str
(
self
.
testcenter_user
.
user
.
id
))
h
.
update
(
str
(
self
.
course_id
))
h
.
update
(
str
(
self
.
exam_series_code
))
return
h
.
hexdigest
()
def
is_accepted
(
self
):
def
is_accepted
(
self
):
return
self
.
upload_status
==
'Accepted'
return
self
.
upload_status
==
'Accepted'
...
@@ -362,7 +415,21 @@ class TestCenterRegistration(models.Model):
...
@@ -362,7 +415,21 @@ class TestCenterRegistration(models.Model):
def
is_pending_acknowledgement
(
self
):
def
is_pending_acknowledgement
(
self
):
return
self
.
upload_status
==
''
and
not
self
.
is_pending_accommodation
()
return
self
.
upload_status
==
''
and
not
self
.
is_pending_accommodation
()
class
TestCenterRegistrationForm
(
ModelForm
):
class
Meta
:
model
=
TestCenterRegistration
fields
=
(
'accommodation_request'
,
)
def
update_and_save
(
self
):
registration
=
self
.
save
(
commit
=
False
)
# create additional values here:
registration
.
user_updated_at
=
datetime
.
now
()
registration
.
save
()
# TODO: add validation code for values added to accommodation_code field.
def
get_testcenter_registrations_for_user_and_course
(
user
,
course_id
,
exam_series_code
=
None
):
def
get_testcenter_registrations_for_user_and_course
(
user
,
course_id
,
exam_series_code
=
None
):
try
:
try
:
tcu
=
TestCenterUser
.
objects
.
get
(
user
=
user
)
tcu
=
TestCenterUser
.
objects
.
get
(
user
=
user
)
...
...
common/djangoapps/student/views.py
View file @
ea8a56da
...
@@ -18,18 +18,17 @@ from django.contrib.auth.models import User
...
@@ -18,18 +18,17 @@ from django.contrib.auth.models import User
from
django.contrib.auth.decorators
import
login_required
from
django.contrib.auth.decorators
import
login_required
from
django.core.context_processors
import
csrf
from
django.core.context_processors
import
csrf
from
django.core.mail
import
send_mail
from
django.core.mail
import
send_mail
from
django.core.urlresolvers
import
reverse
from
django.core.validators
import
validate_email
,
validate_slug
,
ValidationError
from
django.core.validators
import
validate_email
,
validate_slug
,
ValidationError
from
django.db
import
IntegrityError
from
django.db
import
IntegrityError
from
django.http
import
HttpResponse
,
HttpResponseForbidden
,
Http404
,
\
from
django.http
import
HttpResponse
,
HttpResponseForbidden
,
Http404
HttpResponseRedirect
from
django.shortcuts
import
redirect
from
django.shortcuts
import
redirect
from
mitxmako.shortcuts
import
render_to_response
,
render_to_string
from
mitxmako.shortcuts
import
render_to_response
,
render_to_string
from
bs4
import
BeautifulSoup
from
bs4
import
BeautifulSoup
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django_future.csrf
import
ensure_csrf_cookie
,
csrf_exempt
from
django_future.csrf
import
ensure_csrf_cookie
,
csrf_exempt
from
student.models
import
(
Registration
,
UserProfile
,
TestCenterUser
,
TestCenterUserForm
,
TestCenterRegistration
,
from
student.models
import
(
Registration
,
UserProfile
,
TestCenterUser
,
TestCenterUserForm
,
TestCenterRegistration
,
TestCenterRegistrationForm
,
PendingNameChange
,
PendingEmailChange
,
PendingNameChange
,
PendingEmailChange
,
CourseEnrollment
,
unique_id_for_user
,
CourseEnrollment
,
unique_id_for_user
,
get_testcenter_registrations_for_user_and_course
)
get_testcenter_registrations_for_user_and_course
)
...
@@ -248,8 +247,6 @@ def dashboard(request):
...
@@ -248,8 +247,6 @@ def dashboard(request):
'show_courseware_links_for'
:
show_courseware_links_for
,
'show_courseware_links_for'
:
show_courseware_links_for
,
'cert_statuses'
:
cert_statuses
,
'cert_statuses'
:
cert_statuses
,
'news'
:
top_news
,
'news'
:
top_news
,
# No longer needed here...move to begin_registration
# 'testcenteruser': testcenteruser,
}
}
return
render_to_response
(
'dashboard.html'
,
context
)
return
render_to_response
(
'dashboard.html'
,
context
)
...
@@ -657,11 +654,12 @@ def create_test_registration(request, post_override=None):
...
@@ -657,11 +654,12 @@ def create_test_registration(request, post_override=None):
try
:
try
:
testcenter_user
=
TestCenterUser
.
objects
.
get
(
user
=
user
)
testcenter_user
=
TestCenterUser
.
objects
.
get
(
user
=
user
)
needs_updating
=
testcenter_user
.
needs_update
(
post_vars
)
except
TestCenterUser
.
DoesNotExist
:
except
TestCenterUser
.
DoesNotExist
:
# do additional initialization here:
# do additional initialization here:
testcenter_user
=
TestCenterUser
.
create
(
user
)
testcenter_user
=
TestCenterUser
.
create
(
user
)
needs_updating
=
True
needs_updating
=
testcenter_user
.
needs_update
(
post_vars
)
# perform validation:
# perform validation:
if
needs_updating
:
if
needs_updating
:
...
@@ -692,20 +690,28 @@ def create_test_registration(request, post_override=None):
...
@@ -692,20 +690,28 @@ def create_test_registration(request, post_override=None):
# right now.
# right now.
else
:
else
:
accommodation_request
=
post_vars
.
get
(
'accommodation
s
'
,
''
)
accommodation_request
=
post_vars
.
get
(
'accommodation
_request
'
,
''
)
registration
=
TestCenterRegistration
.
create
(
testcenter_user
,
course_id
,
exam_info
,
accommodation_request
)
registration
=
TestCenterRegistration
.
create
(
testcenter_user
,
course_id
,
exam_info
,
accommodation_request
)
needs_saving
=
True
needs_saving
=
True
# TODO: add validation of registration. (Mainly whether an accommodation request is too long.)
if
needs_saving
:
if
needs_saving
:
registration
.
save
()
# do validation of registration. (Mainly whether an accommodation request is too long.)
form
=
TestCenterRegistrationForm
(
instance
=
registration
,
data
=
post_vars
)
if
form
.
is_valid
():
form
.
update_and_save
()
else
:
response_data
=
{
'success'
:
False
}
# return a list of errors...
response_data
[
'field_errors'
]
=
form
.
errors
response_data
[
'non_field_errors'
]
=
form
.
non_field_errors
()
return
HttpResponse
(
json
.
dumps
(
response_data
),
mimetype
=
"application/json"
)
# only do the following if there is accommodation text to send,
# only do the following if there is accommodation text to send,
# and a destination to which to send it.
# and a destination to which to send it.
# TODO: still need to create the accommodation email templates
# TODO: still need to create the accommodation email templates
if
'accommodation
s
'
in
post_vars
and
settings
.
MITX_FEATURES
.
get
(
'ACCOMMODATION_EMAIL'
):
if
'accommodation
_request
'
in
post_vars
and
settings
.
MITX_FEATURES
.
get
(
'ACCOMMODATION_EMAIL'
):
d
=
{
'accommodation
s'
:
post_vars
[
'accommodations
'
]
}
d
=
{
'accommodation
_request'
:
post_vars
[
'accommodation_request
'
]
}
# composes accommodation email
# composes accommodation email
subject
=
render_to_string
(
'emails/accommodation_email_subject.txt'
,
d
)
subject
=
render_to_string
(
'emails/accommodation_email_subject.txt'
,
d
)
...
...
lms/templates/dashboard.html
View file @
ea8a56da
...
@@ -247,7 +247,7 @@
...
@@ -247,7 +247,7 @@
<div
class=
"message message-status is-shown exam-schedule"
>
<div
class=
"message message-status is-shown exam-schedule"
>
<!-- TODO: pull Pearson destination out into a Setting -->
<!-- TODO: pull Pearson destination out into a Setting -->
<a
href=
"https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX"
class=
"exam-button"
>
Schedule Pearson exam
</a>
<a
href=
"https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX"
class=
"exam-button"
>
Schedule Pearson exam
</a>
<p
class=
"exam-registration-number"
><a
href=
"${testcenter_register_target}"
id=
"exam_register_link"
>
Registration
</a>
number:
<strong>
edx00015879548
</strong></p>
<p
class=
"exam-registration-number"
><a
href=
"${testcenter_register_target}"
id=
"exam_register_link"
>
Registration
</a>
number:
<strong>
${registrations[0].client_authorization_id}
</strong></p>
<p
class=
"message-copy"
>
Write this down! You’ll need it to schedule your exam.
</p>
<p
class=
"message-copy"
>
Write this down! You’ll need it to schedule your exam.
</p>
</div>
</div>
% endif
% endif
...
...
lms/templates/test_center_register.html
View file @
ea8a56da
...
@@ -68,17 +68,6 @@
...
@@ -68,17 +68,6 @@
$
(
"label"
).
removeClass
(
"is-focused"
);
$
(
"label"
).
removeClass
(
"is-focused"
);
});
});
$
(
document
).
delegate
(
'#testcenter_register_form'
,
'ajax:success'
,
function
(
data
,
json
,
xhr
)
{
if
(
json
.
success
)
{
location
.
href
=
"${reverse('dashboard')}"
;
}
else
{
if
(
$
(
'#testcenter_register_error'
).
length
==
0
)
{
$
(
'#testcenter_register_form'
).
prepend
(
'<div id="testcenter_register_error" class="modal-form-error"></div>'
);
}
$
(
'#testcenter_register_error'
).
text
(
json
.
field_errors
).
stop
().
css
(
"display"
,
"block"
);
}
});
})(
this
)
})(
this
)
</script>
</script>
</
%
block>
</
%
block>
...
@@ -262,9 +251,9 @@
...
@@ -262,9 +251,9 @@
</li>
</li>
% endif
% endif
% else:
% else:
<li
class=
"field"
>
<li
data-field=
"accommodation_request"
class=
"field"
>
<label
for=
"accommodations"
>
Accommodations Requested
</label>
<label
for=
"accommodations"
>
Accommodations Requested
</label>
<textarea
class=
"long"
id=
"accommodations"
name=
"accommodation
s
"
value=
""
placeholder=
""
></textarea>
<textarea
class=
"long"
id=
"accommodations"
name=
"accommodation
_request
"
value=
""
placeholder=
""
></textarea>
</li>
</li>
% endif
% endif
</ol>
</ol>
...
@@ -290,7 +279,7 @@
...
@@ -290,7 +279,7 @@
<
%
regstatus =
"Registration approved by Pearson"
%
>
<
%
regstatus =
"Registration approved by Pearson"
%
>
<div
class=
"message message-status registration-accepted is-shown"
>
<div
class=
"message message-status registration-accepted is-shown"
>
<p
class=
"registration-status"
><span
class=
"label"
>
Registration Status:
</span><span
class=
"value"
>
${regstatus}
</span></p>
<p
class=
"registration-status"
><span
class=
"label"
>
Registration Status:
</span><span
class=
"value"
>
${regstatus}
</span></p>
<p
class=
"registration-number"
><span
class=
"label"
>
Registration number:
</span>
<span
class=
"value"
>
edx00015879548
</span></p>
<p
class=
"registration-number"
><span
class=
"label"
>
Registration number:
</span>
<span
class=
"value"
>
${registration.client_authorization_id}
</span></p>
<p
class=
"message-copy"
>
Write this down! You’ll need it to schedule your exam.
</p>
<p
class=
"message-copy"
>
Write this down! You’ll need it to schedule your exam.
</p>
<a
href=
"https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX"
class=
"button exam-button"
>
Schedule Pearson exam
</a>
<a
href=
"https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX"
class=
"button exam-button"
>
Schedule Pearson exam
</a>
</div>
</div>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment