Skip to content

Commit f5bd66f

Browse files
updated
1 parent c69270a commit f5bd66f

File tree

5 files changed

+309
-0
lines changed

5 files changed

+309
-0
lines changed

BackendSchema.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Rockae Backend Database Schema
2+
3+
## Overview
4+
The backend database is a fully functionaly postgre sql
5+
6+
## Database Schema
7+
8+
### User Table
9+
| Column Name | Data Type | Constraints |
10+
|-------------|-----------|-------------|
11+
| `id` | Integer | Primary Key, Auto-increment |
12+
| `user_id` | CharField | Unique, Format: ADM<pk> or USR<pk> |
13+
| `username` | varchar(255) | Unique, NOT NULL |
14+
| `email` | varchar | Unique, NOT NULL |
15+
| `password` | varchar | NOT NULL |
16+
| `is_verified` | boolean | default: false |
17+
| `is_active` | boolean | default: true |
18+
| `date_joined` | datetime | auto-generated |
19+
20+
### UserProfile Table
21+
| Column Name | Data Type | Constraints |
22+
|-------------|-----------|-------------|
23+
| `id` | Integer | PRIMARY KEY, AUTO_INCREMENT |
24+
| `user` | ForeignKey | REFERENCES User (user_id), UNIQUE |
25+
| `firstname` | varchar | |
26+
| `lastname` | varchar | |
27+
| `phone_number` | varchar | nullable |
28+
| `photo` | file | nullable |
29+
30+
### Quiz Table
31+
| Column Name | Data Type | Constraints |
32+
|-------------|-----------|-------------|
33+
| `id` | int | PRIMARY KEY |
34+
| `quiz_title` | varchar | NOT NULL |
35+
| `description` | text | nullable |
36+
| `user` | int | FOREIGN KEY REFERENCES User (user_id) |
37+
| `create_date` | datetime | auto-generated |
38+
| `number_of_questions` | int | default: 10 |
39+
| `difficulty_level` | varchar | Choices: Easy, Medium, Hard |
40+
| `category` | varchar | NOT NULL |
41+
| `is_public` | boolean | default: false |
42+
| `is_timed` | boolean | default: false |
43+
| `time_limit` | float | nullable |
44+
| `auth_required` | boolean | default: false |
45+
| `has_flash_card` | boolean | default: false |
46+
47+
### Question Table
48+
| Column Name | Data Type | Constraints |
49+
|-------------|-----------|-------------|
50+
| `id` | int | PRIMARY KEY |
51+
| `quiz_id` | int | ForeignKey to Quiz |
52+
| `text` | text | NOT NULL |
53+
54+
### AnswerOption Table
55+
| Column Name | Data Type | Constraints |
56+
|-------------|-----------|-------------|
57+
| `id` | int | PRIMARY KEY |
58+
| `question_id` | int | ForeignKey to Question |
59+
| `label` | varchar(1) | NOT NULL (A, B, C, D, etc.) |
60+
| `text` | text | NOT NULL |
61+
| `is_correct` | boolean | NOT NULL |
62+
63+
### Flashcard Table
64+
| Column Name | Data Type | Constraints |
65+
|-------------|-----------|-------------|
66+
| `id` | int | PRIMARY KEY |
67+
| `title` | varchar | NOT NULL |
68+
| `description` | text | nullable |
69+
| `user_id` | int | ForeignKey to User |
70+
| `quiz_id` | int | One-to-one relationship with Quiz, nullable |
71+
72+
### FlashcardItem Table
73+
| Column Name | Data Type | Constraints |
74+
|-------------|-----------|-------------|
75+
| `id` | int | PRIMARY KEY |
76+
| `flashcard_id` | int | ForeignKey to Flashcard |
77+
| `question` | text | NOT NULL |
78+
| `answer` | text | NOT NULL |
79+
80+
### SubscriptionPlan Table
81+
| Column Name | Data Type | Constraints |
82+
|-------------|-----------|-------------|
83+
| `id` | int | PRIMARY KEY |
84+
| `name` | varchar | UNIQUE, NOT NULL |
85+
| `duration_days` | int | NOT NULL |
86+
| `price` | decimal | NOT NULL |
87+
| `is_active` | boolean | default: true |
88+
89+
### UserSubscription Table
90+
| Column Name | Data Type | Constraints |
91+
|-------------|-----------|-------------|
92+
| `id` | int | PRIMARY KEY |
93+
| `user_id` | int | ForeignKey to User |
94+
| `plan_id` | int | ForeignKey to SubscriptionPlan |
95+
| `start_date` | datetime | auto-generated |
96+
| `end_date` | datetime | calculated from SubscriptionPlan |
97+
98+
## API Endpoints
99+
100+
(Endpoints listed as previously defined)
101+
102+
## Technologies
103+
- **Django**
104+
- **Django REST Framework**
105+
- **JWT Authentication**
106+
- **Pandas (CSV/Excel processing)**
107+
- **DRF Spectacular (API documentation)**
108+
- **Generative AI (Gemini)**
109+
- **Decouple (Environment Variables Management)**
110+
- **Corsheaders (Cross-Origin Resource Sharing)**
111+
112+
## Security Measures
113+
- **JWT Authentication**
114+
- **Custom Permission Classes**
115+
- **Data Validation & Sanitization**
116+
- **Error Handling & Standardized Responses**
117+
- **File Upload Security**
118+
- **FTP Secure Storage**
119+
120+
## Deployment
121+
- Uses FTP storage for handling static and user-uploaded files
122+
- Environment configuration via `python-decouple`
123+
- Ready for deployment to platforms such as Railway, Heroku, or AWS
124+
125+
## Documentation
126+
- Comprehensive API documentation via DRF Spectacular (Swagger/OpenAPI)
127+
128+
## Configuration
129+
- Secure environment variables handling (`SECRET_KEY`, `DATABASE_URL`, SMTP settings, AI keys)
130+
- Database configured for optimized production performance (`dj_database_url`)
131+
- JWT authentication token lifetime configurable
132+
133+
## Future Enhancements
134+
- Real-time analytics
135+
- Enhanced admin interface
136+
- User activity logs
137+
- Expanded subscription and payment options
138+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# community_publicfeeds app models
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Generated by Django 6.0.1 on 2026-01-29
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
initial = True
11+
12+
dependencies = [
13+
('community', '0001_initial'),
14+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='PublicFeed',
20+
fields=[
21+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('message', models.TextField(help_text='Feed message content')),
23+
('allow_replies', models.BooleanField(default=True, help_text='If true, users can reply to this feed. If false, replies are disabled.')),
24+
('created_at', models.DateTimeField(auto_now_add=True)),
25+
('updated_at', models.DateTimeField(auto_now=True)),
26+
('community', models.ForeignKey(help_text='Community that owns this feed item', on_delete=django.db.models.deletion.CASCADE, related_name='public_feeds', to='community.community')),
27+
('parent_feed', models.ForeignKey(blank=True, help_text='Parent feed if this is a reply', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='community_publicfeeds.publicfeed')),
28+
('posted_by', models.ForeignKey(help_text='Community member who posted this on behalf of the community', on_delete=django.db.models.deletion.CASCADE, related_name='public_feed_posts', to=settings.AUTH_USER_MODEL)),
29+
],
30+
options={
31+
'verbose_name': 'Public Feed',
32+
'verbose_name_plural': 'Public Feeds',
33+
'db_table': 'PublicFeeds',
34+
'ordering': ['-created_at'],
35+
},
36+
),
37+
migrations.CreateModel(
38+
name='PublicFeedsAttachment',
39+
fields=[
40+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
41+
('file_url', models.URLField(help_text='URL of the attached file')),
42+
('file_type', models.CharField(choices=[('image', 'Image'), ('video', 'Video')], help_text='Type of attachment (image or video)', max_length=10)),
43+
('created_at', models.DateTimeField(auto_now_add=True)),
44+
('public_feed', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='community_publicfeeds.publicfeed')),
45+
],
46+
options={
47+
'verbose_name': 'Public Feeds Attachment',
48+
'verbose_name_plural': 'Public Feeds Attachments',
49+
'db_table': 'PublicFeedsAttachment',
50+
'ordering': ['created_at'],
51+
},
52+
),
53+
migrations.CreateModel(
54+
name='PublicFeedsLike',
55+
fields=[
56+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
57+
('created_at', models.DateTimeField(auto_now_add=True)),
58+
('public_feed', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='likes', to='community_publicfeeds.publicfeed')),
59+
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='public_feed_likes', to=settings.AUTH_USER_MODEL)),
60+
],
61+
options={
62+
'verbose_name': 'Public Feeds Like',
63+
'verbose_name_plural': 'Public Feeds Likes',
64+
'db_table': 'PublicFeedsLike',
65+
'ordering': ['-created_at'],
66+
'unique_together': {('user', 'public_feed')},
67+
},
68+
),
69+
]

