Skip to content
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
137 changes: 137 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Development Guide

This document provides detailed information for developers working on DjangoBox.

## Project Structure

```
DjangoBox/
├── DjangoBox/ # Django project settings
│ ├── settings.py # Main settings file
│ ├── urls.py # Root URL configuration
│ └── wsgi.py # WSGI application
├── core/ # Main Django app
│ ├── models.py # Database models (Topic, Feedback)
│ ├── views.py # View functions
│ ├── forms.py # Django forms
│ ├── admin.py # Admin interface configuration
│ ├── urls.py # App URL patterns
│ ├── tests.py # Unit tests
│ └── management/ # Custom management commands
│ └── commands/
│ └── import_feedbacks.py
├── templates/ # HTML templates
│ └── core/
│ └── home.html # Main template
├── static/ # Static files (CSS, JS, images)
│ └── css/
│ └── custom.css # Custom styles
├── data/ # Sample data
│ └── feedbacks.json # Sample feedback data
├── requirements.txt # Python dependencies
└── manage.py # Django management script
```

## Models

### Topic
- `name`: CharField(100) - The topic name
- Used to categorize feedback entries

### Feedback
- `user_name`: CharField(100) - Name of the person giving feedback
- `topic`: ForeignKey to Topic - The topic this feedback relates to
- `content`: MarkdownField - The feedback content (supports markdown)
- `content_rendered`: RenderedMarkdownField - Rendered HTML version
- `created_at`: DateTimeField - When the feedback was created

## Views

### feedback_view
- Handles both GET and POST requests
- GET: Displays the feedback form and paginated feedback list
- POST: Processes form submission (supports AJAX)
- Creates topics automatically if they don't exist

## Forms

### FeedbackForm
- ModelForm based on Feedback model
- Custom `topic_name` field for topic input
- Styled with Tailwind CSS classes
- Supports autocomplete for existing topics

## Management Commands

### import_feedbacks
- Imports feedback data from JSON files
- Usage: `python manage.py import_feedbacks [--file path/to/file.json]`
- Creates topics and feedbacks from JSON data
- Handles duplicate prevention

## Testing

Run tests with:
```bash
python manage.py test
```

Test coverage includes:
- Model creation and validation
- Form validation
- View functionality (GET, POST, AJAX)
- Pagination
- Admin interface

## Static Files

- Custom CSS in `static/css/custom.css`
- Tailwind CSS loaded from CDN
- Responsive design with modern UI
- Custom animations and hover effects

## Admin Interface

Access at `/admin/` with superuser credentials:
- Username: admin
- Password: admin123

Features:
- Topic management with feedback count
- Feedback management with search and filters
- Content preview for long feedbacks
- Date hierarchy for easy navigation

## Development Workflow

1. Make changes to models, views, or templates
2. Run migrations if models changed: `python manage.py makemigrations && python manage.py migrate`
3. Run tests: `python manage.py test`
4. Test manually: `python manage.py runserver`
5. Check admin interface for data management

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Run the test suite
6. Submit a pull request

## Troubleshooting

### Common Issues

1. **Migration errors**: Delete `db.sqlite3` and run `python manage.py migrate`
2. **Static files not loading**: Run `python manage.py collectstatic`
3. **Import errors**: Ensure virtual environment is activated
4. **Form validation errors**: Check that all required fields are provided

### Debug Mode

The project runs in DEBUG mode by default. For production:
1. Set `DEBUG = False` in settings.py
2. Configure `ALLOWED_HOSTS`
3. Set up proper static file serving
4. Use a production database (PostgreSQL recommended)
4 changes: 4 additions & 0 deletions DjangoBox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]

# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
Expand Down
45 changes: 38 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,45 @@ See `CONTRIBUTING.md` for details about how to contribute.

## Features

- Submit feedback entries (stored in a simple data layer)
- View feedback summaries
- Submit feedback entries with markdown support
- View feedback summaries with pagination
- AJAX form submission for better user experience
- Admin interface for managing feedbacks and topics
- Import sample data from JSON files
- Responsive design with modern UI
- Comprehensive test coverage
- Small, focused Django app so contributors can get started quickly

## Quick start (development, Windows PowerShell)
## Quick start (development)

These steps assume you have Python 3.8+ installed. If the repository includes a `requirements.txt` file, prefer installing from it; otherwise install Django and other dependencies manually.
These steps assume you have Python 3.8+ installed.

### Linux/macOS:

1. Create and activate a virtual environment:

```bash
python -m venv .venv
source .venv/bin/activate
```

2. Install dependencies:

```bash
pip install -r requirements.txt
```

