mirror of
https://github.com/lemeow125/StudE-Backend.git
synced 2024-11-17 06:19:24 +08:00
Removed associative entity and fixed relationship between student status and study group
This commit is contained in:
parent
771300f933
commit
7dc80caee7
23 changed files with 266 additions and 253 deletions
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
import accounts.models
|
import accounts.models
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
|
@ -14,8 +14,8 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('semesters', '0001_initial'),
|
('semesters', '0001_initial'),
|
||||||
('courses', '0001_initial'),
|
|
||||||
('auth', '0012_alter_user_first_name_max_length'),
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
|
('courses', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
@ -9,9 +9,9 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('accounts', '0001_initial'),
|
|
||||||
('year_levels', '0001_initial'),
|
('year_levels', '0001_initial'),
|
||||||
('subjects', '0001_initial'),
|
('subjects', '0001_initial'),
|
||||||
|
('accounts', '0001_initial'),
|
||||||
('auth', '0012_alter_user_first_name_max_length'),
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
import django.contrib.gis.db.models.fields
|
import django.contrib.gis.db.models.fields
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
255
stude/schema.yml
255
stude/schema.yml
|
@ -547,9 +547,9 @@ paths:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Landmark'
|
$ref: '#/components/schemas/Landmark'
|
||||||
description: ''
|
description: ''
|
||||||
/api/v1/messages/group_messages/:
|
/api/v1/messages/:
|
||||||
get:
|
get:
|
||||||
operationId: api_v1_messages_group_messages_list
|
operationId: api_v1_messages_list
|
||||||
tags:
|
tags:
|
||||||
- api
|
- api
|
||||||
security:
|
security:
|
||||||
|
@ -564,7 +564,7 @@ paths:
|
||||||
$ref: '#/components/schemas/Message'
|
$ref: '#/components/schemas/Message'
|
||||||
description: ''
|
description: ''
|
||||||
post:
|
post:
|
||||||
operationId: api_v1_messages_group_messages_create
|
operationId: api_v1_messages_create
|
||||||
tags:
|
tags:
|
||||||
- api
|
- api
|
||||||
requestBody:
|
requestBody:
|
||||||
|
@ -588,14 +588,15 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Message'
|
$ref: '#/components/schemas/Message'
|
||||||
description: ''
|
description: ''
|
||||||
/api/v1/messages/group_messages/{id}/:
|
/api/v1/messages/{id}/:
|
||||||
get:
|
get:
|
||||||
operationId: api_v1_messages_group_messages_retrieve
|
operationId: api_v1_messages_retrieve
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: id
|
name: id
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: integer
|
||||||
|
description: A unique integer value identifying this message.
|
||||||
required: true
|
required: true
|
||||||
tags:
|
tags:
|
||||||
- api
|
- api
|
||||||
|
@ -625,6 +626,48 @@ paths:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Semester'
|
$ref: '#/components/schemas/Semester'
|
||||||
description: ''
|
description: ''
|
||||||
|
/api/v1/student_status/filter/near_current_location/:
|
||||||
|
post:
|
||||||
|
operationId: api_v1_student_status_filter_near_current_location_create
|
||||||
|
tags:
|
||||||
|
- api
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudentStatusLocation'
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudentStatusLocation'
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudentStatusLocation'
|
||||||
|
required: true
|
||||||
|
security:
|
||||||
|
- jwtAuth: []
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudentStatusLocation'
|
||||||
|
description: ''
|
||||||
|
/api/v1/student_status/filter/near_student_status:
|
||||||
|
get:
|
||||||
|
operationId: api_v1_student_status_filter_near_student_status_list
|
||||||
|
tags:
|
||||||
|
- api
|
||||||
|
security:
|
||||||
|
- jwtAuth: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/StudentStatusLocation'
|
||||||
|
description: ''
|
||||||
/api/v1/student_status/list/:
|
/api/v1/student_status/list/:
|
||||||
get:
|
get:
|
||||||
operationId: api_v1_student_status_list_list
|
operationId: api_v1_student_status_list_list
|
||||||
|
@ -720,14 +763,96 @@ paths:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/StudyGroup'
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
description: ''
|
description: ''
|
||||||
/api/v1/study_groups/membership/:
|
post:
|
||||||
get:
|
operationId: api_v1_study_groups_create
|
||||||
operationId: api_v1_study_groups_membership_list
|
tags:
|
||||||
|
- api
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
required: true
|
||||||
|
security:
|
||||||
|
- jwtAuth: []
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
description: ''
|
||||||
|
put:
|
||||||
|
operationId: api_v1_study_groups_update
|
||||||
|
tags:
|
||||||
|
- api
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
required: true
|
||||||
|
security:
|
||||||
|
- jwtAuth: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
description: ''
|
||||||
|
patch:
|
||||||
|
operationId: api_v1_study_groups_partial_update
|
||||||
|
tags:
|
||||||
|
- api
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/PatchedStudyGroup'
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/PatchedStudyGroup'
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/PatchedStudyGroup'
|
||||||
|
security:
|
||||||
|
- jwtAuth: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/StudyGroup'
|
||||||
|
description: ''
|
||||||
|
delete:
|
||||||
|
operationId: api_v1_study_groups_destroy
|
||||||
|
tags:
|
||||||
|
- api
|
||||||
|
security:
|
||||||
|
- jwtAuth: []
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: No response body
|
||||||
|
/api/v1/study_groups/near/:
|
||||||
|
get:
|
||||||
|
operationId: api_v1_study_groups_near_list
|
||||||
tags:
|
tags:
|
||||||
- api
|
- api
|
||||||
security:
|
security:
|
||||||
- jwtAuth: []
|
- jwtAuth: []
|
||||||
- {}
|
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
content:
|
content:
|
||||||
|
@ -751,7 +876,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Subject'
|
$ref: '#/components/schemas/SubjectInstance'
|
||||||
description: ''
|
description: ''
|
||||||
/api/v1/subjects/{course_slug}:
|
/api/v1/subjects/{course_slug}:
|
||||||
get:
|
get:
|
||||||
|
@ -774,7 +899,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Subject'
|
$ref: '#/components/schemas/SubjectInstance'
|
||||||
description: ''
|
description: ''
|
||||||
/api/v1/subjects/{course_slug}/{year_slug}/{semester_slug}:
|
/api/v1/subjects/{course_slug}/{year_slug}/{semester_slug}:
|
||||||
get:
|
get:
|
||||||
|
@ -807,7 +932,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Subject'
|
$ref: '#/components/schemas/SubjectInstance'
|
||||||
description: ''
|
description: ''
|
||||||
/api/v1/subjects/all:
|
/api/v1/subjects/all:
|
||||||
get:
|
get:
|
||||||
|
@ -824,7 +949,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/Subject'
|
$ref: '#/components/schemas/SubjectInstance'
|
||||||
description: ''
|
description: ''
|
||||||
/api/v1/year_levels/:
|
/api/v1/year_levels/:
|
||||||
get:
|
get:
|
||||||
|
@ -886,8 +1011,7 @@ components:
|
||||||
title: Email address
|
title: Email address
|
||||||
maxLength: 254
|
maxLength: 254
|
||||||
student_id_number:
|
student_id_number:
|
||||||
type: string
|
type: integer
|
||||||
maxLength: 16
|
|
||||||
year_level:
|
year_level:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
@ -913,7 +1037,6 @@ components:
|
||||||
avatar:
|
avatar:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: uri
|
||||||
nullable: true
|
|
||||||
first_name:
|
first_name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
|
@ -923,6 +1046,7 @@ components:
|
||||||
irregular:
|
irregular:
|
||||||
type: boolean
|
type: boolean
|
||||||
required:
|
required:
|
||||||
|
- avatar
|
||||||
- course_shortname
|
- course_shortname
|
||||||
- first_name
|
- first_name
|
||||||
- last_name
|
- last_name
|
||||||
|
@ -996,8 +1120,7 @@ components:
|
||||||
title: Email address
|
title: Email address
|
||||||
maxLength: 254
|
maxLength: 254
|
||||||
student_id_number:
|
student_id_number:
|
||||||
type: string
|
type: integer
|
||||||
maxLength: 16
|
|
||||||
year_level:
|
year_level:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
@ -1023,7 +1146,6 @@ components:
|
||||||
avatar:
|
avatar:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: uri
|
||||||
nullable: true
|
|
||||||
first_name:
|
first_name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
|
@ -1042,20 +1164,45 @@ components:
|
||||||
type: string
|
type: string
|
||||||
location:
|
location:
|
||||||
type: string
|
type: string
|
||||||
|
timestamp:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
active:
|
||||||
|
type: boolean
|
||||||
|
study_group:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
landmark:
|
landmark:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
PatchedStudyGroup:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
readOnly: true
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
students:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
subject:
|
||||||
|
type: string
|
||||||
|
location:
|
||||||
|
type: string
|
||||||
|
landmark:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
radius:
|
||||||
|
type: number
|
||||||
|
format: double
|
||||||
active:
|
active:
|
||||||
type: boolean
|
type: boolean
|
||||||
timestamp:
|
timestamp:
|
||||||
type: string
|
type: string
|
||||||
format: date
|
format: date
|
||||||
readOnly: true
|
readOnly: true
|
||||||
study_group:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: integer
|
|
||||||
readOnly: true
|
|
||||||
Semester:
|
Semester:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1115,25 +1262,52 @@ components:
|
||||||
type: string
|
type: string
|
||||||
location:
|
location:
|
||||||
type: string
|
type: string
|
||||||
|
timestamp:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
active:
|
||||||
|
type: boolean
|
||||||
|
study_group:
|
||||||
|
type: integer
|
||||||
|
nullable: true
|
||||||
landmark:
|
landmark:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
required:
|
||||||
|
- active
|
||||||
|
- location
|
||||||
|
- subject
|
||||||
|
- timestamp
|
||||||
|
- user
|
||||||
|
StudentStatusLocation:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
user:
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
location:
|
||||||
|
type: string
|
||||||
|
distance:
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
subject:
|
||||||
|
type: string
|
||||||
active:
|
active:
|
||||||
type: boolean
|
type: boolean
|
||||||
timestamp:
|
|
||||||
type: string
|
|
||||||
format: date
|
|
||||||
readOnly: true
|
readOnly: true
|
||||||
study_group:
|
study_group:
|
||||||
type: array
|
type: integer
|
||||||
items:
|
|
||||||
type: integer
|
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
nullable: true
|
||||||
|
landmark:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
required:
|
required:
|
||||||
|
- active
|
||||||
|
- distance
|
||||||
- location
|
- location
|
||||||
- study_group
|
- study_group
|
||||||
- subject
|
- subject
|
||||||
- timestamp
|
|
||||||
- user
|
- user
|
||||||
StudyGroup:
|
StudyGroup:
|
||||||
type: object
|
type: object
|
||||||
|
@ -1141,11 +1315,12 @@ components:
|
||||||
id:
|
id:
|
||||||
type: integer
|
type: integer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
users:
|
name:
|
||||||
|
type: string
|
||||||
|
students:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
|
||||||
subject:
|
subject:
|
||||||
type: string
|
type: string
|
||||||
location:
|
location:
|
||||||
|
@ -1153,9 +1328,9 @@ components:
|
||||||
landmark:
|
landmark:
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
name:
|
radius:
|
||||||
type: string
|
type: number
|
||||||
maxLength: 48
|
format: double
|
||||||
active:
|
active:
|
||||||
type: boolean
|
type: boolean
|
||||||
timestamp:
|
timestamp:
|
||||||
|
@ -1166,9 +1341,11 @@ components:
|
||||||
- id
|
- id
|
||||||
- location
|
- location
|
||||||
- name
|
- name
|
||||||
|
- radius
|
||||||
|
- students
|
||||||
- subject
|
- subject
|
||||||
- timestamp
|
- timestamp
|
||||||
Subject:
|
SubjectInstance:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
|
@ -1176,7 +1353,7 @@ components:
|
||||||
readOnly: true
|
readOnly: true
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 64
|
readOnly: true
|
||||||
code:
|
code:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 16
|
maxLength: 16
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import django.contrib.gis.db.models.fields
|
import django.contrib.gis.db.models.fields
|
||||||
|
@ -11,8 +11,10 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
('accounts', '0001_initial'),
|
||||||
|
('study_groups', '0001_initial'),
|
||||||
('landmarks', '0001_initial'),
|
('landmarks', '0001_initial'),
|
||||||
('accounts', '0002_initial'),
|
('subjects', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
@ -24,6 +26,8 @@ class Migration(migrations.Migration):
|
||||||
('active', models.BooleanField(default=False)),
|
('active', models.BooleanField(default=False)),
|
||||||
('timestamp', models.DateTimeField(auto_now_add=True)),
|
('timestamp', models.DateTimeField(auto_now_add=True)),
|
||||||
('landmark', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='landmarks.landmark')),
|
('landmark', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='landmarks.landmark')),
|
||||||
|
('study_group', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='students', to='study_groups.studygroup')),
|
||||||
|
('subject', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='subjects.subject', to_field='name')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('student_status', '0001_initial'),
|
|
||||||
('study_groups', '0001_initial'),
|
|
||||||
('subjects', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='studentstatus',
|
|
||||||
name='study_group',
|
|
||||||
field=models.ManyToManyField(blank=True, through='study_groups.StudyGroupMembership', to='study_groups.studygroup'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='studentstatus',
|
|
||||||
name='subject',
|
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='subjects.subject'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-05 12:19
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('subjects', '0002_alter_subject_name_alter_subjectinstance_subject'),
|
|
||||||
('student_status', '0002_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='studentstatus',
|
|
||||||
name='subject',
|
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='subjects.subject', to_field='name'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -16,8 +16,8 @@ class StudentStatus(models.Model):
|
||||||
timestamp = models.DateTimeField(auto_now_add=True)
|
timestamp = models.DateTimeField(auto_now_add=True)
|
||||||
landmark = models.ForeignKey(
|
landmark = models.ForeignKey(
|
||||||
'landmarks.Landmark', on_delete=models.SET_NULL, null=True)
|
'landmarks.Landmark', on_delete=models.SET_NULL, null=True)
|
||||||
study_group = models.ManyToManyField(
|
study_group = models.ForeignKey(
|
||||||
'study_groups.StudyGroup', through='study_groups.StudyGroupMembership', blank=True)
|
'study_groups.StudyGroup', on_delete=models.SET_NULL, null=True, related_name='students')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.user.full_name
|
return self.user.full_name
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import StudyGroup, StudyGroupMembership
|
from .models import StudyGroup
|
||||||
from leaflet.admin import LeafletGeoAdmin
|
from leaflet.admin import LeafletGeoAdmin
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(StudyGroup, LeafletGeoAdmin)
|
admin.site.register(StudyGroup, LeafletGeoAdmin)
|
||||||
admin.site.register(StudyGroupMembership)
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
import django.contrib.gis.db.models.fields
|
import django.contrib.gis.db.models.fields
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -10,8 +10,8 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('student_status', '0001_initial'),
|
|
||||||
('subjects', '0001_initial'),
|
('subjects', '0001_initial'),
|
||||||
|
('landmarks', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
@ -23,20 +23,8 @@ class Migration(migrations.Migration):
|
||||||
('location', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)),
|
('location', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)),
|
||||||
('active', models.BooleanField(default=False)),
|
('active', models.BooleanField(default=False)),
|
||||||
('timestamp', models.DateField(auto_now_add=True)),
|
('timestamp', models.DateField(auto_now_add=True)),
|
||||||
|
('landmark', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='landmarks.landmark')),
|
||||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
|
||||||
name='StudyGroupMembership',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('study_group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='study_groups.studygroup')),
|
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='student_status.studentstatus')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='studygroup',
|
|
||||||
name='users',
|
|
||||||
field=models.ManyToManyField(through='study_groups.StudyGroupMembership', to='student_status.studentstatus'),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-24 10:59
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('landmarks', '0001_initial'),
|
|
||||||
('study_groups', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='studygroup',
|
|
||||||
name='landmark',
|
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='landmarks.landmark'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -7,8 +7,6 @@ from django.contrib.gis.geos import Point
|
||||||
|
|
||||||
class StudyGroup(models.Model):
|
class StudyGroup(models.Model):
|
||||||
name = models.CharField(max_length=48)
|
name = models.CharField(max_length=48)
|
||||||
users = models.ManyToManyField(
|
|
||||||
'student_status.StudentStatus', through='StudyGroupMembership')
|
|
||||||
location = gis_models.PointField(blank=True, null=True, srid=4326)
|
location = gis_models.PointField(blank=True, null=True, srid=4326)
|
||||||
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
|
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
|
||||||
active = models.BooleanField(default=False)
|
active = models.BooleanField(default=False)
|
||||||
|
@ -18,13 +16,3 @@ class StudyGroup(models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class StudyGroupMembership(models.Model):
|
|
||||||
user = models.ForeignKey(
|
|
||||||
'student_status.StudentStatus', on_delete=models.CASCADE)
|
|
||||||
study_group = models.ForeignKey(
|
|
||||||
'study_groups.StudyGroup', on_delete=models.CASCADE)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f'StudyGroupMembership: User={self.user}, StudyGroup={self.study_group.name}'
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from .models import StudyGroup, StudyGroupMembership
|
from .models import StudyGroup
|
||||||
from accounts.models import CustomUser
|
from accounts.models import CustomUser
|
||||||
from subjects.models import Subject
|
from subjects.models import Subject
|
||||||
from drf_extra_fields.geo_fields import PointField
|
from drf_extra_fields.geo_fields import PointField
|
||||||
|
@ -15,8 +15,7 @@ class CustomUserKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
||||||
|
|
||||||
class StudyGroupSerializer(serializers.ModelSerializer):
|
class StudyGroupSerializer(serializers.ModelSerializer):
|
||||||
name = serializers.CharField()
|
name = serializers.CharField()
|
||||||
users = CustomUserKeyRelatedField(
|
students = serializers.StringRelatedField(many=True)
|
||||||
queryset=CustomUser.objects.all(), many=True)
|
|
||||||
subject = serializers.SlugRelatedField(
|
subject = serializers.SlugRelatedField(
|
||||||
many=False, slug_field='name', queryset=Subject.objects.all(), required=True, allow_null=False)
|
many=False, slug_field='name', queryset=Subject.objects.all(), required=True, allow_null=False)
|
||||||
location = PointField()
|
location = PointField()
|
||||||
|
@ -42,14 +41,4 @@ class StudyGroupSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = StudyGroup
|
model = StudyGroup
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = ['landmark', 'radius']
|
read_only_fields = ['landmark', 'radius', 'students']
|
||||||
|
|
||||||
|
|
||||||
class StudyGroupMembershipSerializer(serializers.ModelSerializer):
|
|
||||||
user = serializers.CharField(source='accounts.CustomUser', read_only=True)
|
|
||||||
subject = serializers.CharField(
|
|
||||||
source='study_groups.StudyGroup', read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = StudyGroupMembership
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
from .views import StudyGroupListView, StudyGroupListNearView, StudyGroupMembershipViewSet
|
from .views import StudyGroupListView, StudyGroupListNearView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', StudyGroupListView.as_view()),
|
path('', StudyGroupListView.as_view()),
|
||||||
path('near/', StudyGroupListNearView.as_view()),
|
path('near/', StudyGroupListNearView.as_view()),
|
||||||
path('membership/', StudyGroupMembershipViewSet.as_view()),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from rest_framework import generics
|
from rest_framework import generics, mixins
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from .serializers import StudyGroupSerializer
|
from .serializers import StudyGroupSerializer
|
||||||
|
@ -11,6 +11,8 @@ from django.contrib.gis.geos import fromstr
|
||||||
from django.contrib.gis.db.models.functions import Distance
|
from django.contrib.gis.db.models.functions import Distance
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import permissions
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,45 +21,6 @@ class StudyGroupListView(generics.ListCreateAPIView, generics.UpdateAPIView, gen
|
||||||
serializer_class = StudyGroupSerializer
|
serializer_class = StudyGroupSerializer
|
||||||
queryset = StudyGroup.objects.all()
|
queryset = StudyGroup.objects.all()
|
||||||
|
|
||||||
def partial_update(self, instance, request, *args, **kwargs):
|
|
||||||
# Ensure only "users" field is being updated
|
|
||||||
if set(request.data.keys()) != {"users"}:
|
|
||||||
return Response({"detail": "Only the 'users' field can be updated."}, status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
# Get the current list of users
|
|
||||||
instance = self.get_object()
|
|
||||||
current_users = set(instance.users.values_list('id', flat=True))
|
|
||||||
|
|
||||||
# Get the new list of users from the request
|
|
||||||
new_users = set(request.data['users'])
|
|
||||||
|
|
||||||
# Check if the only difference between the two sets is the current user
|
|
||||||
diff = current_users.symmetric_difference(new_users)
|
|
||||||
if len(diff) > 1 or (len(diff) == 1 and request.user.id not in diff):
|
|
||||||
return Response({"detail": "You can only add or remove yourself from the study group."}, status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
# Delete the study group if there are no users left
|
|
||||||
instance = self.get_object()
|
|
||||||
if not instance.users.exists():
|
|
||||||
instance.delete()
|
|
||||||
|
|
||||||
return super().partial_update(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def destroy(self, request, *args, **kwargs):
|
|
||||||
instance = self.get_object()
|
|
||||||
|
|
||||||
# Check if the current user is the creator of the study group
|
|
||||||
# Assuming 'date_joined' is a field in your User model
|
|
||||||
creator = instance.users.all().first()
|
|
||||||
if request.user != creator:
|
|
||||||
return Response({"detail": "Only the creator can delete the study group."}, status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
# Check if the current user is the only one in the study group
|
|
||||||
if instance.users.count() > 1:
|
|
||||||
return Response({"detail": "The study group cannot be deleted if there are other users in it."}, status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
return super().destroy(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
|
|
||||||
|
@ -145,6 +108,7 @@ class StudyGroupListNearView(generics.ListAPIView):
|
||||||
return studygroups
|
return studygroups
|
||||||
|
|
||||||
|
|
||||||
class StudyGroupMembershipViewSet(generics.ListAPIView):
|
class IsOwnerOrReadOnly(permissions.BasePermission):
|
||||||
serializer_class = StudyGroupSerializer
|
def has_object_permission(self, request, view, obj):
|
||||||
queryset = StudyGroup.objects.all()
|
# Check if the requesting user's student status matches the user field
|
||||||
|
return obj.user == request.user.studentstatus
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -3,7 +3,7 @@ from rest_framework import routers
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
router.register(r'group_messages', views.MessageViewSet,
|
router.register(r'', views.MessageViewSet,
|
||||||
basename='group_messages')
|
basename='group_messages')
|
||||||
|
|
||||||
# Wire up our API using automatic URL routing.
|
# Wire up our API using automatic URL routing.
|
||||||
|
|
|
@ -5,7 +5,6 @@ from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
from student_status.models import StudentStatus
|
from student_status.models import StudentStatus
|
||||||
from study_groups.models import StudyGroupMembership
|
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
@ -15,25 +14,29 @@ class MessageViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = MessageSerializer
|
serializer_class = MessageSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
http_method_names = ['get', 'post']
|
http_method_names = ['get', 'post']
|
||||||
|
queryset = Message.objects.all()
|
||||||
def get_object(self):
|
|
||||||
user = self.request.user
|
|
||||||
return Message.objects.get(user=user)
|
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
study_group_id_list = StudyGroupMembership.objects.filter(
|
user_status = StudentStatus.objects.filter(user=user).first()
|
||||||
user=user.id).values_list('study_group', flat=True).first()
|
user_study_group = user_status.study_group
|
||||||
serializer.save(user=user, study_group_id=study_group_id_list)
|
serializer.save(user=user, study_group=user_study_group)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
|
user_status = StudentStatus.objects.filter(user=user).first()
|
||||||
|
user_study_group = user_status.study_group
|
||||||
|
|
||||||
if not user.is_student:
|
if not user.is_student:
|
||||||
raise PermissionDenied(
|
raise PermissionDenied(
|
||||||
"You must be a student to view messages of your current study group"
|
"You must be a student to view messages of your current study group"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not user_study_group:
|
||||||
|
raise PermissionDenied(
|
||||||
|
"You are currently do not have a study group"
|
||||||
|
)
|
||||||
|
|
||||||
# Get student_status id of the current user
|
# Get student_status id of the current user
|
||||||
student_status = StudentStatus.objects.filter(
|
student_status = StudentStatus.objects.filter(
|
||||||
user=user.id
|
user=user.id
|
||||||
|
@ -41,15 +44,9 @@ class MessageViewSet(viewsets.ModelViewSet):
|
||||||
|
|
||||||
print("User ID:", user.id)
|
print("User ID:", user.id)
|
||||||
print("Student_Status ID:", student_status)
|
print("Student_Status ID:", student_status)
|
||||||
|
print("User Study Group:", user_study_group)
|
||||||
# Get the study group id
|
|
||||||
print(StudyGroupMembership.objects.all())
|
|
||||||
study_group_id_list = StudyGroupMembership.objects.filter(
|
|
||||||
user=user.id).values_list('study_group').first()
|
|
||||||
|
|
||||||
print("Study Group List:", study_group_id_list)
|
|
||||||
|
|
||||||
# Now fetch the Messages matching the study group id
|
# Now fetch the Messages matching the study group id
|
||||||
messages = Message.objects.filter(
|
messages = Message.objects.filter(
|
||||||
study_group=study_group_id_list).order_by('-timestamp')
|
study_group=user_study_group).order_by('-timestamp')
|
||||||
return messages
|
return messages
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -12,8 +12,8 @@ class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('year_levels', '0001_initial'),
|
('year_levels', '0001_initial'),
|
||||||
('semesters', '0001_initial'),
|
('semesters', '0001_initial'),
|
||||||
('courses', '0001_initial'),
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('courses', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
@ -21,7 +21,7 @@ class Migration(migrations.Migration):
|
||||||
name='Subject',
|
name='Subject',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(max_length=64)),
|
('name', models.CharField(max_length=64, unique=True)),
|
||||||
('students', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)),
|
('students', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -32,7 +32,7 @@ class Migration(migrations.Migration):
|
||||||
('code', models.CharField(max_length=16)),
|
('code', models.CharField(max_length=16)),
|
||||||
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.course')),
|
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.course')),
|
||||||
('semester', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='semesters.semester')),
|
('semester', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='semesters.semester')),
|
||||||
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')),
|
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name')),
|
||||||
('year_level', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='year_levels.year_level')),
|
('year_level', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='year_levels.year_level')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-05 12:19
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('subjects', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='subject',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(max_length=64, unique=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='subjectinstance',
|
|
||||||
name='subject',
|
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 4.2.3 on 2023-09-03 09:32
|
# Generated by Django 4.2.3 on 2023-09-25 13:07
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue