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

Api v2 #158

Merged
merged 37 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
03da53a
Fix spelling on contribution table
manuGil Dec 21, 2022
1494911
Merge pull request #103 from CUSP-Urban-Science-and-Policy/feature/up…
Esthetech Feb 13, 2023
ba22c4a
Revert "Feature/updates gitignore"
Esthetech Feb 13, 2023
45de145
Merge pull request #104 from CUSP-Urban-Science-and-Policy/revert-103…
Esthetech Feb 13, 2023
91d297e
Update README.md
jgves May 16, 2023
2883764
Merge branch 'devel'
manuGil Mar 1, 2024
76d621e
Delete frontend and citizenvoice files
manuGil Mar 1, 2024
d66601a
copy citizenvoice and frontend folders
manuGil Mar 1, 2024
3219557
fix merge of deve branch into main
manuGil Mar 1, 2024
8b03c3e
initial version of OpenAPI specification and documentation for API
manuGil Mar 20, 2024
31b05f9
Refactor serializers and fix issues with LocationSerializer
manuGil Mar 20, 2024
9d96030
update api schema
manuGil Mar 20, 2024
2dd7ffd
fix issue with location-detail url generation. Closes #155
manuGil Mar 27, 2024
5b3a423
Update Location model to LocationCollection
manuGil Mar 27, 2024
fb2b483
Update location endpoint name
manuGil Mar 27, 2024
63c2fcd
Update Answer model to use LocationCollection instead of Location
manuGil Mar 27, 2024
0f5c823
Update LocationSerializer and related serializers
manuGil Mar 27, 2024
05fde0d
Fix bug in login functionality
manuGil Mar 27, 2024
4f15780
Update Location model and add LocationCollection model
manuGil Mar 27, 2024
516805f
Add migrations for location points and questions
manuGil Mar 27, 2024
986b336
regenerate migrations
manuGil Mar 27, 2024
e26e992
rename entity PointLocation to PointFeature
manuGil Mar 27, 2024
c68f2fc
Reorder fields in LocationCollectionSerializer and update serializer …
manuGil Mar 27, 2024
b93c506
Rename PolygonLocation to PolygonFeature
manuGil Mar 27, 2024
98aa62f
Rename LineStringLocation to LineFeature
manuGil Mar 27, 2024
640e5dc
Remove 'geometries' field from MapView model and update MapViewSerial…
manuGil Mar 27, 2024
a0c7eee
Rename locations field to location in Answer model and MapView model
manuGil Mar 27, 2024
cae6a36
Update response model foreign key constraints
manuGil Mar 27, 2024
21d52e9
Fix foreign key field in Answer model
manuGil Mar 27, 2024
59e758c
Refactor serializers in API app
manuGil Mar 27, 2024
fd02c42
Rename interview_uuid field to response_id and alter fields responden…
manuGil Mar 27, 2024
96eff57
Remove TODO comment for JSON validation in MapView model
manuGil Mar 27, 2024
82cc616
Update API version to 2.0.0
manuGil Mar 27, 2024
f104228
Refactor LocationViewSet to include a features endpoint
manuGil Mar 27, 2024
fc44346
Add LocationCollection model and create a new PointFeature
manuGil Mar 27, 2024
c022200
Merge branch 'main' into api-v2
manuGil Mar 27, 2024
9b56cb2
Merge branch 'devel' into api-v2
manuGil Mar 27, 2024
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
19 changes: 10 additions & 9 deletions .github/workflows/django-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
branches:
- devel
- main

push:
branches:
- devel
Expand All @@ -19,14 +19,14 @@ jobs:
services:
postgres:
image: postgis/postgis:14-master
env: # environmental variables required for the job
env: # environmental variables required for the job
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: github_actions
ports:
ports:
- 5432:5432

options: >-
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
Expand All @@ -40,15 +40,15 @@ jobs:
path: ~/.cache/zip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-pip-
- name: Setup python environment
uses: actions/setup-python@v3
with:
python-version: "3.x"
python-version: '3.x'
- name: Install GDAL library
run: |
sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable
sudo apt-get update
sudo add-apt-repository ppa:ubuntugis/ppa -y
sudo apt-get update -y
sudo apt-get install gdal-bin libgdal-dev -y
export CPLUS_INCLUDE_PATH=/usr/include/gdal
export C_INCLUDE_PATH=/usr/include/gdal
Expand All @@ -63,5 +63,6 @@ jobs:
run: |
nohup python citizenvoice/manage.py runserver &
sleep 5
- name: Stop Development Server
- name: Stop Development Server
run: pkill -f runserver

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ sdist/
vue/
node_modules/
package-lock.json
package.json
var/
wheels/
pip-wheel-metadata/
Expand Down
40 changes: 1 addition & 39 deletions README.dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,42 +73,4 @@ python manage.py test
### GitHub

