project model create and add contributors
This commit is contained in:
parent
278ea3ed0a
commit
776ba21695
@ -1,6 +1,5 @@
|
|||||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField, ValidationError
|
from rest_framework.serializers import ModelSerializer, SerializerMethodField, ValidationError
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from support.models import Project, Issue, Comment, Contributor
|
|
||||||
from authentication.models import User
|
from authentication.models import User
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,12 +22,8 @@ class UserCreateView(APIView):
|
|||||||
#TODELETE : for testing purpose
|
#TODELETE : for testing purpose
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
user = User.objects.all()
|
user = User.objects.all()
|
||||||
print(request.user)
|
|
||||||
serializer = UserSerializer(user, many=True)
|
serializer = UserSerializer(user, many=True)
|
||||||
print(serializer.data)
|
|
||||||
#if serializer.is_valid():
|
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
#return Response("prout", status=status.HTTP_226_IM_USED)
|
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
"""
|
"""
|
||||||
@ -73,7 +69,6 @@ class UserView(APIView):
|
|||||||
|
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
user = request.user
|
user = request.user
|
||||||
print("coucou", request.data['user'])
|
|
||||||
serializer = UserUpdateSerializer(user, data=request.data)
|
serializer = UserUpdateSerializer(user, data=request.data)
|
||||||
print(serializer.initial_data)
|
print(serializer.initial_data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from support.models import Project, Issue, Comment, Contributor
|
from support.models import Project, Issue, Comment, ProjectContributor
|
||||||
from authentication.models import User
|
from authentication.models import User
|
||||||
|
|
||||||
class AdminUser:
|
class AdminUser:
|
||||||
@ -9,5 +9,5 @@ admin.site.register(User)
|
|||||||
admin.site.register(Project)
|
admin.site.register(Project)
|
||||||
admin.site.register(Issue)
|
admin.site.register(Issue)
|
||||||
admin.site.register(Comment)
|
admin.site.register(Comment)
|
||||||
admin.site.register(Contributor)
|
admin.site.register(ProjectContributor)
|
||||||
|
|
||||||
|
19
softdesk/support/migrations/0004_alter_project_author.py
Normal file
19
softdesk/support/migrations/0004_alter_project_author.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-05-25 19:36
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('support', '0003_rename_contributor_contributor_user'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='project',
|
||||||
|
name='author',
|
||||||
|
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='author', to='support.contributor'),
|
||||||
|
),
|
||||||
|
]
|
19
softdesk/support/migrations/0005_alter_project_author.py
Normal file
19
softdesk/support/migrations/0005_alter_project_author.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-05-25 19:37
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('support', '0004_alter_project_author'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='project',
|
||||||
|
name='author',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='author', to='support.contributor'),
|
||||||
|
),
|
||||||
|
]
|
19
softdesk/support/migrations/0006_alter_project_author.py
Normal file
19
softdesk/support/migrations/0006_alter_project_author.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-05-25 19:37
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('support', '0005_alter_project_author'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='project',
|
||||||
|
name='author',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='author', to='support.contributor'),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-05-25 19:49
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('support', '0006_alter_project_author'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='contributor',
|
||||||
|
name='active',
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='project',
|
||||||
|
name='author',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='author', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-05-25 19:52
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('support', '0007_contributor_active_alter_project_author'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='contributor',
|
||||||
|
old_name='user',
|
||||||
|
new_name='contributor_user',
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-05-26 05:26
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('support', '0008_rename_user_contributor_contributor_user'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='contributor',
|
||||||
|
old_name='contributor_user',
|
||||||
|
new_name='username',
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,52 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2025-05-26 05:53
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('support', '0009_rename_contributor_user_contributor_username'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='comment',
|
||||||
|
name='author',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='comment_author', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='issue',
|
||||||
|
name='author',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='issue_author', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='project',
|
||||||
|
name='author',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='project_author', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ProjectContributor',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('active', models.BooleanField(default=True)),
|
||||||
|
('data', models.CharField(blank=True, max_length=255)),
|
||||||
|
('contributor', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL)),
|
||||||
|
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project', to='support.project')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'unique_together': {('contributor', 'project')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='project',
|
||||||
|
name='contributors',
|
||||||
|
field=models.ManyToManyField(related_name='contribution', through='support.ProjectContributor', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='Contributor',
|
||||||
|
),
|
||||||
|
]
|
@ -16,23 +16,31 @@ class Project(models.Model):
|
|||||||
type = models.CharField(choices=Type.choices, max_length=10)
|
type = models.CharField(choices=Type.choices, max_length=10)
|
||||||
active = models.BooleanField(default=True)
|
active = models.BooleanField(default=True)
|
||||||
description = models.CharField(max_length=4000)
|
description = models.CharField(max_length=4000)
|
||||||
author = models.ForeignKey('Contributor',
|
author = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.DO_NOTHING,
|
on_delete=models.DO_NOTHING,
|
||||||
related_name='author')
|
related_name='project_author', null=True)
|
||||||
|
|
||||||
contributors = models.ManyToManyField(settings.AUTH_USER_MODEL,
|
contributors = models.ManyToManyField(settings.AUTH_USER_MODEL,
|
||||||
through='Contributor',
|
through='ProjectContributor',
|
||||||
related_name='contribution')
|
related_name='contribution')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.title
|
||||||
|
|
||||||
class Contributor(models.Model):
|
class ProjectContributor(models.Model):
|
||||||
user = models.ForeignKey(settings.AUTH_USER_MODEL,
|
contributor = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||||
on_delete=models.DO_NOTHING)
|
on_delete=models.DO_NOTHING)
|
||||||
|
active = models.BooleanField(default=True)
|
||||||
project = models.ForeignKey('Project',
|
project = models.ForeignKey('Project',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='project')
|
related_name='project')
|
||||||
data = models.CharField(max_length=255, blank=True)
|
data = models.CharField(max_length=255, blank=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = ('contributor', 'project')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.contributor.username
|
||||||
|
|
||||||
class Issue(models.Model):
|
class Issue(models.Model):
|
||||||
|
|
||||||
@ -57,21 +65,24 @@ class Issue(models.Model):
|
|||||||
title = models.CharField(max_length=255, verbose_name='title')
|
title = models.CharField(max_length=255, verbose_name='title')
|
||||||
date_created = models.DateTimeField(auto_now_add=True)
|
date_created = models.DateTimeField(auto_now_add=True)
|
||||||
description = models.TextField()
|
description = models.TextField()
|
||||||
|
status = models.CharField(Status.choices, max_length=15)
|
||||||
|
priority = models.CharField(Priority.choices, max_length=15)
|
||||||
|
tag = models.CharField(Tag.choices, max_length=15)
|
||||||
project = models.ForeignKey(Project,
|
project = models.ForeignKey(Project,
|
||||||
null=True,
|
null=True,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
blank=True)
|
blank=True)
|
||||||
status = models.CharField(Status.choices, max_length=15)
|
author = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||||
priority = models.CharField(Priority.choices, max_length=15)
|
on_delete=models.DO_NOTHING,
|
||||||
tag = models.CharField(Tag.choices, max_length=15)
|
related_name='issue_author', null=True)
|
||||||
|
|
||||||
author = models.ForeignKey('Contributor', on_delete=models.DO_NOTHING)
|
|
||||||
|
|
||||||
|
|
||||||
class Comment(models.Model):
|
class Comment(models.Model):
|
||||||
title = models.CharField(max_length=255)
|
title = models.CharField(max_length=255)
|
||||||
date_created = models.DateTimeField(auto_now_add=True)
|
date_created = models.DateTimeField(auto_now_add=True)
|
||||||
description = models.CharField(max_length=4000)
|
description = models.CharField(max_length=4000)
|
||||||
author = models.ForeignKey('Contributor', on_delete=models.DO_NOTHING)
|
|
||||||
issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
|
issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
|
||||||
|
author = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||||
|
on_delete=models.DO_NOTHING,
|
||||||
|
related_name='comment_author', null=True)
|
||||||
|
|
||||||
|
9
softdesk/support/permissions.py
Normal file
9
softdesk/support/permissions.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from rest_framework.permissions import BasePermission
|
||||||
|
|
||||||
|
|
||||||
|
class IsAuthor(BasePermission):
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, project):
|
||||||
|
return bool(request.user
|
||||||
|
and request.user.is_authenticated
|
||||||
|
and request.user==project.author)
|
@ -1,17 +1,36 @@
|
|||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import (ModelSerializer,
|
||||||
from support.models import Project, Contributor, Issue, Comment
|
StringRelatedField,
|
||||||
|
SlugRelatedField)
|
||||||
|
from support.models import Project, ProjectContributor, Issue, Comment
|
||||||
|
|
||||||
|
|
||||||
|
class ContributorSerializer(ModelSerializer):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ProjectContributor
|
||||||
|
fields = ['contributor', 'project', 'data']
|
||||||
|
|
||||||
|
|
||||||
class ProjectSerializer(ModelSerializer):
|
class ProjectSerializer(ModelSerializer):
|
||||||
|
|
||||||
|
contributors = SlugRelatedField(many=True,
|
||||||
|
read_only='True',
|
||||||
|
slug_field='username')
|
||||||
|
author = StringRelatedField(many=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Project
|
model = Project
|
||||||
fields = ['title', 'date_created', 'type', 'description', 'author',
|
fields = ['id', 'title', 'date_created', 'type', 'description', 'author',
|
||||||
'contributors']
|
'contributors']
|
||||||
|
|
||||||
|
class ProjectDetailSerializer(ModelSerializer):
|
||||||
|
pass
|
||||||
|
|
||||||
class ContributorSerialier(ModelSerializer):
|
class IssueSerializer(ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Contributor
|
model = Issue
|
||||||
Fields = ['']
|
fields = ['title', 'date_created', 'priority', 'tag', 'status', 'author']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,11 +1,50 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from rest_framework.serializers import raise_errors_on_nested_writes
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
from support.models import Project, Contributor, Issue, Comment
|
from support.models import Project, ProjectContributor, Issue, Comment
|
||||||
from support.serializers import ProjectSerializer
|
from authentication.models import User
|
||||||
|
from support.serializers import ProjectSerializer, ContributorSerializer
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.permissions import (IsAuthenticated,
|
||||||
|
IsAuthenticatedOrReadOnly)
|
||||||
|
from support.permissions import IsAuthor
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
|
||||||
|
|
||||||
class ProjectViewSet(ModelViewSet):
|
class ProjectViewSet(ModelViewSet):
|
||||||
serializer_class = ProjectSerializer
|
permission_classes=[IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
def get_queryset(self):
|
serializer_class = ProjectSerializer
|
||||||
return Project.objects.all()
|
queryset = Project.objects.filter(active=True)
|
||||||
|
|
||||||
|
def perform_create(self, serializer):
|
||||||
|
"""set authenticated user as author and contributor on creation"""
|
||||||
|
test = serializer.save(author=self.request.user)
|
||||||
|
data = {'contributor': self.request.user.id, 'project': test.id}
|
||||||
|
contributor_serializer = ContributorSerializer(data=data)
|
||||||
|
if contributor_serializer.is_valid():
|
||||||
|
contributor_serializer.save()
|
||||||
|
|
||||||
|
@action(detail=True, methods=['patch'],
|
||||||
|
permission_classes=[IsAuthor],
|
||||||
|
basename='add_contributor')
|
||||||
|
def add_contributor(self, request, pk):
|
||||||
|
"""Create the user/project contributor's relation"""
|
||||||
|
if 'contributor' in request.data:
|
||||||
|
contributor = User.objects.get(username=request.data['contributor'])
|
||||||
|
data = {'contributor': contributor.id, 'project': pk}
|
||||||
|
serializer = ContributorSerializer(data=data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response(f"User {contributor} added",
|
||||||
|
status=status.HTTP_202_ACCEPTED)
|
||||||
|
return Response("This user is already contributing",
|
||||||
|
status=status.HTTP_226_IM_USED)
|
||||||
|
return Response(f"Key error;`contributor` is expected, "
|
||||||
|
f"not `{list(request.data)[0]}`",
|
||||||
|
status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
class IssueViewSet(ModelViewSet):
|
||||||
|
serializer =
|
Loading…
x
Reference in New Issue
Block a user