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
19f737d5
Commit
19f737d5
authored
Nov 25, 2014
by
stephensanchez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Creating a new Organization based preference model.
parent
3393f25f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
181 additions
and
6 deletions
+181
-6
common/djangoapps/user_api/migrations/0004_auto__add_userorgtag__add_unique_userorgtag_user_org_key__chg_field_us.py
+110
-0
common/djangoapps/user_api/models.py
+17
-0
common/djangoapps/user_api/tests/factories.py
+11
-1
common/djangoapps/user_api/tests/test_models.py
+43
-5
No files found.
common/djangoapps/user_api/migrations/0004_auto__add_userorgtag__add_unique_userorgtag_user_org_key__chg_field_us.py
0 → 100644
View file @
19f737d5
# -*- coding: utf-8 -*-
import
datetime
from
south.db
import
db
from
south.v2
import
SchemaMigration
from
django.db
import
models
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
# Adding model 'UserOrgTag'
db
.
create_table
(
'user_api_userorgtag'
,
(
(
'id'
,
self
.
gf
(
'django.db.models.fields.AutoField'
)(
primary_key
=
True
)),
(
'created'
,
self
.
gf
(
'model_utils.fields.AutoCreatedField'
)(
default
=
datetime
.
datetime
.
now
)),
(
'modified'
,
self
.
gf
(
'model_utils.fields.AutoLastModifiedField'
)(
default
=
datetime
.
datetime
.
now
)),
(
'user'
,
self
.
gf
(
'django.db.models.fields.related.ForeignKey'
)(
related_name
=
'+'
,
to
=
orm
[
'auth.User'
])),
(
'key'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
,
db_index
=
True
)),
(
'org'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
,
db_index
=
True
)),
(
'value'
,
self
.
gf
(
'django.db.models.fields.TextField'
)()),
))
db
.
send_create_signal
(
'user_api'
,
[
'UserOrgTag'
])
# Adding unique constraint on 'UserOrgTag', fields ['user', 'org', 'key']
db
.
create_unique
(
'user_api_userorgtag'
,
[
'user_id'
,
'org'
,
'key'
])
# Create a composite index of user_id, org, and key.
db
.
create_index
(
'user_api_userorgtag'
,
[
'user_id'
,
'org'
,
'key'
])
# Changing field 'UserCourseTag.course_id'
db
.
alter_column
(
'user_api_usercoursetag'
,
'course_id'
,
self
.
gf
(
'xmodule_django.models.CourseKeyField'
)(
max_length
=
255
))
def
backwards
(
self
,
orm
):
# Delete the composite index of user_id, org, and key.
db
.
delete_index
(
'user_api_userorgtag'
,
[
'user_id'
,
'org'
,
'key'
])
# Removing unique constraint on 'UserOrgTag', fields ['user', 'org', 'key']
db
.
delete_unique
(
'user_api_userorgtag'
,
[
'user_id'
,
'org'
,
'key'
])
# Deleting model 'UserOrgTag'
db
.
delete_table
(
'user_api_userorgtag'
)
# Changing field 'UserCourseTag.course_id'
db
.
alter_column
(
'user_api_usercoursetag'
,
'course_id'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
))
models
=
{
'auth.group'
:
{
'Meta'
:
{
'object_name'
:
'Group'
},
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'80'
}),
'permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
})
},
'auth.permission'
:
{
'Meta'
:
{
'ordering'
:
"('content_type__app_label', 'content_type__model', 'codename')"
,
'unique_together'
:
"(('content_type', 'codename'),)"
,
'object_name'
:
'Permission'
},
'codename'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'content_type'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['contenttypes.ContentType']"
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
})
},
'auth.user'
:
{
'Meta'
:
{
'object_name'
:
'User'
},
'date_joined'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'email'
:
(
'django.db.models.fields.EmailField'
,
[],
{
'max_length'
:
'75'
,
'blank'
:
'True'
}),
'first_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'groups'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Group']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'is_active'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'True'
}),
'is_staff'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'is_superuser'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'last_login'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'last_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'password'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
}),
'user_permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'username'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'30'
})
},
'contenttypes.contenttype'
:
{
'Meta'
:
{
'ordering'
:
"('name',)"
,
'unique_together'
:
"(('app_label', 'model'),)"
,
'object_name'
:
'ContentType'
,
'db_table'
:
"'django_content_type'"
},
'app_label'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'model'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
})
},
'user_api.usercoursetag'
:
{
'Meta'
:
{
'unique_together'
:
"(('user', 'course_id', 'key'),)"
,
'object_name'
:
'UserCourseTag'
},
'course_id'
:
(
'xmodule_django.models.CourseKeyField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'+'"
,
'to'
:
"orm['auth.User']"
}),
'value'
:
(
'django.db.models.fields.TextField'
,
[],
{})
},
'user_api.userorgtag'
:
{
'Meta'
:
{
'unique_together'
:
"(('user', 'org', 'key'),)"
,
'object_name'
:
'UserOrgTag'
},
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'org'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'+'"
,
'to'
:
"orm['auth.User']"
}),
'value'
:
(
'django.db.models.fields.TextField'
,
[],
{})
},
'user_api.userpreference'
:
{
'Meta'
:
{
'unique_together'
:
"(('user', 'key'),)"
,
'object_name'
:
'UserPreference'
},
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'related_name'
:
"'preferences'"
,
'to'
:
"orm['auth.User']"
}),
'value'
:
(
'django.db.models.fields.TextField'
,
[],
{})
}
}
complete_apps
=
[
'user_api'
]
common/djangoapps/user_api/models.py
View file @
19f737d5
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
from
django.core.validators
import
RegexValidator
from
django.core.validators
import
RegexValidator
from
django.db
import
models
from
django.db
import
models
from
model_utils.models
import
TimeStampedModel
from
xmodule_django.models
import
CourseKeyField
from
xmodule_django.models
import
CourseKeyField
...
@@ -59,3 +60,19 @@ class UserCourseTag(models.Model):
...
@@ -59,3 +60,19 @@ class UserCourseTag(models.Model):
class
Meta
:
# pylint: disable=missing-docstring
class
Meta
:
# pylint: disable=missing-docstring
unique_together
=
(
"user"
,
"course_id"
,
"key"
)
unique_together
=
(
"user"
,
"course_id"
,
"key"
)
class
UserOrgTag
(
TimeStampedModel
):
""" Per-Organization user tags.
Allows settings to be configured at an organization level.
"""
user
=
models
.
ForeignKey
(
User
,
db_index
=
True
,
related_name
=
"+"
)
key
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
)
org
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
)
value
=
models
.
TextField
()
class
Meta
:
""" Meta class for defining unique constraints. """
unique_together
=
(
"user"
,
"org"
,
"key"
)
common/djangoapps/user_api/tests/factories.py
View file @
19f737d5
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
from
factory.django
import
DjangoModelFactory
from
factory.django
import
DjangoModelFactory
from
factory
import
SubFactory
from
factory
import
SubFactory
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
user_api.models
import
UserPreference
,
UserCourseTag
from
user_api.models
import
UserPreference
,
UserCourseTag
,
UserOrgTag
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
...
@@ -23,3 +23,13 @@ class UserCourseTagFactory(DjangoModelFactory):
...
@@ -23,3 +23,13 @@ class UserCourseTagFactory(DjangoModelFactory):
course_id
=
SlashSeparatedCourseKey
(
'org'
,
'course'
,
'run'
)
course_id
=
SlashSeparatedCourseKey
(
'org'
,
'course'
,
'run'
)
key
=
None
key
=
None
value
=
None
value
=
None
class
UserOrgTagFactory
(
DjangoModelFactory
):
""" Simple factory class for generating UserOrgTags """
FACTORY_FOR
=
UserOrgTag
user
=
SubFactory
(
UserFactory
)
org
=
'org'
key
=
None
value
=
None
common/djangoapps/user_api/tests/test_models.py
View file @
19f737d5
from
django.db
import
IntegrityError
from
django.db
import
IntegrityError
from
django.test
import
TestCase
from
django.test
import
TestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
user_api.tests.factories
import
UserPreferenceFactory
from
user_api.tests.factories
import
UserPreferenceFactory
,
UserCourseTagFactory
,
UserOrgTagFactory
from
user_api.models
import
UserPreference
from
user_api.models
import
UserPreference
...
@@ -19,15 +20,52 @@ class UserPreferenceModelTest(TestCase):
...
@@ -19,15 +20,52 @@ class UserPreferenceModelTest(TestCase):
def
test_arbitrary_values
(
self
):
def
test_arbitrary_values
(
self
):
user
=
UserFactory
.
create
()
user
=
UserFactory
.
create
()
UserPreferenceFactory
.
create
(
user
=
user
,
key
=
"testkey0"
,
value
=
""
)
self
.
_create_and_assert
(
user
=
user
,
key
=
"testkey0"
,
value
=
""
)
UserPreferenceFactory
.
create
(
user
=
user
,
key
=
"testkey1"
,
value
=
"This is some English text!"
)
self
.
_create_and_assert
(
user
=
user
,
key
=
"testkey1"
,
value
=
"This is some English text!"
)
UserPreferenceFactory
.
create
(
user
=
user
,
key
=
"testkey2"
,
value
=
"{'some': 'json'}"
)
self
.
_create_and_assert
(
user
=
user
,
key
=
"testkey2"
,
value
=
"{'some': 'json'}"
)
UserPreferenceFactory
.
create
(
self
.
_create_and_assert
(
user
=
user
,
user
=
user
,
key
=
"testkey3"
,
key
=
"testkey3"
,
value
=
"
\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\xad\xe5\x9b\xbd\xe6\x96\x87\xe5\xad\x97
'"
value
=
"
\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\xad\xe5\x9b\xbd\xe6\x96\x87\xe5\xad\x97
'"
)
)
def
_create_and_assert
(
self
,
user
,
key
,
value
):
"""Create a new preference and assert the values. """
preference
=
UserPreferenceFactory
.
create
(
user
=
user
,
key
=
key
,
value
=
value
)
self
.
assertEqual
(
preference
.
user
,
user
)
self
.
assertEqual
(
preference
.
key
,
key
)
self
.
assertEqual
(
preference
.
value
,
value
)
return
preference
def
test_create_user_course_tags
(
self
):
"""Create user preference tags and confirm properties are set accordingly. """
user
=
UserFactory
.
create
()
course
=
CourseFactory
.
create
()
tag
=
UserCourseTagFactory
.
create
(
user
=
user
,
course_id
=
course
.
id
,
key
=
"testkey"
,
value
=
"foobar"
)
self
.
assertEquals
(
tag
.
user
,
user
)
self
.
assertEquals
(
tag
.
course_id
,
course
.
id
)
self
.
assertEquals
(
tag
.
key
,
"testkey"
)
self
.
assertEquals
(
tag
.
value
,
"foobar"
)
def
test_create_user_org_tags
(
self
):
"""Create org specific user tags and confirm all properties are set """
user
=
UserFactory
.
create
()
course
=
CourseFactory
.
create
()
tag
=
UserOrgTagFactory
.
create
(
user
=
user
,
org
=
course
.
id
.
org
,
key
=
"testkey"
,
value
=
"foobar"
)
self
.
assertEquals
(
tag
.
user
,
user
)
self
.
assertEquals
(
tag
.
org
,
course
.
id
.
org
)
self
.
assertEquals
(
tag
.
key
,
"testkey"
)
self
.
assertEquals
(
tag
.
value
,
"foobar"
)
self
.
assertIsNotNone
(
tag
.
created
)
self
.
assertIsNotNone
(
tag
.
modified
)
# Modify the tag and save it. Check if the modified timestamp is updated.
original_modified
=
tag
.
modified
tag
.
value
=
"barfoo"
tag
.
save
()
self
.
assertEquals
(
tag
.
value
,
"barfoo"
)
self
.
assertNotEqual
(
original_modified
,
tag
.
modified
)
def
test_get_set_preference
(
self
):
def
test_get_set_preference
(
self
):
# Checks that you can set a preference and get that preference later
# Checks that you can set a preference and get that preference later
# Also, tests that no preference is returned for keys that are not set
# Also, tests that no preference is returned for keys that are not set
...
...
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