How create django model with timestamptz field - django

I have responce data from API it's look like this
{
"api": {
"results": 1,
"fixtures": {
"65": {
"fixture_id": "65",
"event_timestamp": "1533927600",
"event_date": "2018-08-10T19:00:00+00:00",
"league_id": "2",
"round": "Premier League - 1",
"homeTeam_id": "33",
"awayTeam_id": "46",
"homeTeam": "Manchester United",
"awayTeam": "Leicester",
"status": "Match Finished",
"statusShort": "FT",
"goalsHomeTeam": "2",
"goalsAwayTeam": "1",
"halftime_score": "1 - 0",
"final_score": "2 - 1",
"penalty": null,
"elapsed": "95",
"firstHalfStart": "1533927660",
"secondHalfStart": "1533931380"
}
}
}
}
Now I am trying to build fixture model to store above data in PosgreSql database. I dont understand didnt find any example of builded model with timestamptz field. I need to store event_date key in timestamptz. Can anyone to show me how i should create this field

Django does not have a default timestamp field. However, you can add one by having the following model field:
event_date = models.DateTimeField(auto_now_add=True)
EDIT
Or alternatively, something a little more up to date:
from django.utils import timezone
....
event_date = models.DateTimeField(default=timezone.now)
Make sure its timezone.now and not timzone.now()

Related

Fetch and return category and all related objects

I have a Bookmark and a BookmarkCategory object. I'd like to be able to fetch JSON that looks like this:
GET -> localhost:8000/api/bookmarks
[
"python": {
"title": "Python",
"bookmarks": [
{
"title": "Python Documentation",
"url": "https://docs.python.org"
}
]
},
"javascript": {
"title": "Javascript",
"bookmarks": [
{
"title": "Python Documentation",
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript"
}
]
}
]
Here's my models:
class BookmarkCategory(models.Model):
title = models.CharField(max_length=255)
class Bookmark(models.Model):
title = models.CharField(max_length=255)
url = models.CharField(max_length=255)
category = models.ManyToManyField(BookmarkCategory)
Here's how I would query all the BookmarkCategory objects:
from .models import BookmarkCategory
bookmarks = BookmarkCategory.objects.all()
The JSON doesn't have to look exactly like this. I just need to get all my BookmarkCategory objects along with all the related Bookmark objects so I can iterate over them after I make a GET request to fetch them.
You'll have to use select_related on "bookmark_set", to fetch them along. If you are using DRF, you need to create a nested serializer configuration for bookmarks. Here is an example without DRF:
categories = BookmarkCategory.objects.select_related("bookmark_set")
items = []
for category in categories:
items.append(
{
"title": category.title,
"bookmarks": category.bookmark_set.values_list("title", "url"),
}
)

Django - Get a single timestamp per foreign key ID (MySQL)

Im having trouble getting only a single record per foreign key ID on the below model, I have tried this query, but it doesnt seem to be doing anything at all currently
I have used a RAW query which works, but I can't use a filter on it. ive also created a list and removed duplicates from the QuerySet but again I can't filter it because its a list
Query:
queryset = BGPData.objects.annotate(max_timestamp=Max('timestamp')).filter(timestamp=F('max_timestamp')).select_related(
'device_circuit_subnet__subnet',
'device_circuit_subnet__device',
'device_circuit_subnet__circuit',
'device_circuit_subnet__device__site',
)
Model:
class BGPData(models.Model):
device_circuit_subnet = models.ForeignKey(DeviceCircuitSubnets, verbose_name="Device", on_delete=models.CASCADE)
bgp_peer_as = models.CharField(max_length=20, verbose_name='BGP Peer AS', blank=True, null=True)
bgp_session = models.CharField(max_length=10, verbose_name='BGP Session', blank=True, null=True)
bgp_routes = models.CharField(max_length=10, verbose_name='BGP Routes Received', blank=True, null=True)
service_status = models.CharField(max_length=10, verbose_name='Service Status', blank=True, null=True)
timestamp = models.DateTimeField(auto_now=True, blank=True, null=True)
Sample Data im testing with (printed as a dict), there should only be one record for "device_circuit_subnet_id" : "10", the one which is newest.
I would like the latest record per device_circuit_subnet_id, so the query should return 3 results instead of 4, as there are 2 items with the same device_circuit_subnet_id.
ive read that distinct is used for this but were running MySQL, is there another way?
Thanks
[{
"id": 4,
"device_circuit_subnet_id" : "10",
"hostname": "EDGE",
"circuit_name": "MPLS",
"subnet": "172.1.1.1",
"subnet_mask": "/30",
"bgp_session": "1w2d",
"bgp_routes": "377",
"bgp_peer_as": "1",
"service_status": "Up",
"timestamp": "2019-11-18 16:16:17"
},
{
"id": 5,
"device_circuit_subnet_id" : "11",
"hostname": "INT-GW",
"subnet": "1.1.1.1",
"subnet_mask": "/24",
"bgp_session": null,
"bgp_routes": null,
"bgp_peer_as": null,
"service_status": "unknown",
"timestamp": "2019-08-07 14:46:00"
},
{
"id": 8,
"hostname": "EDGE",
"device_circuit_subnet_id" : "20",
"circuit_name": "MPLS 02",
"subnet": "172.2.1.1",
"subnet_mask": "/30",
"bgp_session": null,
"bgp_routes": null,
"bgp_peer_as": null,
"service_status": "unknown",
"timestamp": "2019-11-15 16:18:30"
},
{
"id": 9,
"hostname": "EDGE",
"device_circuit_subnet_id" : "10",
"circuit_name": "MPLS",
"subnet": "172.1.1.1",
"subnet_mask": "/30",
"bgp_session": "1w3d",
"bgp_routes": "385",
"bgp_peer_as": "1",
"service_status": "Up",
"timestamp": "2019-11-18 16:16:44"
}
]
Thanks
Have you tried this?
from django.db.models import Max, F
max_timestamp = Max('device_circuit_subnet__bgpdata__timestamp')
result = BGPData.objects.annotate(ts=max_timestamp).filter(timestamp=F('ts')).select_related(...)
I'm not sure about the performance of this query, but it will work :) :)
Django querysets are evaluated in a lazy fashion. As such, this query will only fetch one record from the database. The ordering on timestamp is in descending order due to the - prefix, so the latest timestamp value will be the first record.
queryset = BGPData.objects.all().order_by(
#prefix field name to order by with `-` to use Descending order
'-timestamp'
).select_related(
'device_circuit_subnet__subnet',
'device_circuit_subnet__device',
'device_circuit_subnet__circuit',
'device_circuit_subnet__device__site',
)[0]