1. Make sure that the GitHub-Zenodo integration is enabled for https://github.com/NLeSC/python-template
1. Go to https://github.com/NLeSC/python-template/releases and click `Draft a new release`

### The REST API and authentication

We are using Django rest knox for authentication. Knox authentication is token based, similar to the TokenAuthentication.
This means some API's are protected and can only be called with a authentication token.
To get an valid authentication token you need to have an account and then login with that account.

Example using postman:
Create a new POST request to `http://127.0.0.1:8000/api/auth/login/` in the body add the next key value pairs in `from-data`:

| key | value |
| -------- | ------------- |
| email | `<you email>` |
| password | `<your pass>` |

As a response you will receive:
```json
{
"expiry": "2023-01-24T11:00:24.545608Z",
"token": "<token>",
"user": {
"id": <id>,
"username": "<name>",
"email": "<email></email>"
}
}
```

Use the token string to fetch authenticated API's:
Create a new GET request in postman to `http://127.0.0.1:8000/api/auth/me`. In the `Headers` add the key value pair:

| key | value |
| ------------- | --------------- |
| Authorization | Token `<token>` |

Make sure your using the same capitals and have a space between `Token` and `<token>`.

Now you should get the authenticated user data.
1. Go to https://github.com/NLeSC/python-template/releases and click `Draft a new release`
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ If you use this software, please cite it as follows:

