Display friends on map

This commit is contained in:
Gabriel Augendre 2019-03-02 12:47:44 +01:00
parent 02cb38219c
commit 940cb1e413
12 changed files with 234 additions and 5 deletions

View file

@ -16,6 +16,7 @@
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="leaflet" level="application" />
</component> </component>
<component name="TemplatesService"> <component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Django" /> <option name="TEMPLATE_CONFIGURATION" value="Django" />

View file

@ -14,8 +14,9 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import path from django.urls import path, include
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('', include('map.urls')),
] ]

View file

@ -1,5 +1,15 @@
from django.contrib import admin from django.contrib import admin
from django.contrib.admin import register
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from .models import Friend from .models import Friend, FriendLocation
admin.site.register(Friend, UserAdmin) admin.site.register(Friend, UserAdmin)
@register(FriendLocation)
class FriendLocationAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ('friend',)}),
('Place', {'fields': ('latitude', 'longitude')}),
('Dates', {'fields': ('start_date', 'end_date')}),
]

11
map/fields.py Normal file
View file

@ -0,0 +1,11 @@
from django.db import models
class CoordinateField(models.DecimalField):
def __init__(self, *args, **kwargs):
kwargs['max_digits'] = 11
kwargs['decimal_places'] = 8
kwargs['help_text'] = ('Format : xxx,xxxxxxxx<br>'
'(max 8 décimales, max 3 chiffres avant la virgule, séparateur : virgule)')
super().__init__(*args, **kwargs)

View file

@ -0,0 +1,29 @@
# Generated by Django 2.1.7 on 2019-03-02 11:13
from django.db import migrations, models
import map.fields
class Migration(migrations.Migration):
dependencies = [
('map', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='FriendLocation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('latitude', map.fields.CoordinateField(decimal_places=8, help_text='Format : xxx,xxxxxxxx<br>(max 8 décimales, max 3 chiffres avant la virgule, séparateur : virgule)', max_digits=11)),
('longitude', map.fields.CoordinateField(decimal_places=8, help_text='Format : xxx,xxxxxxxx<br>(max 8 décimales, max 3 chiffres avant la virgule, séparateur : virgule)', max_digits=11)),
('start_date', models.DateField(blank=True, null=True, verbose_name='from')),
('end_date', models.DateField(blank=True, null=True, verbose_name='until')),
],
options={
'abstract': False,
},
),
]

View file

@ -0,0 +1,21 @@
# Generated by Django 2.1.7 on 2019-03-02 11:17
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('map', '0002_friendlocation'),
]
operations = [
migrations.AddField(
model_name='friendlocation',
name='friend',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
]

View file

@ -1,10 +1,36 @@
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from map.fields import CoordinateField
class BaseModel(models.Model):
class Meta:
abstract = True
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Friend(AbstractUser): class Friend(AbstractUser):
pass pass
# class Location(models.Model): class FriendLocation(BaseModel):
# latitude = models. latitude = CoordinateField()
longitude = CoordinateField()
start_date = models.DateField('from', blank=True, null=True)
end_date = models.DateField('until', blank=True, null=True)
friend = models.ForeignKey(Friend, on_delete=models.CASCADE)
@property
def latitude_str(self):
return str(self.latitude)
@property
def longitude_str(self):
return str(self.longitude)
def __str__(self):
return f'{self.friend.get_full_name()} from {self.start_date} to {self.end_date}'

4
map/static/map/style.css Normal file
View file

@ -0,0 +1,4 @@
#map {
height: 70vh;
margin-top: 1rem;
}

View file

@ -0,0 +1,82 @@
{% load static %}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- Fontawesome CSS -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css"
integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="stylesheet" href="{% static 'map/style.css' %}">
{% block add-head %}
{% endblock %}
<title>{{ app.site.name }} &centerdot; {% block title %}Home{% endblock %}</title>
</head>
<body>
{#{% include 'map/navbar.html' %}#}
<div class="container">
{% for message in messages %}
<div class="alert alert-dismissible alert-{{ message.tags }} fade show" role="alert">
{{ message|safe }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
<div class="row">
<div class="col-12">
<h1>{% block h1 %}{% endblock %}</h1>
</div>
</div>
{% block quick_actions %}
{% if quick_actions %}
<div class="row">
<div class="col-12 d-none d-md-block"> {# Visible only on large screens #}
{% for qa in quick_actions %}
<a href="{{ qa.url }}" class="btn btn-{{ qa.category }}">
{% if qa.icon %}<i class="{{ qa.icon }}"></i>{% endif %}
{{ qa.display }}
</a>
{% endfor %}
</div>
<div class="col-12 d-md-none"> {# Visible only on small screens #}
{% for qa in quick_actions %}
<a href="{{ qa.url }}" class="btn btn-{{ qa.category }} btn-block">
{% if qa.icon %}<i class="{{ qa.icon }}"></i>{% endif %}
{{ qa.display }}
</a>
{% endfor %}
</div>
</div>
{% endif %}
{% endblock %}
{% block content %}
{% endblock %}
</div>
<!-- Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
{% block js %}
{% endblock %}
</body>
</html>

View file

@ -0,0 +1,32 @@
{% extends 'map/base.html' %}
{% load static %}
{% block title %}Carte autour de {{ place }}{% endblock %}
{% block h1 %}Carte autour de {{ place }}{% endblock %}
{% block add-head %}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"
integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
crossorigin=""/>
{% endblock %}
{% block content %}
<div id="map"></div>
{% endblock %}
{% block js %}
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"
integrity="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg=="
crossorigin=""></script>
<script type="application/javascript">
let map = L.map('map').setView([45.805, 2.67], 5);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
{% for location in locations %}
let marker = L.marker([{{ location.latitude_str }}, {{ location.longitude_str }}]).addTo(map);
marker.bindPopup("<strong>{{ location.friend.get_full_name }}</strong> from {{ location.start_date }} until {{ location.end_date }}").openPopup();
{% endfor %}
</script>
{% endblock %}

6
map/urls.py Normal file
View file

@ -0,0 +1,6 @@
from django.urls import path
from map import views
urlpatterns = [
path('map/', views.MapView.as_view()),
]

View file

@ -1,3 +1,9 @@
from django.shortcuts import render from django.shortcuts import render
from django.views.generic import ListView
from map import models
# Create your views here.
class MapView(ListView):
model = models.FriendLocation
context_object_name = 'locations'
template_name = 'map/map.html'