project model create and add contributors

This commit is contained in:
yann 2025-05-26 20:08:34 +02:00
parent 278ea3ed0a
commit 776ba21695
14 changed files with 273 additions and 30 deletions

View File

@ -1,6 +1,5 @@
from rest_framework.serializers import ModelSerializer, SerializerMethodField, ValidationError
from rest_framework import serializers
from support.models import Project, Issue, Comment, Contributor
from authentication.models import User

View File

@ -22,12 +22,8 @@ class UserCreateView(APIView):
#TODELETE : for testing purpose
def get(self, request, *args, **kwargs):
user = User.objects.all()
print(request.user)
serializer = UserSerializer(user, many=True)
print(serializer.data)
#if serializer.is_valid():
return Response(serializer.data)
#return Response("prout", status=status.HTTP_226_IM_USED)
def post(self, request):
"""
@ -73,7 +69,6 @@ class UserView(APIView):
def put(self, request):
user = request.user
print("coucou", request.data['user'])
serializer = UserUpdateSerializer(user, data=request.data)
print(serializer.initial_data)
if serializer.is_valid():

View File

@ -1,5 +1,5 @@
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
class AdminUser:
@ -9,5 +9,5 @@ admin.site.register(User)
admin.site.register(Project)
admin.site.register(Issue)
admin.site.register(Comment)
admin.site.register(Contributor)
admin.site.register(ProjectContributor)

View 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'),
),
]

View 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'),
),
]

View 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'),
),
]

View File

@ -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),
),
]

View File

@ -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',
),
]

View File

@ -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',
),
]

View File

@ -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',
),
]

View File

@ -16,23 +16,31 @@ class Project(models.Model):
type = models.CharField(choices=Type.choices, max_length=10)
active = models.BooleanField(default=True)
description = models.CharField(max_length=4000)
author = models.ForeignKey('Contributor',
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.DO_NOTHING,
related_name='author')
related_name='project_author', null=True)
contributors = models.ManyToManyField(settings.AUTH_USER_MODEL,
through='Contributor',
through='ProjectContributor',
related_name='contribution')
def __str__(self):
return self.title
class Contributor(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
class ProjectContributor(models.Model):
contributor = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.DO_NOTHING)
active = models.BooleanField(default=True)
project = models.ForeignKey('Project',
on_delete=models.CASCADE,
related_name='project')
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):
@ -57,21 +65,24 @@ class Issue(models.Model):
title = models.CharField(max_length=255, verbose_name='title')
date_created = models.DateTimeField(auto_now_add=True)
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,
null=True,
on_delete=models.CASCADE,
blank=True)
status = models.CharField(Status.choices, max_length=15)
priority = models.CharField(Priority.choices, max_length=15)
tag = models.CharField(Tag.choices, max_length=15)
author = models.ForeignKey('Contributor', on_delete=models.DO_NOTHING)
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.DO_NOTHING,
related_name='issue_author', null=True)
class Comment(models.Model):
title = models.CharField(max_length=255)
date_created = models.DateTimeField(auto_now_add=True)
description = models.CharField(max_length=4000)
author = models.ForeignKey('Contributor', on_delete=models.DO_NOTHING)
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)

View 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)

View File

@ -1,17 +1,36 @@
from rest_framework.serializers import ModelSerializer
from support.models import Project, Contributor, Issue, Comment
from rest_framework.serializers import (ModelSerializer,
StringRelatedField,
SlugRelatedField)
from support.models import Project, ProjectContributor, Issue, Comment
class ContributorSerializer(ModelSerializer):
class Meta:
model = ProjectContributor
fields = ['contributor', 'project', 'data']
class ProjectSerializer(ModelSerializer):
contributors = SlugRelatedField(many=True,
read_only='True',
slug_field='username')
author = StringRelatedField(many=False)
class Meta:
model = Project
fields = ['title', 'date_created', 'type', 'description', 'author',
fields = ['id', 'title', 'date_created', 'type', 'description', 'author',
'contributors']
class ProjectDetailSerializer(ModelSerializer):
pass
class ContributorSerialier(ModelSerializer):
class IssueSerializer(ModelSerializer):
class Meta:
model = Contributor
Fields = ['']
model = Issue
fields = ['title', 'date_created', 'priority', 'tag', 'status', 'author']

View File

@ -1,11 +1,50 @@
from django.shortcuts import render
from rest_framework.serializers import raise_errors_on_nested_writes
from rest_framework.viewsets import ModelViewSet
from support.models import Project, Contributor, Issue, Comment
from support.serializers import ProjectSerializer
from support.models import Project, ProjectContributor, Issue, Comment
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):
serializer_class = ProjectSerializer
permission_classes=[IsAuthenticatedOrReadOnly]
def get_queryset(self):
return Project.objects.all()
serializer_class = ProjectSerializer
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 =