david / django-roa (http://welldev.org/)

Turn your models into remote resources that you can access through Django's ORM. ROA stands for Resource Oriented Architecture.

Clone this repository (size: 560.7 KB): HTTPS / SSH
$ hg clone http://code.welldev.org/django-roa
commit 132: 8d453d0b35dd
parent 131: 3e613d59de36
branch: default
Solve the many-to-many issue using the "through" argument, which is now required for that type of relation and allows you to customize the URL called in this case. This is no more required to patch Django, yay! Note that I'm still working on the auth/remoteauth duality because of M2M relations between users, groups and permissions. Not easy.
David Larlet / david
8 months ago

Changed (Δ2.6 KB):

raw changeset »

examples/django_roa_client/models.py (14 lines added, 1 lines removed)

examples/django_roa_client/tests.py (10 lines added, 5 lines removed)

examples/django_roa_server/handlers.py (8 lines added, 17 lines removed)

examples/django_roa_server/models.py (10 lines added, 1 lines removed)

examples/django_roa_server/urls.py (6 lines added, 1 lines removed)

Up to file-list examples/django_roa_client/models.py:

@@ -92,10 +92,23 @@ class RemotePageWithOverriddenUrls(Model
92
92
        return u'' # overridden by settings
93
93
94
94
95
class RemotePageWithRelationsThrough(Model):
96
    title = models.CharField(max_length=50)
97
    remote_page_with_relations = models.ForeignKey("RemotePageWithRelations", blank=True, null=True)
98
    remote_page_with_many_fields = models.ForeignKey("RemotePageWithManyFields", blank=True, null=True)
99
100
    def __unicode__(self):
101
        return u'%s (%s)' % (self.title, self.id)
102
    
103
    @staticmethod
104
    def get_resource_url_list():
105
        return u'http://127.0.0.1:8081/django_roa_server/remotepagewithrelationsthrough/'
106
107
95
108
class RemotePageWithRelations(Model):
96
109
    title = models.CharField(max_length=50)
97
110
    remote_page = models.ForeignKey(RemotePage, blank=True, null=True)
98
    remote_page_fields = models.ManyToManyField(RemotePageWithManyFields, blank=True, null=True)
111
    remote_page_fields = models.ManyToManyField(RemotePageWithManyFields, through=RemotePageWithRelationsThrough, blank=True, null=True)
99
112
100
113
    def __unicode__(self):
101
114
        return u'%s (%s)' % (self.title, self.id)

Up to file-list examples/django_roa_client/tests.py:

@@ -41,7 +41,8 @@ from django_roa.remoteauth.models import
41
41
from django_roa_client.models import RemotePage, RemotePageWithManyFields, \
42
42
    RemotePageWithBooleanFields, RemotePageWithRelations, \
43
43
    RemotePageWithCustomSlug, RemotePageWithOverriddenUrls, \
44
    RemotePageWithNamedRelations, RemotePageWithProxy
44
    RemotePageWithNamedRelations, RemotePageWithProxy, \
45
    RemotePageWithRelationsThrough
45
46
from django_roa_client.forms import TestForm, RemotePageForm
46
47
47
48
class ROATestCase(TestCase):
@@ -381,17 +382,21 @@ class ROARelationsTests(ROATestCase):
381
382
        remote_page = RemotePageWithManyFields.objects.create(char_field=u'A remote page')
382
383
        another_remote_page = RemotePageWithManyFields.objects.create(char_field=u'Another remote page')
383
384
        relations_page = RemotePageWithRelations.objects.create(title=u'A remote relation page')
384
        relations_page.remote_page_fields.add(remote_page)
385
        relations_page_through = RemotePageWithRelationsThrough.objects.create(title=u'A remote relation page through', 
386
                                                                               remote_page_with_relations=relations_page,
387
                                                                               remote_page_with_many_fields=remote_page)
385
388
        self.assertEqual(repr(relations_page.remote_page_fields.all()), '[<RemotePageWithManyFields: RemotePageWithManyFields (1)>]')
386
389
        relations_page = RemotePageWithRelations.objects.get(id=relations_page.id)
387
390
        self.assertEqual(repr(relations_page.remote_page_fields.all()), '[<RemotePageWithManyFields: RemotePageWithManyFields (1)>]')
388
        relations_page.remote_page_fields.add(another_remote_page)
391
        another_relations_page_through = RemotePageWithRelationsThrough.objects.create(title=u'Another remote relation page through', 
392
                                                                                       remote_page_with_relations=relations_page,
393
                                                                                       remote_page_with_many_fields=another_remote_page)
389
394
        relations_page = RemotePageWithRelations.objects.get(id=relations_page.id)
390
395
        self.assertEqual(repr(relations_page.remote_page_fields.all()), '[<RemotePageWithManyFields: RemotePageWithManyFields (1)>, <RemotePageWithManyFields: RemotePageWithManyFields (2)>]')
391
396
        self.assertEqual(repr(remote_page.remotepagewithrelations_set.all()), '[<RemotePageWithRelations: A remote relation page (1)>]')
392
        relations_page.remote_page_fields.remove(remote_page)
397
        relations_page_through.delete()
393
398
        self.assertEqual(repr(relations_page.remote_page_fields.all()), '[<RemotePageWithManyFields: RemotePageWithManyFields (2)>]')
394
        relations_page.remote_page_fields.clear()
399
        another_relations_page_through.delete()
395
400
        self.assertEqual(repr(relations_page.remote_page_fields.all()), '[]')
396
401
        relations_page.delete()
397
402
        another_remote_page.delete()

Up to file-list examples/django_roa_server/handlers.py:

@@ -15,7 +15,7 @@ from piston.utils import rc
15
15
from django_roa_server.models import RemotePage, RemotePageWithManyFields, \
16
16
    RemotePageWithBooleanFields, RemotePageWithCustomSlug, \
17
17
    RemotePageWithOverriddenUrls, RemotePageWithRelations, \
18
    RemotePageWithNamedRelations
18
    RemotePageWithNamedRelations, RemotePageWithRelationsThrough
19
19
20
20
logger = logging.getLogger("django_roa_server")
21
21
@@ -151,22 +151,6 @@ class ROAHandler(BaseHandler):
151
151
        
152
152
        object.save()
153
153
        
154
        for field in self.model._meta.many_to_many:
155
            field_value = data.get(field.attname, None)
156
            m2m_field = getattr(object, field.attname)
157
            if field_value in (u'', u'None', None):
158
                m2m_field.clear()
159
                logger.debug('M2M relations cleared for "%s"' % (
160
                    unicode(object).encode(settings.DEFAULT_CHARSET), ))
161
            else:
162
                m2m_field.clear() # FIXME: find a clever way?
163
                m2m_convert = field.rel.to._meta.pk.to_python
164
                obj_ids = [m2m_convert(smart_unicode(pk)) for pk in field_value.split(',')]
165
                m2m_field.add(*obj_ids)
166
                logger.debug('M2M relations updated for "%s" with ids %s' % (
167
                    unicode(object).encode(settings.DEFAULT_CHARSET), 
168
                    obj_ids))
169
        
170
154
        response = [self.model.objects.get(id=object.id)]
171
155
        #response = [object]
172
156
        logger.debug('Object "%s" modified with %s' % (
@@ -283,6 +267,13 @@ class RemotePageWithRelationsCountHandle
283
267
    model = RemotePageWithRelations
284
268
285
269
    
270
class RemotePageWithRelationsThroughHandler(ROAHandler):
271
    model = RemotePageWithRelationsThrough
272
273
class RemotePageWithRelationsThroughCountHandler(ROACountHandler):
274
    model = RemotePageWithRelationsThrough
275
276
    
286
277
class RemotePageWithNamedRelationsHandler(ROAHandler):
287
278
    model = RemotePageWithNamedRelations
288
279

Up to file-list examples/django_roa_server/models.py:

@@ -56,10 +56,19 @@ class RemotePageWithOverriddenUrls(model
56
56
        return u'%s (%s)' % (self.title, self.id)
57
57
58
58
59
class RemotePageWithRelationsThrough(models.Model):
60
    title = models.CharField(max_length=50)
61
    remote_page_with_relations = models.ForeignKey("RemotePageWithRelations", blank=True, null=True)
62
    remote_page_with_many_fields = models.ForeignKey("RemotePageWithManyFields", blank=True, null=True)
63
64
    def __unicode__(self):
65
        return u'%s (%s)' % (self.title, self.id)
66
67
59
68
class RemotePageWithRelations(models.Model):
60
69
    title = models.CharField(max_length=50)
61
70
    remote_page = models.ForeignKey(RemotePage, blank=True, null=True)
62
    remote_page_fields = models.ManyToManyField(RemotePageWithManyFields, blank=True, null=True)
71
    remote_page_fields = models.ManyToManyField(RemotePageWithManyFields, through=RemotePageWithRelationsThrough, blank=True, null=True)
63
72
64
73
    def __unicode__(self):
65
74
        return u'%s (%s)' % (self.title, self.id)

Up to file-list examples/django_roa_server/urls.py:

@@ -12,7 +12,7 @@ from django_roa_server.handlers import R
12
12
    RemotePageWithManyFieldsCountHandler, RemotePageWithBooleanFieldsCountHandler, \
13
13
    RemotePageWithCustomSlugCountHandler, RemotePageWithOverriddenUrlsCountHandler, \
14
14
    RemotePageWithRelationsHandler, RemotePageWithNamedRelationsHandler, \
15
    RemotePageWithNamedRelationsCountHandler
15
    RemotePageWithNamedRelationsCountHandler, RemotePageWithRelationsThroughHandler
16
16
17
17
remote_pages = Resource(handler=RemotePageHandler)
18
18
remote_pages_count = Resource(handler=RemotePageCountHandler)
@@ -32,6 +32,9 @@ remote_pages_with_overridden_urls_count
32
32
remote_pages_with_relations = Resource(handler=RemotePageWithRelationsHandler)
33
33
remote_pages_with_relations_count = Resource(handler=RemotePageWithRelationsHandler)
34
34
35
remote_pages_with_relations_through = Resource(handler=RemotePageWithRelationsThroughHandler)
36
remote_pages_with_relations_through_count = Resource(handler=RemotePageWithRelationsThroughHandler)
37
35
38
remote_pages_with_named_relations = Resource(handler=RemotePageWithNamedRelationsHandler)
36
39
remote_pages_with_named_relations_count = Resource(handler=RemotePageWithNamedRelationsCountHandler)
37
40
@@ -48,6 +51,7 @@ urlpatterns = patterns('',
48
51
    url(r'^django_roa_server/remotepagewithcustomslug/count/$', remote_pages_with_custom_slug_count),
49
52
    url(r'^django_roa_server/remotepagewithoverriddenurls/count/$', remote_pages_with_overridden_urls_count),
50
53
    url(r'^django_roa_server/remotepagewithrelations/count/$', remote_pages_with_relations_count),
54
    url(r'^django_roa_server/remotepagewithrelationsthrough/count/$', remote_pages_with_relations_through_count),
51
55
    url(r'^django_roa_server/remotepagewithnamedrelations/count/$', remote_pages_with_named_relations_count),
52
56
    url(r'^django_roa_server/remotepagewithproxy/count/$', remote_pages_count),
53
57
    
@@ -58,6 +62,7 @@ urlpatterns = patterns('',
58
62
    url(r'^django_roa_server/remotepagewithcustomslug/?(?P<object_slug>[-\w]+)?/?$', remote_pages_with_custom_slug),
59
63
    url(r'^django_roa_server/remotepagewithoverriddenurls/?(?P<object_slug>[-\w]+)?/?$', remote_pages_with_overridden_urls),
60
64
    url(r'^django_roa_server/remotepagewithrelations/?(?P<id>\d+)?/?$', remote_pages_with_relations),
65
    url(r'^django_roa_server/remotepagewithrelationsthrough/?(?P<id>\d+)?/?$', remote_pages_with_relations_through),
61
66
    url(r'^django_roa_server/remotepagewithnamedrelations/?(?P<id>\d+)?/?$', remote_pages_with_named_relations),
62
67
    url(r'^django_roa_server/remotepagewithproxy/?(?P<id>\d+)?/?$', remote_pages),
63
68