Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restangular, Django REST and relations

I'm using Django REST Framework for modelling a REST API that uses a lot of model relations.

What's an easy and good way to resolve those relations at the frontend level using AngularJS and Restangular?

Models

This is how part of my models look like:

class Country( Model ):
  name = CharField( max_length = 256 )

class City( Model ):
  name = CharField( max_length = 256 )
  postal_code = CharField( max_length = 16 )

  country = ForeignKey( "Country" )

class Customer( Model ):
  first_name = CharField( max_length = 256 )
  last_name = CharField( max_length = 256 )

  city = ForeignKey( "City" )

Fetching the data

The following JavaScript code shows how I load the data: (I actually use the promises returned by all(), but $object is shorter for explaining this)

$scope.countries = [];
$scope.cities = [];
$scope.customers = [];

Restangular.all( "countries" ).getList().$object;
Restangular.all( "cities" ).getList().$object;
Restangular.all( "customers" ).getList().$object;

Here's an example of a cities reponse: (all, without exception, models contain an id field)

[{"id": 1, "name": "Bocholt", "postal_code": "46397", "country": 1}]

Displaying the data

And finally the AngularJS part for displaying the data; the code you see here is how I'd like to use it:

<table>
  <tbody>
    <tr ng-repeat="customer in customers">
      <td>{{ customer.first_name }}</td>
      <td>{{ customer.last_name }}</td>
      <td>{{ cities[customer.city].name }}</td>
      <td>{{ countries[cities[customer.city].country].name }}</td>
    </tr>
  </tbody>
</table>

Admittedly the nested statement looks a little bit ugly, but considering the fact that the original data stays intact, I'm fine with doing it like that.


Unfortunately the code does (of course) not work. What's a good way to solve such kind of relations?


Clue: I'm willing to change my way of doing things at any of the involved frameworks/programs (Django, Django REST, AngularJS, Restangular etc.).

like image 778
stschindler Avatar asked Sep 30 '22 05:09

stschindler


1 Answers

I believe the best way to do this is to create nested serailizers. You'll have to switch out the serializer on posts, but on list and retrieves a serializer like this would work.

class CountrySerializer(serializer.ModelSerializer):
    class Meta:
        model = Country


class CitySerializer(serializer.ModelSerializer):
    country = CountrySerializer()
    class Meta:
        model = City

class CustomerSerializer(serializer.ModelSerializer):
    city = CitySerializer()
    class Meta:
        model = Customer

class CustomerViewSet(viewsets.ModelViewSet):
    model = Customer
    serializer_class = CustomerSerializer
    queryset = Customer.objects.all()

And then your Restangular just has to hit the api and the object is properly nested

Restangular.all('costumers').one(1).get().then(function(response) {
    $scope.costumer = response; 
})
like image 172
user133688 Avatar answered Oct 14 '22 02:10

user133688