You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Bug追踪系统:自动分配、邮件通知及权限控制需求

Django Bug Tracking System: Feature Implementations

Hey there! Let's work through each of your requirements for your Django bug tracking system step by step. I'll share practical, actionable code snippets that you can integrate directly into your project.


1. Auto-Populate Assigned_to When Selecting Project_Name

First, we need a way to store the fixed project-to-leader mapping. Let's create a dedicated Project model to hold this data, then link it to your Bugs model. We'll add frontend logic to auto-fill the assignee when a project is selected.

Step 1: Add the Project Model

Update your models.py to include this model:

from django.db import models

class Project(models.Model):
    name = models.CharField(max_length=100, unique=True)
    lead = models.CharField(max_length=100)  # Stores the assigned person for this project

    def __str__(self):
        return self.name

# Update your existing Bugs model's Project_Name field to use a ForeignKey
class Bugs(models.Model):
    STATUS_CHOICE = (
        ('Work In Progress', 'Work In Progress'),
        ('Incomplete', 'Incomplete'),
        ('Completed', 'Completed')
    )
    # Replace the old CharField with a ForeignKey to Project
    Project_Name = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='bugs')
    Basic_Description = models.CharField(max_length=100)
    Detailed_Description = models.TextField(default='The Description, here.')
    Status = models.CharField(max_length=18, choices=STATUS_CHOICE)
    Assigned_to = models.CharField(max_length=100)
    Reported_by = models.CharField(max_length=50, blank=True, null=True)
    Reporters_Mail_ID = models.CharField(max_length=50, blank=True, null=True)
    Reported_Date = models.DateTimeField(null=True, blank=True)
    Created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
    Updated = models.DateTimeField(auto_now=True, null=True, blank=True)
    Deadline_Date = models.DateTimeField(null=True, blank=True)
    image = models.FileField(null=True, blank=True)

    def __str__(self):
        return f"{self.Project_Name} [{self.Status}] {self.Basic_Description} [{self.Assigned_to}]"

    class Meta:
        verbose_name_plural = "Bugs"

Step 2: Add Admin Logic for Auto-Fill

Create a custom admin form and add JavaScript to handle the auto-population:

# admin.py
from django import forms
from django.contrib import admin
import json
from .models import Bugs, Project

class BugsAdminForm(forms.ModelForm):
    class Meta:
        model = Bugs
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Pass project-lead mappings to the frontend as JSON
        project_lead_map = {p.id: p.lead for p in Project.objects.all()}
        self.fields['Project_Name'].widget.attrs['data-project-leads'] = json.dumps(project_lead_map)

class BugsAdmin(admin.ModelAdmin):
    form = BugsAdminForm

    # Include custom JS for auto-fill
    class Media:
        js = ('admin/js/project_lead_auto_fill.js',)

# Register both models in the admin
admin.site.register(Project)
admin.site.register(Bugs, BugsAdmin)

Step 3: Create the Auto-Fill JavaScript

Create a file static/admin/js/project_lead_auto_fill.js (ensure your static files are configured correctly):

document.addEventListener('DOMContentLoaded', function() {
    const projectSelect = document.getElementById('id_Project_Name');
    const assignedToInput = document.getElementById('id_Assigned_to');
    
    if (!projectSelect || !assignedToInput) return;

    const projectLeadMap = JSON.parse(projectSelect.dataset.projectLeads);

    // Fill assignee on initial load if a project is selected
    if (projectSelect.value) {
        assignedToInput.value = projectLeadMap[projectSelect.value] || '';
    }

    // Update assignee when project selection changes
    projectSelect.addEventListener('change', function() {
        assignedToInput.value = projectLeadMap[this.value] || '';
    });
});

2. Automatic Email Notifications on Bug Edits

We'll use Django's post_save signal to trigger emails when a bug is updated. First, configure your email settings, then set up the signal logic.

Step 1: Configure Email Settings

Update settings.py with your SMTP details:

# settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'your-smtp-host'  # e.g., 'smtp.gmail.com' for Gmail
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-email@example.com'
EMAIL_HOST_PASSWORD = 'your-email-password-or-app-specific-password'
DEFAULT_FROM_EMAIL = 'your-email@example.com'

Step 2: Set Up the Signal Handler

Create a signals.py file in your app to handle email triggers:

# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.core.mail import send_mail
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
import threading
from .models import Bugs

# Thread-local storage to pass the request to the signal
_thread_locals = threading.local()

class RequestMiddleware(MiddlewareMixin):
    def process_request(self, request):
        _thread_locals.request = request

def get_current_request():
    return getattr(_thread_locals, 'request', None)

@receiver(post_save, sender=Bugs)
def send_bug_update_email(sender, instance, created, **kwargs):
    request = get_current_request()
    if not request:
        return  # Skip if no request (e.g., command-line operations)

    current_user = request.user

    # Case 1: Superuser updates the bug (assigns person or changes status)
    if current_user.is_superuser:
        # Only send email if Assigned_to or Status was updated
        updated_fields = kwargs.get('update_fields', set())
        if 'Assigned_to' in updated_fields or 'Status' in updated_fields:
            # Get the assignee's email (adjust this if you use User model for assignees)
            recipient_email = instance.Reporters_Mail_ID
            if not recipient_email:
                # Fallback: Get email from User model if Assigned_to matches username
                recipient_user = User.objects.filter(username=instance.Assigned_to).first()
                recipient_email = recipient_user.email if recipient_user else None

            if recipient_email:
                subject = f"Bug Updated: {instance.Project_Name} - {instance.Basic_Description}"
                message = f"""
                Hello {instance.Assigned_to},

                A bug you're assigned to has been updated:
                - Project: {instance.Project_Name}
                - Bug Summary: {instance.Basic_Description}
                - New Status: {instance.Status}
                - Updated At: {instance.Updated.strftime('%Y-%m-%d %H:%M')}

                You can view full details in the Django Admin.

                Best regards,
                The Bug Tracking Team
                """
                send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [recipient_email])

    # Case 2: Assigned user updates the bug
    else:
        if current_user.username == instance.Assigned_to:
            # Get all superusers' emails
            superuser_emails = [user.email for user in User.objects.filter(is_superuser=True) if user.email]
            if superuser_emails:
                subject = f"Bug Updated by {current_user.username}: {instance.Project_Name} - {instance.Basic_Description}"
                message = f"""
                Hello Admin Team,

                {current_user.username} has updated a bug they're assigned to:
                - Project: {instance.Project_Name}
                - Bug Summary: {instance.Basic_Description}
                - Current Status: {instance.Status}
                - Updated At: {instance.Updated.strftime('%Y-%m-%d %H:%M')}

                You can view full details in the Django Admin.

                Best regards,
                The Bug Tracking Team
                """
                send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, superuser_emails)

Step 3: Register the Signal and Middleware

Update your apps.py to register the signal:

# apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'

    def ready(self):
        import your_app_name.signals  # Import signals to register them

Update settings.py to use your app config and add the middleware:

# settings.py
INSTALLED_APPS = [
    # ... other apps
    'your_app_name.apps.YourAppConfig',
]

MIDDLEWARE = [
    # ... other middleware
    'your_app_name.signals.RequestMiddleware',
]

Step 4: Pass Request to Signal in Admin

Update BugsAdmin in admin.py to store the request in thread-local storage:

# admin.py
class BugsAdmin(admin.ModelAdmin):
    # ... existing code
    def save_model(self, request, obj, form, change):
        # Store request in thread-local for the signal
        _thread_locals.request = request
        super().save_model(request, obj, form, change)

3. Optional: Permission Isolation (Assigned Users See Only Their Bugs)

Restrict regular users to only view and edit bugs assigned to them by modifying the admin's queryset and permissions.

Update BugsAdmin in admin.py:

# admin.py
class BugsAdmin(admin.ModelAdmin):
    # ... existing code
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        # Superusers see all bugs; regular users see only their assigned ones
        if request.user.is_superuser:
            return qs
        return qs.filter(Assigned_to=request.user.username)

    def has_change_permission(self, request, obj=None):
        # Superusers can edit all; regular users can only edit their assigned bugs
        if request.user.is_superuser:
            return True
        if obj:
            return obj.Assigned_to == request.user.username
        return False

    def has_delete_permission(self, request, obj=None):
        # Optional: Restrict delete permission similarly
        if request.user.is_superuser:
            return True
        if obj:
            return obj.Assigned_to == request.user.username
        return False

内容的提问来源于stack exchange,提问作者user9779509

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:57:46