Browse Source

Add created_by field to Project

pull/1644/head
Hironsan 2 years ago
parent
commit
e2a99b1b6b
8 changed files with 49 additions and 46 deletions
  1. 25
      backend/api/migrations/0029_auto_20220119_2333.py
  2. 6
      backend/api/models.py
  3. 3
      backend/api/serializers.py
  4. 2
      backend/api/tests/api/utils.py
  5. 2
      backend/api/tests/test_models.py
  6. 4
      backend/api/views/project.py
  7. 7
      backend/members/apps.py
  8. 46
      backend/members/signals.py

25
backend/api/migrations/0029_auto_20220119_2333.py

@ -0,0 +1,25 @@
# Generated by Django 3.2.11 on 2022-01-19 23:33
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('api', '0028_auto_20220111_0655'),
]
operations = [
migrations.RemoveField(
model_name='project',
name='users',
),
migrations.AddField(
model_name='project',
name='created_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
]

6
backend/api/models.py

@ -33,7 +33,11 @@ class Project(PolymorphicModel):
guideline = models.TextField(default='', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
users = models.ManyToManyField(User, related_name='projects')
created_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
)
project_type = models.CharField(max_length=30, choices=PROJECT_CHOICES)
random_order = models.BooleanField(default=False)
collaborative_annotation = models.BooleanField(default=False)

3
backend/api/serializers.py

@ -159,10 +159,10 @@ class ProjectSerializer(serializers.ModelSerializer):
'name',
'description',
'guideline',
'users',
'project_type',
'updated_at',
'random_order',
'created_by',
'collaborative_annotation',
'single_class_classification',
'is_text_project',
@ -174,7 +174,6 @@ class ProjectSerializer(serializers.ModelSerializer):
)
read_only_fields = (
'updated_at',
'users',
'is_text_project',
'can_define_label',
'can_define_relation',

2
backend/api/tests/api/utils.py

@ -73,8 +73,8 @@ def make_project(
project = mommy.make(
_model=project_model,
project_type=task,
users=users,
collaborative_annotation=collaborative_annotation,
created_by=users[0],
**kwargs
)

2
backend/api/tests/test_models.py

@ -231,7 +231,7 @@ class TestLabelDistribution(TestCase):
mommy.make('Span', example=self.example, start_offset=10, end_offset=15, user=self.user, label=label_b)
distribution = Span.objects.calc_label_distribution(
examples=self.project.item.examples.all(),
users=self.project.item.users.all(),
members=self.project.users,
labels=SpanType.objects.all()
)
expected = {user.username: {label.text: 0 for label in SpanType.objects.all()} for user in self.project.users}

4
backend/api/views/project.py

@ -22,10 +22,10 @@ class ProjectList(generics.ListCreateAPIView):
return super().get_permissions()
def get_queryset(self):
return self.request.user.projects
return Project.objects.filter(role_mappings__user=self.request.user)
def perform_create(self, serializer):
serializer.save(users=[self.request.user])
serializer.save(created_by=self.request.user)
def delete(self, request, *args, **kwargs):
delete_ids = request.data['ids']

7
backend/members/apps.py

@ -1,6 +1,7 @@
import importlib
from django.apps import AppConfig
from django.db.models.signals import post_save
class MembersConfig(AppConfig):
@ -9,3 +10,9 @@ class MembersConfig(AppConfig):
def ready(self):
importlib.import_module('members.signals')
from api.models import Project
from .signals import add_administrator_on_project_creation
# Registering signals with the subclasses of project.
for project in Project.__subclasses__():
post_save.connect(add_administrator_on_project_creation, project)

46
backend/members/signals.py

@ -1,48 +1,16 @@
from django.conf import settings
from django.contrib.auth.models import User
from django.db.models.signals import m2m_changed, post_save, pre_delete
from django.dispatch import receiver
from api.models import Project
from roles.models import Role
from .models import Member
@receiver(post_save, sender=Member)
def add_linked_project(sender, instance, created, **kwargs):
if not created:
return
userInstance = instance.user
projectInstance = instance.project
if userInstance and projectInstance:
user = User.objects.get(pk=userInstance.pk)
project = Project.objects.get(pk=projectInstance.pk)
user.projects.add(project)
user.save()
@receiver(m2m_changed, sender=Project.users.through)
def remove_mapping_on_remove_user_from_project(sender, instance, action, reverse, **kwargs):
# if reverse is True, pk_set is project_ids and instance is user.
# else, pk_set is user_ids and instance is project.
user_ids = kwargs['pk_set']
if action.startswith('post_remove') and not reverse:
Member.objects.filter(user__in=user_ids, project=instance).delete()
elif action.startswith('post_add') and not reverse:
def add_administrator_on_project_creation(sender, instance: Project, created: bool, **kwargs):
# In the case of creating a project.
if created:
admin_role = Role.objects.get(name=settings.ROLE_PROJECT_ADMIN)
Member.objects.bulk_create(
[Member(role=admin_role, project=instance, user_id=user)
for user in user_ids
if not Member.objects.filter(project=instance, user_id=user).exists()]
Member.objects.create(
project=instance,
user=instance.created_by,
role=admin_role,
)
@receiver(pre_delete, sender=Member)
def delete_linked_project(sender, instance, using, **kwargs):
userInstance = instance.user
projectInstance = instance.project
if userInstance and projectInstance:
user = User.objects.get(pk=userInstance.pk)
project = Project.objects.get(pk=projectInstance.pk)
user.projects.remove(project)
user.save()
Loading…
Cancel
Save