3. Prepare the database and run the development server:

```bash
python manage.py migrate
python manage.py import_feedbacks # Import sample data
python manage.py runserver
```

4. Open http://127.0.0.1:8000/ in your browser to view the site.

### Windows PowerShell:

1. Create and activate a virtual environment:

Expand All @@ -26,18 +58,17 @@ python -m venv .venv
.\.venv\Scripts\Activate.ps1
```

2. Install dependencies (if a `requirements.txt` exists):
2. Install dependencies:

```powershell
pip install -r requirements.txt
# or, if no requirements file exists
pip install django
```

3. Prepare the database and run the development server:

```powershell
python manage.py migrate
python manage.py import_feedbacks # Import sample data
python manage.py runserver
```

Expand Down
24 changes: 23 additions & 1 deletion core/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
from django.contrib import admin
from .models import Topic, Feedback

# Register your models here.

@admin.register(Topic)
class TopicAdmin(admin.ModelAdmin):
list_display = ('name', 'feedback_count')
search_fields = ('name',)

def feedback_count(self, obj):
return obj.feedback_set.count()
feedback_count.short_description = 'Number of feedbacks'


@admin.register(Feedback)
class FeedbackAdmin(admin.ModelAdmin):
list_display = ('user_name', 'topic', 'created_at', 'content_preview')
list_filter = ('topic', 'created_at')
search_fields = ('user_name', 'content', 'topic__name')
readonly_fields = ('created_at', 'content_rendered')
date_hierarchy = 'created_at'

def content_preview(self, obj):
return obj.content[:100] + '...' if len(obj.content) > 100 else obj.content
content_preview.short_description = 'Content Preview'
4 changes: 2 additions & 2 deletions core/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from .models import Feedback

class FeedbackForm(forms.ModelForm):
topic = forms.CharField(
topic_name = forms.CharField(
max_length=100,
widget=forms.TextInput(attrs={
'class': 'block w-full px-3 py-2 bg-slate-800 text-white border-blue-700 focus:border-indigo-400 focus:ring-indigo-400 rounded-xl shadow-sm focus:outline-none',
Expand All @@ -14,7 +14,7 @@ class FeedbackForm(forms.ModelForm):

class Meta:
model = Feedback
fields = ['user_name', 'topic', 'content']
fields = ['user_name', 'content']
widgets = {
'user_name': forms.TextInput(attrs={
'class': 'block w-full px-3 py-2 bg-slate-800 text-white border-blue-700 focus:border-indigo-400 focus:ring-indigo-400 rounded-xl shadow-sm focus:outline-none',
Expand Down
74 changes: 74 additions & 0 deletions core/management/commands/import_feedbacks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from django.core.management.base import BaseCommand
from django.utils import timezone
from core.models import Topic, Feedback
import json
import os
from datetime import datetime


class Command(BaseCommand):
help = 'Import feedback data from JSON file'

def add_arguments(self, parser):
parser.add_argument(
'--file',
type=str,
default='data/feedbacks.json',
help='Path to JSON file containing feedback data'
)

def handle(self, *args, **options):
file_path = options['file']

if not os.path.exists(file_path):
self.stdout.write(
self.style.ERROR(f'File {file_path} does not exist')
)
return

try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)

imported_count = 0
for item in data:
# Get or create topic
topic, created = Topic.objects.get_or_create(
name=item['topic']
)

# Parse datetime if it exists
created_at = timezone.now()
if 'created_at' in item:
try:
created_at = datetime.fromisoformat(
item['created_at'].replace('Z', '+00:00')
)
except ValueError:
pass

# Create feedback
feedback, created = Feedback.objects.get_or_create(
user_name=item['user_name'],
topic=topic,
content=item['content'],
defaults={'created_at': created_at}
)

if created:
imported_count += 1

self.stdout.write(
self.style.SUCCESS(
f'Successfully imported {imported_count} feedback entries'
)
)

except json.JSONDecodeError:
self.stdout.write(
self.style.ERROR('Invalid JSON file')
)
except Exception as e:
self.stdout.write(
self.style.ERROR(f'Error importing data: {str(e)}')
)
4 changes: 3 additions & 1 deletion core/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.db import models
import markdownfield.models

# Create your models here.

Expand All @@ -11,7 +12,8 @@ def __str__(self):
class Feedback(models.Model):
user_name = models.CharField(max_length=100)
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
content = models.TextField()
content = markdownfield.models.MarkdownField(rendered_field='content_rendered')
content_rendered = markdownfield.models.RenderedMarkdownField()
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
Expand Down
Loading