app_models/community_publicfeeds/migrations/__init__.py

Whitespace-only changes.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from django.db import models
2+
from app_models.account.models import User
3+
from app_models.community.models import Community
4+
5+
6+
class PublicFeed(models.Model):
7+
"""
8+
Public feed item posted by a community.
9+
Only communities can post to public feeds; posted_by is the community member who created it.
10+
"""
11+
community = models.ForeignKey(
12+
Community,
13+
on_delete=models.CASCADE,
14+
related_name='public_feeds',
15+
help_text='Community that owns this feed item',
16+
)
17+
posted_by = models.ForeignKey(
18+
User,
19+
on_delete=models.CASCADE,
20+
related_name='public_feed_posts',
21+
help_text='Community member who posted this on behalf of the community',
22+
)
23+
parent_feed = models.ForeignKey(
24+
'self',
25+
on_delete=models.CASCADE,
26+
null=True,
27+
blank=True,
28+
related_name='replies',
29+
help_text='Parent feed if this is a reply',
30+
)
31+
message = models.TextField(help_text='Feed message content')
32+
allow_replies = models.BooleanField(
33+
default=True,
34+
help_text='If true, users can reply to this feed. If false, replies are disabled.',
35+
)
36+
created_at = models.DateTimeField(auto_now_add=True)
37+
updated_at = models.DateTimeField(auto_now=True)
38+
39+
class Meta:
40+
db_table = 'PublicFeeds'
41+
verbose_name = 'Public Feed'
42+
verbose_name_plural = 'Public Feeds'
43+
ordering = ['-created_at']
44+
45+
def __str__(self):
46+
return f"Feed by {self.community.name} (posted by {self.posted_by.email})"
47+
48+
49+
class PublicFeedsAttachment(models.Model):
50+
"""Attachment model for public feed images/videos."""
51+
ATTACHMENT_TYPE_CHOICES = [
52+
('image', 'Image'),
53+
('video', 'Video'),
54+
]
55+
56+
public_feed = models.ForeignKey(
57+
PublicFeed,
58+
on_delete=models.CASCADE,
59+
related_name='attachments',
60+
)
61+
file_url = models.URLField(help_text='URL of the attached file')
62+
file_type = models.CharField(
63+
max_length=10,
64+
choices=ATTACHMENT_TYPE_CHOICES,
65+
help_text='Type of attachment (image or video)',
66+
)
67+
created_at = models.DateTimeField(auto_now_add=True)
68+
69+
class Meta:
70+
db_table = 'PublicFeedsAttachment'
71+
verbose_name = 'Public Feeds Attachment'
72+
verbose_name_plural = 'Public Feeds Attachments'
73+
ordering = ['created_at']
74+
75+
def __str__(self):
76+
return f"{self.file_type} attachment for public feed {self.public_feed.id}"
77+
78+
79+
class PublicFeedsLike(models.Model):
80+
"""Model to track user likes on public feeds."""
81+
user = models.ForeignKey(
82+
User,
83+
on_delete=models.CASCADE,
84+
related_name='public_feed_likes',
85+
)
86+
public_feed = models.ForeignKey(
87+
PublicFeed,
88+
on_delete=models.CASCADE,
89+
related_name='likes',
90+
)
91+
created_at = models.DateTimeField(auto_now_add=True)
92+
93+
class Meta:
94+
db_table = 'PublicFeedsLike'
95+
verbose_name = 'Public Feeds Like'
96+
verbose_name_plural = 'Public Feeds Likes'
97+
unique_together = ['user', 'public_feed']
98+
ordering = ['-created_at']
99+
100+
def __str__(self):
101+
return f"{self.user.email} liked public feed {self.public_feed.id}"

0 commit comments

Comments
 (0)