Different map pins using Mapbox-gl-js with Django

Viewed 1827

I'm trying to create a dynamic map of places for my travel blog with Django to be automatically updated based on new entries in database. So far it's going quite good (link: http://puchalatravel.com/map) What I'm having issues with is creating different colour pins based on status field in the database. I'd like to have 4 colors for 4 different status options.

I don't know JavaScript well enough to know how to approach the issue. I've googled and tried JS for() loops but didn't manage to make it work..

Currently my code looks as follows: models.py

class PlaceStatus(models.Model):
    status = models.CharField(max_length=32)

    class Meta:
        verbose_name_plural = "Place statuses"

    def __unicode__(self):
        return self.status

    def __str__(self):
        return self.status


class Place(models.Model):
    name = models.CharField(max_length=32)
    coord_v = models.FloatField()
    coord_h = models.FloatField()
    status = models.ForeignKey(PlaceStatus, on_delete=models.CASCADE)
    trip = models.ManyToManyField(Trip, blank=True, null=True)
    images = models.ManyToManyField(Image, blank=True, null=True)

    def __unicode__(self):
        return self.name

    def __str__(self):
        return self.name

views.py

def map(request):
    places = Place.objects.all()
    return render(request, 'blog/map.html', {'places': places})

map.html

{% extends 'blog/base.html' %}

{% block header %}
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.css' rel='stylesheet'/>
{% endblock %}

{% block banner %}
{% endblock %}

{% block two_columns %}

<div id='map'></div>

<script>

mapboxgl.accessToken = 'pk.eyJ1IjoibWljaGFscHVjaGFsYSIsImEiOiJjamxxeWk0ZTYwcWJyM3BwbGVzMWpobjFqIn0.sBxqcK2lDMxn9RvqaBfduw';

var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
center: [0, 40],
zoom: 1.0
});

var geojson = {
type: 'FeatureCollection',
features: [
{% for place in places %}
    {
    type: 'Feature',
    geometry: {
        type: 'Point',
        coordinates: [{{ place.coord_h }}, {{ place.coord_v }}]
    },
    properties: {
        title: '{{ place.name }}',
        description: '{{ place.status }}'
    }
    },
{% endfor %}
]
};

// add markers to map
geojson.features.forEach(function(marker) {

// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker-green';

// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
});

</script>
{% endblock %}

default.css

#map {
width:100%;
height: 90%
}

.marker-green {
background-image: url(../pictures/green_pin.png);
background-size: cover;
width: 15px;
height: 15px;
border-radius: 50%;
cursor: pointer;
}

.marker-red {
background-image: url(../pictures/red_pin.png);
background-size: cover;
width: 15px;
height: 15px;
border-radius: 50%;
cursor: pointer;
}

You can find all code in this GitHub repo: https://github.com/michalpuchala/puchalatravel

What's the easiest or most reliable way to create a conditioning in the map.html JS that would pick different color (i.e. different CSS class) depending on the value of status?

1 Answers

Ok, I figured it out in the end.

views.py

def map(request):
    planned_places = Place.objects.filter(status=1)
    visited_places = Place.objects.filter(status=2)
    planned_wedding_places = Place.objects.filter(status=3)
    visited_wedding_places = Place.objects.filter(status=4)
    return render(request, 'blog/map.html',
                {'planned_places': planned_places,
                'visited_places': visited_places,
                'planned_wedding_places': planned_wedding_places,
                'visited_wedding_places': visited_wedding_places})

map.html

{% extends 'blog/base.html' %}

{% block header %}
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.css' rel='stylesheet'/>
{% endblock %}

{% block banner %}
{% endblock %}

{% block two_columns %}

<div id='map'></div>

<script>

mapboxgl.accessToken = 'pk.eyJ1IjoibWljaGFscHVjaGFsYSIsImEiOiJjamxxeWk0ZTYwcWJyM3BwbGVzMWpobjFqIn0.sBxqcK2lDMxn9RvqaBfduw';

var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
center: [0, 40],
zoom: 1.0
});

// planned
var geojson_planned = {
type: 'FeatureCollection',
features: [
{% for i in planned_places %}
    {
    type: 'Feature',
    geometry: {
        type: 'Point',
        coordinates: [{{ i.coord_h }}, {{ i.coord_v }}]
    },
    properties: {
        title: '{{ i.name }}',
        description: '{{ i.status }}'
    }
    },
{% endfor %}
]
};

// add markers to map
geojson_planned.features.forEach(function(marker) {

// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker-light-red';

// visited
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
});

var geojson_visited = {
type: 'FeatureCollection',
features: [
{% for i in visited_places %}
    {
    type: 'Feature',
    geometry: {
        type: 'Point',
        coordinates: [{{ i.coord_h }}, {{ i.coord_v }}]
    },
    properties: {
        title: '{{ i.name }}',
        description: '{{ i.status }}'
    }
    },
{% endfor %}
]
};

// add markers to map
geojson_visited.features.forEach(function(marker) {

// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker-light-green';

// planned wedding
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
});

var geojson_planned_wedding = {
type: 'FeatureCollection',
features: [
{% for i in planned_wedding_places %}
    {
    type: 'Feature',
    geometry: {
        type: 'Point',
        coordinates: [{{ i.coord_h }}, {{ i.coord_v }}]
    },
    properties: {
        title: '{{ i.name }}',
        description: '{{ i.status }}'
    }
    },
{% endfor %}
]
};

// add markers to map
geojson_planned_wedding.features.forEach(function(marker) {

// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker-red';

// visited_wedding
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
});

var geojson_visited_wedding = {
type: 'FeatureCollection',
features: [
{% for i in visited_wedding_places %}
    {
    type: 'Feature',
    geometry: {
        type: 'Point',
        coordinates: [{{ i.coord_h }}, {{ i.coord_v }}]
    },
    properties: {
        title: '{{ i.name }}',
        description: '{{ i.status }}'
    }
    },
{% endfor %}
]
};

// add markers to map
geojson_visited_wedding.features.forEach(function(marker) {

// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker-green';

// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
});

</script>
{% endblock %}
Related