Django JsonField Array data query

I have a jsonfield in Postgres db and data like below:
income_info = [
{
"id": "1",
"name": "A",
"min_income": 22000
},
{
"id": "2",
"name": "B",
"min_income": 40000
},
{
"id": "3",
"name": "C",
"min_income": 22000
}
]
Now want to use gte and lte over the django orm queryset. Already tried
Employee.objects.filter(income_info__min_income__lte = 4000000)
but did not work at all.
models.py:
class Employee(models.Model):
institute = models.ForeignKey(Institute, on_delete=models.DO_NOTHING)
income_info = JSONField(default=list)
others = models.TextField(null=True)
In django's documentation for querying JsonFields:
If the key is an integer, it will be interpreted as an index lookup in an array
As your json data is list of json datas, you need a query like this:
Employee.objects.filter(income_info__0__min_income__lte=4000000)

Joining 2 Models in Django

Im trying to join 2 tables in a django view. I currently have two models
The join could be done on ticker and date. As both models have them.
SSALiReport.objects.all()
NELiReport.objects.all()
NELI looks like this
{
"clout": 40000,
"date": "2018-05-15",
"sentiment": 500,
"ticker": "AAPL"
},
SALI looks like this
{
"date": "2018-05-15",
"market": "NYSE",
"prediction": 0.6,
"price": 300,
"ticker": "AAPL"
},
I want a third view that looks like this, lets call it FullReport
{
"date": "2018-05-15",
"market": "NYSE",
"prediction": 0.6,
"price": 300,
"ticker": "AAPL",
"clout": 40000,
"sentiment": 500
},
How do I pull this in a view? Also note I want to be able to many rows by date. So I'll need to join the two tables
for reference see the model
from django.contrib.postgres.fields import JSONField
from django.db import models
import datetime
# Create your models here.
class SSALiReport(models.Model):
date = models.DateField()
ticker = models.CharField(max_length=10,default='NA')
market = models.CharField(max_length=250,default='NA')
price = models.FloatField()
prediction = models.FloatField()
def __str__(self):
return str(self.date) + " - " + str(self.ticker)
class NELiReport(models.Model):
date = models.DateField()
ticker = models.CharField(max_length=10,default='NA')
sentiment = models.FloatField(default='0.0')
clout = models.FloatField(default='0.0')
top_news = JSONField(default='{}')
def __str__(self):
return str(self.date) + " - " + str(self.ticker)
this SQL script works
SELECT *
FROM api_neli_report, api_ssali_report
WHERE api_neli_report.ticker = api_ssali_report.ticker
AND api_neli_report.date = api_ssali_report.date
what is the django equivalent?
You could simply do a raw query, if you don't want to change your models.
See the documentation: Performing raw SQL queries

Django-REST-Framework "GroupBy" ModelSerializer

I have the following situation
class MyModel(models.Model):
key = models.CharField(max_length=255)
value = models.TextField(max_length=255)
category = models.CharField(max_length=4)
mode = models.CharField(max_length=4)
the fields key, category and mode are unique together. I have the following objects:
m1 = MyModel(key='MODEL_KEY', value='1', category='CAT_1' mode='MODE_1')
m2 = MyModel(key='MODEL_KEY', value='2', category='CAT_1' mode='MODE_2')
m3 = MyModel(key='MODEL_KEY', value='1', category='CAT_2' mode='MODE_1')
m4 = MyModel(key='MODEL_KEY', value='2', category='CAT_2' mode='MODE_2')
I want to expose an API that will group by key and category so the serialized data will look something like this:
{
"key": "MODEL_KEY",
"category": "CAT_1"
"MODE_1": { "id": 1, "value": "1" }
"MODE_2": { "id": 2, "value": "2" }
},
{
"key": "MODEL_KEY",
"category": "CAT_2"
"MODE_1": { "id": 3, "value": "1" }
"MODE_2": { "id": 4, "value": "2" }
}
Is there any way of doing this in django rest framework with ModelSerializer.
There is module that allows you to group Django models and still work with a QuerySet in the result: https://github.com/kako-nawao/django-group-by
Using the above to form your queryset:
# Postgres specific!
from django.contrib.postgres.aggregates.general import ArrayAgg
qs = MyModel.objects.group_by('key', 'category').annotate(
mode_list=ArrayAgg('mode')).order_by(
'key', 'category').distinct()
You can then access the properties key, category and mode_list on the resulting QuerySet items as attributes like qs[0].mode_list. Therefore, in your serializer you can simply name them as fields.
The model_list field might require a SerializerMethodField with some custom code to transform the list.
Note that you need an aggregation if you don't want to group by mode, as well.