Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
django-rest-framework
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
django-rest-framework
Commits
ec096a1c
Commit
ec096a1c
authored
Sep 02, 2014
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add relations and get tests running
parent
4ac4676a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
151 additions
and
19 deletions
+151
-19
rest_framework/fields.py
+25
-5
rest_framework/mixins.py
+0
-1
rest_framework/relations.py
+111
-0
rest_framework/renderers.py
+7
-7
rest_framework/serializers.py
+4
-4
rest_framework/utils/html.py
+2
-0
tests/test_serializer.py
+2
-2
No files found.
rest_framework/fields.py
View file @
ec096a1c
...
...
@@ -68,7 +68,7 @@ class Field(object):
def
__init__
(
self
,
read_only
=
False
,
write_only
=
False
,
required
=
None
,
default
=
empty
,
initial
=
None
,
source
=
None
,
label
=
None
,
style
=
None
):
label
=
None
,
style
=
None
,
error_messages
=
None
):
self
.
_creation_counter
=
Field
.
_creation_counter
Field
.
_creation_counter
+=
1
...
...
@@ -216,9 +216,11 @@ class CharField(Field):
'blank'
:
'This field may not be blank.'
}
def
__init__
(
self
,
*
args
,
*
*
kwargs
):
def
__init__
(
self
,
**
kwargs
):
self
.
allow_blank
=
kwargs
.
pop
(
'allow_blank'
,
False
)
super
(
CharField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
max_length
=
kwargs
.
pop
(
'max_length'
,
None
)
self
.
min_length
=
kwargs
.
pop
(
'min_length'
,
None
)
super
(
CharField
,
self
)
.
__init__
(
**
kwargs
)
def
to_native
(
self
,
data
):
if
data
==
''
and
not
self
.
allow_blank
:
...
...
@@ -233,7 +235,7 @@ class ChoiceField(Field):
}
coerce_to_type
=
str
def
__init__
(
self
,
*
args
,
*
*
kwargs
):
def
__init__
(
self
,
**
kwargs
):
choices
=
kwargs
.
pop
(
'choices'
)
assert
choices
,
'`choices` argument is required and may not be empty'
...
...
@@ -257,7 +259,7 @@ class ChoiceField(Field):
str
(
key
):
key
for
key
in
self
.
choices
.
keys
()
}
super
(
ChoiceField
,
self
)
.
__init__
(
*
args
,
*
*
kwargs
)
super
(
ChoiceField
,
self
)
.
__init__
(
**
kwargs
)
def
to_native
(
self
,
data
):
try
:
...
...
@@ -296,6 +298,24 @@ class IntegerField(Field):
return
data
class
EmailField
(
CharField
):
pass
# TODO
class
RegexField
(
CharField
):
def
__init__
(
self
,
**
kwargs
):
self
.
regex
=
kwargs
.
pop
(
'regex'
)
super
(
CharField
,
self
)
.
__init__
(
**
kwargs
)
class
DateTimeField
(
CharField
):
pass
# TODO
class
FileField
(
Field
):
pass
# TODO
class
MethodField
(
Field
):
def
__init__
(
self
,
**
kwargs
):
kwargs
[
'source'
]
=
'*'
...
...
rest_framework/mixins.py
View file @
ec096a1c
...
...
@@ -6,7 +6,6 @@ which allows mixin classes to be composed in interesting ways.
"""
from
__future__
import
unicode_literals
from
django.core.exceptions
import
ValidationError
from
django.http
import
Http404
from
rest_framework
import
status
from
rest_framework.response
import
Response
...
...
rest_framework/relations.py
View file @
ec096a1c
from
rest_framework.fields
import
Field
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.core.urlresolvers
import
resolve
,
get_script_prefix
from
rest_framework.compat
import
urlparse
def
get_default_queryset
(
serializer_class
,
field_name
):
manager
=
getattr
(
serializer_class
.
opts
.
model
,
field_name
)
if
hasattr
(
manager
,
'related'
):
# Forward relationships
return
manager
.
related
.
model
.
_default_manager
.
all
()
# Reverse relationships
return
manager
.
field
.
rel
.
to
.
_default_manager
.
all
()
class
RelatedField
(
Field
):
def
__init__
(
self
,
**
kwargs
):
self
.
queryset
=
kwargs
.
pop
(
'queryset'
,
None
)
self
.
many
=
kwargs
.
pop
(
'many'
,
False
)
super
(
RelatedField
,
self
)
.
__init__
(
**
kwargs
)
def
bind
(
self
,
field_name
,
parent
,
root
):
super
(
RelatedField
,
self
)
.
bind
(
field_name
,
parent
,
root
)
if
self
.
queryset
is
None
and
not
self
.
read_only
:
self
.
queryset
=
get_default_queryset
(
parent
,
self
.
source
)
class
PrimaryKeyRelatedField
(
RelatedField
):
MESSAGES
=
{
'required'
:
'This field is required.'
,
'does_not_exist'
:
"Invalid pk '{pk_value}' - object does not exist."
,
'incorrect_type'
:
'Incorrect type. Expected pk value, received {data_type}.'
,
}
def
from_native
(
self
,
data
):
try
:
return
self
.
queryset
.
get
(
pk
=
data
)
except
ObjectDoesNotExist
:
self
.
fail
(
'does_not_exist'
,
pk_value
=
data
)
except
(
TypeError
,
ValueError
):
self
.
fail
(
'incorrect_type'
,
data_type
=
type
(
data
)
.
__name__
)
class
HyperlinkedRelatedField
(
RelatedField
):
lookup_field
=
'pk'
MESSAGES
=
{
'required'
:
'This field is required.'
,
'no_match'
:
'Invalid hyperlink - No URL match'
,
'incorrect_match'
:
'Invalid hyperlink - Incorrect URL match.'
,
'does_not_exist'
:
"Invalid hyperlink - Object does not exist."
,
'incorrect_type'
:
'Incorrect type. Expected URL string, received {data_type}.'
,
}
def
__init__
(
self
,
**
kwargs
):
self
.
view_name
=
kwargs
.
pop
(
'view_name'
)
self
.
lookup_field
=
kwargs
.
pop
(
'lookup_field'
,
self
.
lookup_field
)
self
.
lookup_url_kwarg
=
kwargs
.
pop
(
'lookup_url_kwarg'
,
self
.
lookup_field
)
super
(
HyperlinkedRelatedField
,
self
)
.
__init__
(
**
kwargs
)
def
get_object
(
self
,
view_name
,
view_args
,
view_kwargs
):
"""
Return the object corresponding to a matched URL.
Takes the matched URL conf arguments, and should return an
object instance, or raise an `ObjectDoesNotExist` exception.
"""
lookup_value
=
view_kwargs
[
self
.
lookup_url_kwarg
]
lookup_kwargs
=
{
self
.
lookup_field
:
lookup_value
}
return
self
.
queryset
.
get
(
**
lookup_kwargs
)
def
from_native
(
self
,
value
):
try
:
http_prefix
=
value
.
startswith
((
'http:'
,
'https:'
))
except
AttributeError
:
self
.
fail
(
'incorrect_type'
,
type
(
value
)
.
__name__
)
if
http_prefix
:
# If needed convert absolute URLs to relative path
value
=
urlparse
.
urlparse
(
value
)
.
path
prefix
=
get_script_prefix
()
if
value
.
startswith
(
prefix
):
value
=
'/'
+
value
[
len
(
prefix
):]
try
:
match
=
resolve
(
value
)
except
Exception
:
self
.
fail
(
'no_match'
)
if
match
.
view_name
!=
self
.
view_name
:
self
.
fail
(
'incorrect_match'
)
try
:
return
self
.
get_object
(
match
.
view_name
,
match
.
args
,
match
.
kwargs
)
except
(
ObjectDoesNotExist
,
TypeError
,
ValueError
):
self
.
fail
(
'does_not_exist'
)
class
HyperlinkedIdentityField
(
RelatedField
):
lookup_field
=
'pk'
def
__init__
(
self
,
**
kwargs
):
self
.
view_name
=
kwargs
.
pop
(
'view_name'
)
self
.
lookup_field
=
kwargs
.
pop
(
'lookup_field'
,
self
.
lookup_field
)
self
.
lookup_url_kwarg
=
kwargs
.
pop
(
'lookup_url_kwarg'
,
self
.
lookup_field
)
super
(
HyperlinkedIdentityField
,
self
)
.
__init__
(
**
kwargs
)
class
SlugRelatedField
(
RelatedField
):
def
__init__
(
self
,
**
kwargs
):
self
.
slug_field
=
kwargs
.
pop
(
'slug_field'
,
None
)
rest_framework/renderers.py
View file @
ec096a1c
...
...
@@ -436,13 +436,13 @@ class BrowsableAPIRenderer(BaseRenderer):
if
request
.
method
==
method
:
try
:
data
=
request
.
DATA
files
=
request
.
FILES
#
files = request.FILES
except
ParseError
:
data
=
None
files
=
None
#
files = None
else
:
data
=
None
files
=
None
#
files = None
with
override_method
(
view
,
request
,
method
)
as
request
:
obj
=
getattr
(
view
,
'object'
,
None
)
...
...
@@ -579,10 +579,10 @@ class BrowsableAPIRenderer(BaseRenderer):
'available_formats'
:
[
renderer_cls
.
format
for
renderer_cls
in
view
.
renderer_classes
],
'response_headers'
:
response_headers
,
#'put_form': self.get_rendered_html_form(view, 'PUT', request),
#'post_form': self.get_rendered_html_form(view, 'POST', request),
#'delete_form': self.get_rendered_html_form(view, 'DELETE', request),
#'options_form': self.get_rendered_html_form(view, 'OPTIONS', request),
#
'put_form': self.get_rendered_html_form(view, 'PUT', request),
#
'post_form': self.get_rendered_html_form(view, 'POST', request),
#
'delete_form': self.get_rendered_html_form(view, 'DELETE', request),
#
'options_form': self.get_rendered_html_form(view, 'OPTIONS', request),
'raw_data_put_form'
:
raw_data_put_form
,
'raw_data_post_form'
:
raw_data_post_form
,
...
...
rest_framework/serializers.py
View file @
ec096a1c
...
...
@@ -477,8 +477,8 @@ class ModelSerializer(Serializer):
if
model_field
:
kwargs
[
'required'
]
=
not
(
model_field
.
null
or
model_field
.
blank
)
# if model_field.help_text is not None:
# kwargs['help_text'] = model_field.help_text
#
if model_field.help_text is not None:
#
kwargs['help_text'] = model_field.help_text
if
model_field
.
verbose_name
is
not
None
:
kwargs
[
'label'
]
=
model_field
.
verbose_name
if
not
model_field
.
editable
:
...
...
@@ -566,8 +566,8 @@ class HyperlinkedModelSerializerOptions(ModelSerializerOptions):
class
HyperlinkedModelSerializer
(
ModelSerializer
):
_options_class
=
HyperlinkedModelSerializerOptions
_default_view_name
=
'
%(model_name)
s-detail'
#_hyperlink_field_class = HyperlinkedRelatedField
#_hyperlink_identify_field_class = HyperlinkedIdentityField
#
_hyperlink_field_class = HyperlinkedRelatedField
#
_hyperlink_identify_field_class = HyperlinkedIdentityField
def
get_default_fields
(
self
):
fields
=
super
(
HyperlinkedModelSerializer
,
self
)
.
get_default_fields
()
...
...
rest_framework/utils/html.py
View file @
ec096a1c
"""
Helpers for dealing with HTML input.
"""
import
re
def
is_html_input
(
dictionary
):
# MultiDict type datastructures are used to represent HTML form input,
...
...
tests/test_serializer.py
View file @
ec096a1c
...
...
@@ -1795,8 +1795,8 @@ class DefaultValuesOnAutogeneratedFieldsTests(TestCase):
class
MetadataSerializer
(
serializers
.
Serializer
):
field1
=
serializers
.
CharField
(
3
,
required
=
True
)
field2
=
serializers
.
CharField
(
10
,
required
=
False
)
field1
=
serializers
.
CharField
(
max_length
=
3
,
required
=
True
)
field2
=
serializers
.
CharField
(
max_length
=
10
,
required
=
False
)
class
MetadataSerializerTestCase
(
TestCase
):
...
...
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