| [Role](https://credit.niso.org/contributor-roles-defined/) | Author |
|------|--------|
| Conceptulization | Goncalves, J. E., Forgaci, C., Verma, T., & Garcia Alvarez, M. |
| Conceptualization | Goncalves, J. E., Forgaci, C., Verma, T., & Garcia Alvarez, M. |
| Funding acquisition | Goncalves, J. E., Forgaci, C., & Verma, T.|
| Project administration | Goncalves, J. E., Forgaci, C., & Verma, T. |
| Investigation | Ioannou I. |
| Project management | Goncalves, J. E. |
| Research | Goncalves, J. E., Ioannou I., Forgaci, C., & Verma, T. |
| Software | van der Laarse, G., Ijpma, J., Aslan, Y., & Garcia Alvarez, M. |
| Supervision | Garcia Alvarez, M. |

Expand Down
14 changes: 7 additions & 7 deletions citizenvoice/apiapp/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
import django.contrib.auth.models
from django.contrib import auth

from .models import ( Answer, Question, Survey, Response, PointLocation,
PolygonLocation, LineStringLocation, MapView,
Location)
from .models import ( Answer, Question, Survey, Response, PointFeature,
PolygonFeature, LineFeature, MapView,
LocationCollection)

# Register the models in the admin site in order to view, create and edit them from the admin page
admin.site.register(Answer)
admin.site.register(Question)
admin.site.register(Survey)
admin.site.register(Response)
admin.site.register(PointLocation)
admin.site.register(LineStringLocation)
admin.site.register(PolygonLocation)
admin.site.register(PointFeature)
admin.site.register(LineFeature)
admin.site.register(PolygonFeature)
admin.site.register(MapView)
admin.site.register(Location)
admin.site.register(LocationCollection)


# Unregister User and Group fields
Expand Down
86 changes: 40 additions & 46 deletions citizenvoice/apiapp/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0 on 2024-02-29 23:12
# Generated by Django 5.0 on 2024-03-27 09:43

import apiapp.models.mapview
import django.contrib.gis.db.models.fields
Expand All @@ -18,12 +18,11 @@ class Migration(migrations.Migration):

operations = [
migrations.CreateModel(
name='Answer',
name='LocationCollection',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Last edited')),
('body', models.TextField(verbose_name='Answer Body')),
('name', models.CharField(blank=True, max_length=100)),
('descripion', models.CharField(blank=True, max_length=300)),
],
),
migrations.CreateModel(
Expand All @@ -37,66 +36,54 @@ class Migration(migrations.Migration):
],
),
migrations.CreateModel(
name='Question',
name='LineStringLocation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.TextField(verbose_name='Text of the Question')),
('order', models.IntegerField(verbose_name='Order of where question is placed')),
('required', models.BooleanField(default=True, verbose_name='Question must be filled out')),
('question_type', models.CharField(choices=[('text', 'text (multiple line)'), ('short-text', 'short text (one line)'), ('radio', 'radio'), ('select', 'select'), ('select-multiple', 'Select Multiple'), ('select_image', 'Select Image'), ('integer', 'integer'), ('float', 'float'), ('date', 'date')], default='text', max_length=150, verbose_name='Type of question')),
('choices', models.TextField(blank=True, null=True, verbose_name='Choices for answers')),
('is_geospatial', models.BooleanField(default=False, verbose_name='If the question must be answered geospatially or not')),
('map_view', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.mapview')),
('geom', django.contrib.gis.db.models.fields.LineStringField(srid=4326)),
('description', models.CharField(blank=True, max_length=100, null=True)),
('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apiapp.locationcollection')),
],
options={
'verbose_name': 'question',
'verbose_name_plural': 'questions',
'ordering': ('survey', 'order'),
},
),
migrations.CreateModel(
name='PolygonLocation',
name='PointLocation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=100)),
('location', django.contrib.gis.db.models.fields.PolygonField(srid=4326)),
('answer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.answer')),
('question', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.question')),
('geom', django.contrib.gis.db.models.fields.PointField(srid=4326)),
('description', models.CharField(blank=True, max_length=100, null=True)),
('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apiapp.locationcollection')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='PointLocation',
name='PolygonLocation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=100)),
('location', django.contrib.gis.db.models.fields.PointField(srid=4326)),
('answer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.answer')),
('question', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.question')),
('geom', django.contrib.gis.db.models.fields.PolygonField(srid=4326)),
('description', models.CharField(blank=True, max_length=100, null=True)),
('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apiapp.locationcollection')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='LineStringLocation',
name='Question',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=100)),
('location', django.contrib.gis.db.models.fields.LineStringField(srid=4326)),
('answer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.answer')),
('question', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.question')),
('text', models.TextField(verbose_name='Text of the Question')),
('order', models.IntegerField(verbose_name='Order of where question is placed')),
('required', models.BooleanField(default=True, verbose_name='Question must be filled out')),
('question_type', models.CharField(choices=[('text', 'text (multiple line)'), ('short-text', 'short text (one line)'), ('radio', 'radio'), ('select', 'select'), ('select-multiple', 'Select Multiple'), ('select_image', 'Select Image'), ('integer', 'integer'), ('float', 'float'), ('date', 'date')], default='text', max_length=150, verbose_name='Type of question')),
('choices', models.TextField(blank=True, null=True, verbose_name='Choices for answers')),
('is_geospatial', models.BooleanField(default=False, verbose_name='If the question must be answered geospatially or not')),
('map_view', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.mapview')),
],
options={
'abstract': False,
'verbose_name': 'question',
'verbose_name_plural': 'questions',
'ordering': ('survey', 'order'),
},
),
migrations.AddField(
model_name='answer',
model_name='locationcollection',
name='question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apiapp.question'),
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.question'),
),
migrations.CreateModel(
name='Response',
Expand All @@ -107,10 +94,17 @@ class Migration(migrations.Migration):
('respondent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='answer',
name='response',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apiapp.response'),
migrations.CreateModel(
name='Answer',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Last edited')),
('body', models.TextField(blank=True, verbose_name='Answer Body')),
('locations', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.locationcollection')),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apiapp.question')),
('response', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='apiapp.response')),
],
),
migrations.CreateModel(
name='Survey',
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.0 on 2024-03-27 09:58

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('apiapp', '0001_initial'),
]

operations = [
migrations.RemoveField(
model_name='locationcollection',
name='question',
),
]
19 changes: 19 additions & 0 deletions citizenvoice/apiapp/migrations/0003_mapview_location_collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.0 on 2024-03-27 10:08

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


class Migration(migrations.Migration):

dependencies = [
('apiapp', '0002_remove_locationcollection_question'),
]

operations = [
migrations.AddField(
model_name='mapview',
name='location_collection',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='apiapp.locationcollection'),
),
]

This file was deleted.

Loading
Loading