Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Database migration #68

Merged
merged 11 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,5 @@ dmypy.json
cython_debug/

# docker compose production environment
docker-compose.prod.yml
docker-compose.prod.yml
db_backup
27 changes: 27 additions & 0 deletions app/api/migrations/0002_alter_fk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 5.1.2 on 2024-12-09 08:58

from django.db import migrations, models
from devices.models import Sensor


class Migration(migrations.Migration):

dependencies = [
('api', '0001_initial'),
('devices', '0004_alter_device_model_remove_device_sensor_bme280_and_more')
]
# TODO: migrate data aswell
operations = [
migrations.RemoveField(
model_name='measurement',
name='sensor',
),
migrations.AddField(
model_name='measurement',
name='sensor',
field=models.ForeignKey(
to='devices.Sensor',
on_delete=models.CASCADE,
),
),
]
46 changes: 46 additions & 0 deletions app/api/migrations/0003_devicelogs_measurementnew_values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generated by Django 5.1.2 on 2024-12-09 11:06

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0002_alter_fk'),
('campaign', '0002_alter_campaign_id_alter_campaign_name_organization_and_more'),
('devices', '0004_alter_device_model_remove_device_sensor_bme280_and_more'),
]

operations = [
migrations.CreateModel(
name='DeviceLogs',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('timestamp', models.DateTimeField()),
('level', models.IntegerField()),
('message', models.TextField()),
('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='devices.device')),
],
),
migrations.CreateModel(
name='MeasurementNew',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('time_received', models.DateTimeField()),
('time_measured', models.DateTimeField()),
('sensor_model', models.IntegerField()),
('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='devices.device')),
('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='campaign.room')),
],
),
migrations.CreateModel(
name='Values',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('dimension', models.IntegerField()),
('value', models.FloatField()),
('measurement', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.measurementnew')),
],
),
]
43 changes: 43 additions & 0 deletions app/api/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db import models
from workshops.models import Participant, Workshop
from devices.models import Device, Sensor
from campaign.models import Room
#from campaign.models import Campaign


Expand Down Expand Up @@ -75,3 +76,45 @@ class AirQualityRecord(models.Model):
lon = models.FloatField(null=True, blank=True)
location_precision = models.FloatField(null=True, blank=True)
mode = models.ForeignKey(MobilityMode, on_delete=models.CASCADE, null=True, blank=True)


class MeasurementNew(models.Model):
"""
Measurement taken by a device in a room.
"""
id = models.IntegerField(primary_key=True)
time_received = models.DateTimeField()
time_measured = models.DateTimeField()
sensor_model = models.IntegerField()
device = models.ForeignKey(Device, on_delete=models.CASCADE)
room = models.ForeignKey(Room, on_delete=models.CASCADE)

def __str__(self):
return f'Measurement {self.id} from Device {self.device.id}'


class Values(models.Model):
"""
Values associated with a measurement.
"""
id = models.IntegerField(primary_key=True)
dimension = models.IntegerField()
value = models.FloatField()
measurement = models.ForeignKey(MeasurementNew, on_delete=models.CASCADE)

def __str__(self):
return f'Value {self.id} for Measurement {self.measurement.id}'


class DeviceLogs(models.Model):
"""
Logs for each device.
"""
id = models.IntegerField(primary_key=True)
device = models.ForeignKey(Device, on_delete=models.CASCADE)
timestamp = models.DateTimeField()
level = models.IntegerField()
message = models.TextField()

def __str__(self):
return f'Log {self.id} for Device {self.device.id}'
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Generated by Django 5.1.2 on 2024-12-09 11:06

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('campaign', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AlterField(
model_name='campaign',
name='id',
field=models.IntegerField(primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='campaign',
name='name',
field=models.CharField(max_length=255),
),
migrations.CreateModel(
name='Organization',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=255)),
('description', models.TextField(blank=True, null=True)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owned_organizations', to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='campaign',
name='organization',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='campaigns', to='campaign.organization'),
preserve_default=False,
),
migrations.CreateModel(
name='Room',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('campaign', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rooms', to='campaign.campaign')),
],
options={
'unique_together': {('campaign', 'name')},
},
),
migrations.CreateModel(
name='UserCampaign',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('campaign', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='campaign.campaign')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'unique_together': {('user', 'campaign')},
},
),
migrations.CreateModel(
name='UserOrganization',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='campaign.organization')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'unique_together': {('user', 'organization')},
},
),
]
87 changes: 70 additions & 17 deletions app/campaign/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
import random

class Campaign(models.Model):
name = models.CharField(max_length=100)
"""
Represents a campaign.
"""
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
Expand All @@ -13,25 +17,74 @@ class Campaign(models.Model):
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='owned_campaigns', # Allows user.owned_campaigns.all() to get all owned workshops
related_name='owned_campaigns',
null=True,
blank=True
)
organization = models.ForeignKey(
'Organization',
on_delete=models.CASCADE,
related_name='campaigns'
)

def __str__(self):
return self.name

def save(self, *args, **kwargs):
if not self.id_token:
# Generate a unique ID for new workshops
self.id_token = self.generate_id_token()
super(Campaign, self).save(*args, **kwargs)

@staticmethod
def generate_id_token():
length = 8
# Ensure the generated ID is unique
while Campaign.objects.filter(id_token=id_token).exists():
# Generate a random string of letters and digits
id_token = ''.join(random.choices(string.ascii_letters + string.digits, k=length))
return id_token


class Room(models.Model):
"""
Represents a room where a campaign takes place.
"""
campaign = models.ForeignKey('Campaign', on_delete=models.CASCADE, related_name='rooms')
name = models.CharField(max_length=255)

class Meta:
unique_together = ('campaign', 'name')

def __str__(self):
return f'{self.name} in {self.campaign}'


class Organization(models.Model):
"""
Represents an organization that owns campaigns and users can be part of.
"""
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='owned_organizations'
)

def __str__(self):
return self.name


class UserOrganization(models.Model):
"""
Represents the many-to-many relationship between users and organizations.
"""
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)

class Meta:
unique_together = ('user', 'organization')

def __str__(self):
return f'{self.user} in {self.organization}'


class UserCampaign(models.Model):
"""
Represents the many-to-many relationship between users and campaigns.
"""
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
campaign = models.ForeignKey('Campaign', on_delete=models.CASCADE)

class Meta:
unique_together = ('user', 'campaign')

def __str__(self):
return f'{self.user} in {self.campaign}'
Loading
Loading