localization.py 4.79 KB
Newer Older
1
from django.db import models
Florent Chehab's avatar
Florent Chehab committed
2
from rest_framework import serializers, viewsets, permissions
3

Florent Chehab's avatar
Florent Chehab committed
4
5
6
7
8
9
10
11
12
# Data model based on : https://unstats.un.org/unsd/methodology/m49/overview/


class Region(models.Model):
    name = models.CharField(max_length=200)
    un_code = models.CharField(primary_key=True, max_length=3)
    parent = models.ForeignKey(
        'self', on_delete=models.SET_NULL, null=True)

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    def r_type(self):
        p = 0
        region = self
        while region.parent is not None:
            p += 1
            region = region.parent

        if p is 0:
            return "main"
        elif p is 1:
            return "sub"
        elif p is 2:
            return "inter"
        else:
            raise Exception("Impossible case found")

Florent Chehab's avatar
Florent Chehab committed
29

30
class Country(models.Model):
31
    name = models.CharField(max_length=200)
Florent Chehab's avatar
Florent Chehab committed
32
33
34
    iso_alpha3_code = models.CharField(primary_key=True, max_length=3)
    region = models.ForeignKey(Region, on_delete=models.PROTECT, null=True)

35
36
37
38
39
40
41
42
    def get_regions(self):
        regions = [None] * 3
        regions.append(self.region)
        while regions[-1] is not None and regions[-1].parent is not None:
            regions.append(regions[-1].parent)
        regions = regions[::-1]
        return regions[0:3]

Florent Chehab's avatar
Florent Chehab committed
43

Florent Chehab's avatar
Florent Chehab committed
44
45
46
47
48
49
50
51
52
class City(models.Model):
    name = models.CharField(max_length=200)
    local_name = models.CharField(max_length=200, null=True)
    # We add an area to distinguish similarly named cities
    # in a country
    area = models.CharField(max_length=200, null=True)
    country = models.ForeignKey(Country, on_delete=models.PROTECT)


Florent Chehab's avatar
Florent Chehab committed
53
54
55
"""
API RELATED STUFF BELLOW
"""
Florent Chehab's avatar
Florent Chehab committed
56
57


Florent Chehab's avatar
Florent Chehab committed
58
59
60
61
class CountrySerializer(serializers.ModelSerializer):
    regions = serializers.SerializerMethodField()

    def get_regions(self, obj):
62
63
64
65
66
67
68
69
70
71
72
73
        regions = obj.get_regions()

        def get_info(i):
            r = regions[i]
            r_code = r.un_code if r is not None else None
            return {"code": r_code,
                    "url": self.get_region_url(regions[i])}
        res = {}
        res["main"] = get_info(0)
        res["sub"] = get_info(1)
        res["inter"] = get_info(2)
        return res
Florent Chehab's avatar
Florent Chehab committed
74
75
76
77
78
79
80
81
82
83
84

    def get_region_url(self, region):
        if region is None:
            return None

        return serializers.HyperlinkedRelatedField(
            view_name='country-detail',
            read_only=True) \
            .get_url(region, view_name='region-detail',
                     request=self.context['request'], format=None)

Florent Chehab's avatar
Florent Chehab committed
85
86
    class Meta:
        model = Country
Florent Chehab's avatar
Florent Chehab committed
87
        fields = ('name', 'iso_alpha3_code',
88
                  'region', 'regions')
Florent Chehab's avatar
Florent Chehab committed
89
90


Florent Chehab's avatar
Florent Chehab committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
class DictModeViewSet(viewsets.ModelViewSet):
    """
    ViewSet that renders data as dict with keys corresponding to the model
    primary key. Instead of list.
    """

    def list(self, request, *args, **kwargs):
        response = super(viewsets.ModelViewSet, self).list(
            request, *args, **kwargs)  # call the original 'list'
        pk_attr_name = self.serializer_class.Meta.model._meta.pk.name
        response.data = {
            d[pk_attr_name]: d for d in response.data
        }
        return response


class CountryViewSet(DictModeViewSet):
Florent Chehab's avatar
Florent Chehab committed
108
109
110
    permission_classes = (permissions.DjangoModelPermissions,)
    queryset = Country.objects.all()  # noqa: E1101
    serializer_class = CountrySerializer
Florent Chehab's avatar
Florent Chehab committed
111
112


Florent Chehab's avatar
Florent Chehab committed
113
114
class RegionSerializer(serializers.ModelSerializer):
    parent_url = serializers.SerializerMethodField()
115
    region_type = serializers.SerializerMethodField()
Florent Chehab's avatar
Florent Chehab committed
116
117
118
119
120
121
122
123
124
125
126

    def get_parent_url(self, obj):
        if obj.parent is None:
            return None

        return serializers.HyperlinkedRelatedField(
            view_name='country-detail',
            read_only=True) \
            .get_url(obj.parent, view_name='region-detail',
                     request=self.context['request'], format=None)

127
128
129
    def get_region_type(self, obj):
        return obj.r_type()

Florent Chehab's avatar
Florent Chehab committed
130
131
    class Meta:
        model = Region
132
        fields = ('name', 'un_code', 'parent', 'parent_url', 'region_type')
Florent Chehab's avatar
Florent Chehab committed
133
134


Florent Chehab's avatar
Florent Chehab committed
135
class RegionViewSet(DictModeViewSet):
Florent Chehab's avatar
Florent Chehab committed
136
137
138
    permission_classes = (permissions.DjangoModelPermissions,)
    queryset = Region.objects.all()  # noqa: E1101
    serializer_class = RegionSerializer
Florent Chehab's avatar
Florent Chehab committed
139
140
141
142
143
144
145
146
147


class CitySerializer(serializers.ModelSerializer):
    country_url = serializers.SerializerMethodField()

    def get_country_url(self, obj):
        return serializers.HyperlinkedRelatedField(
            view_name='country-detail',
            read_only=True) \
Florent Chehab's avatar
Florent Chehab committed
148
            .get_url(obj.country, view_name='country-detail',
Florent Chehab's avatar
Florent Chehab committed
149
150
151
152
                     request=self.context['request'], format=None)

    class Meta:
        model = City
Florent Chehab's avatar
Florent Chehab committed
153
        fields = ('name', 'local_name', 'area', 'country', 'country_url', 'id')
Florent Chehab's avatar
Florent Chehab committed
154
155


Florent Chehab's avatar
Florent Chehab committed
156
class CityViewSet(DictModeViewSet):
Florent Chehab's avatar
Florent Chehab committed
157
158
159
    permission_classes = (permissions.DjangoModelPermissions,)
    queryset = City.objects.all()  # noqa: E1101
    serializer_class = CitySerializer