Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/apigen/api.template.py b/planetstack/apigen/api.template.py
index 84f7613..6638808 100644
--- a/planetstack/apigen/api.template.py
+++ b/planetstack/apigen/api.template.py
@@ -2,6 +2,7 @@
 from rest_framework.response import Response
 from rest_framework.reverse import reverse
 from rest_framework import serializers
+from rest_framework import generics
 from core.models import *
 from django.forms import widgets
 
@@ -35,11 +36,15 @@
 class {{ object.camel }}Serializer(serializers.HyperlinkedModelSerializer):
 	id = serializers.Field()
 	{% for ref in object.refs %}
-	{{ ref.plural }} = serializers.HyperlinkedRelatedField(view_name='{{ ref }}-detail')
+	{% if ref.multi %}
+	{{ ref.plural }} = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='{{ ref }}-detail')
+	{% else %}
+	{{ ref }} = serializers.HyperlinkedRelatedField(read_only=True, view_name='{{ ref }}-detail')
+	{% endif %}
 	{% endfor %}
 	class Meta:
-		model = {{ object }}
-		fields = ({% for prop in object.props %}'{{ prop }}',{% endfor %})
+		model = {{ object.camel }}
+		fields = ({% for prop in object.props %}'{{ prop }}',{% endfor %}{% for ref in object.refs %}{%if ref.multi %}'{{ ref.plural }}'{% else %}'{{ ref }}'{% endif %},{% endfor %})
 {% endfor %}
 
 serializerLookUp = { 
@@ -53,7 +58,7 @@
 {% for object in generator.all %}
 
 class {{ object.camel }}List(generics.ListCreateAPIView):
-    #queryset = {{ object.camel }}.objects.all()
+    queryset = {{ object.camel }}.objects.select_related().all()
     serializer_class = {{ object.camel }}Serializer
     
     def get_queryset(self):
@@ -69,7 +74,7 @@
             return Response(status=status.HTTP_400_BAD_REQUEST)
 
 class {{ object.camel }}Detail(generics.RetrieveUpdateDestroyAPIView):
-    #queryset = {{ object.camel }}.objects.all()
+    queryset = {{ object.camel }}.objects.select_related().all()
     serializer_class = {{ object.camel }}Serializer
     
     def get_queryset(self):
diff --git a/planetstack/apigen/modelgen b/planetstack/apigen/modelgen
index 4c8a0f1..ef2730b 100755
--- a/planetstack/apigen/modelgen
+++ b/planetstack/apigen/modelgen
@@ -2,24 +2,35 @@
 
 import os
 import pdb
+import copy
 import sys
 import json
 import re
 from django.template import Context, Template
 
+blacklist = ['SingletonModel','PlCoreBase']
+
 # Django set up
 
 sys.path.append('.')
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
-from django.db.models.fields.related import ForeignKey
+from django.db.models.fields.related import ForeignKey, ManyToManyField
 from core.models import *
 
+def singular(foo, keys):
+	for k in keys:
+		if (foo==k+'es'):
+			return k
+		elif (foo==k+'s'):
+			return k
+	raise Exception('Plural to singular error for %s'%foo)
+
 g = globals()
 
 def enum_classes():
 	model_classes = []
 	for c in g.values():
-		if type(c)==type(PlCoreBase):
+		if type(c)==type(PlCoreBase) and c.__name__ not in blacklist:
 			model_classes.append(c)
 	return model_classes
 
@@ -32,17 +43,21 @@
 		self.model = m
 		self.props = []
 		self.refs = []
+		self.plural_name = None
 
 	def plural(self):
-		name = str(self)
-		if (name.endswith('s')):
-			return name+'es'
+		if (self.plural_name):
+			return self.plural_name
 		else:
-			return name+'s'
+			name = str(self)
+			if (name.endswith('s')):
+				return name+'es'
+			else:
+				return name+'s'
 
 	def camel(self):
 		name = str(self.model.__name__)
-		return name.title()
+		return name
 		
 class Generator(dict):
 	def all(self):
@@ -59,13 +74,61 @@
 
 	def compute_links(self):
 		for obj in self.values():
+			#if (str(obj)=='network'):
+			#	pdb.set_trace()
 			fields = obj.model._meta.fields
 			for f in fields:
-				if type(f)==ForeignKey and f.name in self.keys():
-					refobj = self[f.name]
-					obj.refs.append(refobj)
+				if (f and f.rel):
+					to_name = str(f.rel.to)
+				else:
+					to_name = None
+
+				if type(f)==ForeignKey and to_name and to_name in self.keys():
+					refobj = self[f.to_name]
+
+					if (str(obj)=='slice' and f.to_name=='networks'):
+						obj.refs.append(refobj)
+					related_name = f.related_query_name()
+					if (related_name!='+' and related_name.lower()!=str(obj).lower()):
+						cobj = copy.deepcopy(obj)
+						cobj.multi = True
+						cobj.plural_name = related_name
+						#if (str(refobj)=='slice' and related_name=='networks'):
+						#	pdb.set_trace()
+						refobj.refs.append(cobj)
 				else:
 					obj.props.append(f.name)
+
+			m2m = obj.model._meta.many_to_many
+			for f in m2m:
+				try:
+					related_model_name = f.m2m_reverse_field_name()
+				except:
+					related_model_name = f.m2m_db_table().rsplit('_',1)[-1]
+
+				related_name = f.related_query_name()
+				if related_model_name in self.keys():
+			#		pdb.set_trace()
+					refobj = self[related_model_name]
+					cobj = copy.deepcopy(obj)
+					cobj.multi=True
+					refobj.refs.append(cobj)
+				
+				if (related_name!='+' and related_name.lower()!=str(obj).lower()):
+					cobj = copy.deepcopy(obj)
+					cobj.multi = True
+					cobj.plural_name = related_name
+
+					#if (str(refobj)=='slice' and related_name=='networks'):
+					#	pdb.set_trace()
+					refobj.refs.append(cobj)
+
+					#if (related_name=='networks'):
+						#pdb.set_trace()
+						#print str(refobj)
+
+
+
 			
 def main():
 	try:
diff --git a/planetstack/apigen/simple.template.txt b/planetstack/apigen/simple.template.txt
index 109927e..fb00670 100644
--- a/planetstack/apigen/simple.template.txt
+++ b/planetstack/apigen/simple.template.txt
@@ -1,7 +1,8 @@
 {% for object in generator.all %}
 Object {{ object }}:
 Refs:
-{% for ref in object.refs %}{{ ref }}{% endfor %}
+{% for ref in object.refs %}
+{{ ref }}{% endfor %}
 Props:
 {% for prop in object.props %}{{ prop }}
 {% endfor %}
diff --git a/planetstack/planetstack/urls.py b/planetstack/planetstack/urls.py
index 49b144f..599b20b 100644
--- a/planetstack/planetstack/urls.py
+++ b/planetstack/planetstack/urls.py
@@ -16,7 +16,7 @@
 from core.views.slice_privileges import SlicePrivilegeList, SlicePrivilegeDetail
 from core.views.slivers import SliverList, SliverDetail
 from core.views.tags import TagList, TagDetail
-from core.views.users import UserList, UserDetail
+from genapi import UserList, UserDetail
 from core.views.legacyapi import LegacyXMLRPC
 #from core.views.analytics import AnalyticsAjaxView
 from core.models import *