Commit 7cc2242d authored by Jean-Baptiste's avatar Jean-Baptiste

update: Automatically generate urls from models

parent 36995359
......@@ -34,13 +34,19 @@ In the future it could also be used to auto configure django router (e.g. urls.p
from djangoldp.models import Model
class Todo(Model):
container_path = "/my-path/"
name = models.CharField(max_length=255)
deadline = models.DateTimeField()
3.1. Configure field visibility (optional)
3.1. Configure container path (optional)
By default it will be "todos/" with an S for model called Todo
<Model>._meta.container_path = "/my-path/"
3.2. Configure field visibility (optional)
Note that at this stage you can limit access to certain fields of models using
......@@ -68,12 +74,18 @@ from djangoldp.views import LDPViewSet
from .models import Todo
urlpatterns = [
url(r'^todos/', LDPViewSet.urls(model=Todo)),
url(r'^', include('djangoldp.urls')),
url(r'^admin/',, # Optional
This creates 2 routes, one for the list, and one with an ID listing the detail of an object.
This creates 2 routes for each Model, one for the list, and one with an ID listing the detail of an object.
You could also only use this line in instead:
ROOT_URLCONF = 'djangoldp.urls'
5. In the file, add your application name at the beginning of the application list, and add the following lines
......@@ -4,10 +4,22 @@ from django.urls import get_resolver
class Model(models.Model):
container_path = None
def get_container_path(self):
return self.container_path
def get_view_set(cls):
view_set = getattr(cls._meta, 'view_set', None)
if view_set is None:
from djangoldp.views import LDPViewSet
view_set = LDPViewSet
return view_set
def get_container_path(cls):
path = getattr(cls._meta, 'container_path', None)
if path is None:
path = "{}s".format(cls._meta.object_name.lower())
return path
def get_absolute_url(self):
return Model.resource_id(self)
......@@ -26,9 +38,7 @@ class Model(models.Model):
def container_id(cls, instance):
if isinstance(instance, cls):
path = instance.container_path
if path is None:
path = "{}s".format(instance._meta.object_name.lower())
path = instance.get_container_path()
view_name = '{}-list'.format(instance._meta.object_name.lower())
path = get_resolver().reverse(view_name)
......@@ -69,6 +79,7 @@ class Model(models.Model):
path = "{}/".format(path)
return path
class LDPSource(models.Model):
container = models.URLField()
federation = models.CharField(max_length=255)
......@@ -9,6 +9,7 @@ settings.configure(DEBUG=True,
......@@ -29,11 +29,10 @@ class LDPModelTest(TestCase):
result = Model.resolve_container("/dummys/")
self.assertEquals(Dummy, result)
@unittest.skip("futur feature: avoid on apps")
def test_auto_url(self):
from django.urls import get_resolver
dummy = LDPDummy.objects.create(some="text")
view_name = '{}-list'.format(dummy._meta.object_name.lower())
path = '/{}'.format(get_resolver().reverse_dict[view_name][0][0][0],
path = '/{}{}'.format(get_resolver().reverse_dict[view_name][0][0][0],
self.assertEquals(path, dummy.get_absolute_url())
from django.conf import settings
from django.conf.urls import url, include
from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy, LDPDummy
from djangoldp.tests.models import Skill, JobOffer, Message, Thread, Dummy
from djangoldp.views import LDPViewSet
from django.conf.urls import url
urlpatterns = [
url(r'^skills/', LDPViewSet.urls(model=Skill, permission_classes=[], fields=["@id", "title"], nested_fields=[])),
......@@ -12,5 +11,6 @@ urlpatterns = [
url(r'^threads/', LDPViewSet.urls(model=Thread, nested_fields=["message_set"], permission_classes=())),
url(r'^users/', LDPViewSet.urls(model=settings.AUTH_USER_MODEL, permission_classes=[])),
url(r'^dummys/', LDPViewSet.urls(model=Dummy, permission_classes=[])),
url(r'^ldp-dummys/', LDPViewSet.urls(model=LDPDummy, permission_classes=[])),
\ No newline at end of file
url(r'^', include('djangoldp.urls')),
from importlib import import_module
from django.conf import settings
from django.conf.urls import url, include
from djangoldp.models import LDPSource, Model
from djangoldp.views import LDPSourceViewSet
def __clean_path(path):
if path.startswith("/"):
path = path[1:]
if not path.endswith("/"):
path = "{}/".format(path)
return path
urlpatterns = [
url(r'^sources/', LDPSourceViewSet.urls(model=LDPSource)),
for package in settings.DJANGOLDP_PACKAGES:
model_classes = {cls.__name__: cls for cls in Model.__subclasses__()}
for class_name in model_classes:
model_class = model_classes[class_name]
path = __clean_path(model_class.get_container_path())
urls_fct = model_class.get_view_set().urls
urlpatterns.append(url(r'^' + path, include(
permission_classes=getattr(model_class._meta, 'permission_classes', []),
fields=getattr(model_class._meta, 'serializer_fields', []),
nested_fields=getattr(model_class._meta, 'nested_fields', [])))))
......@@ -6,6 +6,7 @@ from django.core.urlresolvers import get_resolver
from django.db.utils import OperationalError
from django.shortcuts import get_object_or_404
from django.utils.decorators import classonlymethod
from djangoldp.models import LDPSource
from guardian.shortcuts import get_objects_for_user
from pyld import jsonld
from rest_framework.authentication import SessionAuthentication
......@@ -13,7 +14,6 @@ from rest_framework.parsers import JSONParser
from rest_framework.renderers import JSONRenderer
from rest_framework.viewsets import ModelViewSet
from .models import LDPSource
from .serializers import LDPSerializer
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment