Отображение представления Django с данными, классифицированными по принципу "один ко многим".
У меня отношения один ко многим:
class SessionGPS(models.Model):
start_timestamp = models.IntegerField()
end_timestamp= models.IntegerField()
class GPSData(models.Model):
longitude = models.DecimalField(max_digits=15, decimal_places=13)
lat = models.DecimalField(max_digits=15, decimal_places=13)
session_new = models.ForeignKey(SessionGPS, on_delete=models.CASCADE, related_name="sesion_gps")
Каждая запись SessionGPS имеет несколько записей GPSData. Сессия состоит из набора GPS-координат. Этот набор находится в модели GPSData.
Мне нужно запросить SessionGPS на основе начальной и конечной временных меток:
def date_search(request):
data = request.body.decode("utf-8")
start=int(datetime.datetime.strptime(request.POST['start'], '%Y-%m-%d').timestamp())
end=int(datetime.datetime.strptime(request.POST['end'], '%Y-%m-%d').timestamp())
res = GPSData.objects.filter(session_new_id__start_timestamp__gte=start,session_new_id__end_timestamp__lte=end)
res = serializers.serialize("json", res)
return HttpResponse(res, content_type='application/json')
Таким образом, я получаю все GPSData между временными метками, но они не классифицируются по сессиям, а объединяются.
Мне нужно получить запрос следующего вида:
session 1 ->> all GPSData of that session 1
session 2 ->> all GPSData of that session 2
Так что в шаблоне я могу сделать вот так:
For GPSData in session 1 do something
For GPSData in session 2 do something
etc.
Я пытался вернуть несколько запросов в представление, но это не сработало.
Спасибо за любую помощь.
Я не думаю, что существует вариант запроса для того, что вы хотите. Поэтому единственный способ, который я могу придумать, это пост-обработка данных:
models.py:
class SessionGPS(models.Model):
start_timestamp = models.DateTimeField(auto_now_add=True)
end_timestamp = models.DateTimeField(null=True)
class GPSData(models.Model):
longitude = models.DecimalField(max_digits=15, decimal_places=13)
latitude = models.DecimalField(max_digits=15, decimal_places=13)
session = models.ForeignKey(SessionGPS, on_delete=models.CASCADE, related_name="sesion_gps")
views.py:
def gps_timestamps(request):
if request.method == 'POST':
start = request.POST.get('start_date').split('-')
end = request.POST.get('end_date').split('-')
start_date = datetime.datetime(int(start[0]), int(start[1]), int(start[2]))
end_date = datetime.datetime(int(end[0]), int(end[1]), int(end[2]))
data_rows = GPSData.objects.filter(session__start_timestamp__gte=start_date,session__end_timestamp__lte=end_date)
# Initialize dictionary
# with unique sessions keys inside the queryset
data = {}
for row in data_rows:
if row.session.id not in data:
data[row.session.id] = {
'start_time': row.session.start_timestamp.strftime("%Y-%m-%d"),
'end_time': row.session.end_timestamp.strftime("%Y-%m-%d"),
}
else:
pass
# Populate
for key, value in data.items():
gps_data_list = []
for row in data_rows:
if row.session.id == key:
gps_data_list.append( {'latitude': str(row.latitude), 'longitude': str(row.longitude)} )
data[key].update(data=gps_data_list)
# If you really want JSON
json_object = json.dumps(data, indent = 4)
print(json_object)
context = {
'data': data
}
return render(request, 'gps_timestamp.html', context)
gps_timestamp.html (я использовал bootstrap 5), два входа с форматом yyyy-mm-dd:
<div class="container">
<form action="{% url 'app:urlname' %}" method="post">
{% csrf_token %}
<div class="form-group mb-3">
<label class="form-label" for="start_date">Start Date</label>
<input id="start_date" name="start_date" type="text" class="form-control" placeholder="year-month-day" aria-label="start_date">
</div>
<div class="form-group mb-3">
<label class="form-label" for="end_date">End Date</label>
<input id="end_date" name="end_date" type="text" class="form-control" placeholder="year-month-day" aria-label="end_date">
</div>
<input type="submit" value="OK">
</form>
</div>
<div class="container d-flex justify-content-center" style="flex-direction: column;">
{% for key, obj in data.items %}
<p>Session ID: {{key}}</p>
<p>Start Time: {{obj.start_time}}</p>
<p>End Time: {{obj.end_time}}</p>
<p>GPS Data:</p>
{% for row in obj.data %}
{{row}}
<br>
{% endfor %}
<p>----------------------------------</p>
{% endfor %}
</div>
JSON вывод моего теста:
{
"2": {
"start_time": "2022-11-25",
"end_time": "2022-11-26",
"data": [
{
"latitude": "70.7762500000000",
"longitude": "12.4800500000000"
},
{
"latitude": "42.7545200000000",
"longitude": "71.1392900000000"
},
{
"latitude": "56.1794700000000",
"longitude": "90.8119600000000"
}
]
},
"3": {
"start_time": "2022-11-27",
"end_time": "2022-11-28",
"data": [
{
"latitude": "10.1099500000000",
"longitude": "-19.2024500000000"
},
{
"latitude": "80.1405100000000",
"longitude": "16.2555700000000"
},
{
"latitude": "-16.1924200000000",
"longitude": "-51.7266300000000"
},
{
"latitude": "19.4745700000000",
"longitude": "10.7191800000000"
}
]
}
}
Кстати, я должен упомянуть, что у меня были некоторые проблемы с вашей моделью GPSData, когда либо широта, либо логарифм имели 3 цифры. Например, 123.3123123. Она принимает только <100, но я не стал разбираться с этим.
Только что изменил SessionGPS для лучшего доступа к данным.