-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Partly implements #981: * add models and views for viewing, creating, and updating DataTypes * add views for managing a project's registered DataTypes * handle specified DataTypes in the API for file uploads * some default behavior if DataTypes weren't specified during upload * records DataType edit history * adds public API endpoint for DataTypes * adds public API endpoint for projects Aspects related to sharing permissions are not part of this commit (i.e. requesting and authorizing data sharing according to DataType). Also, the feature at this stage does not enforce DataType in uploaded data, but does introduce a default we plan to use for legacy support.
- Loading branch information
Showing
30 changed files
with
1,283 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
from django import forms | ||
|
||
from .models import DataType | ||
|
||
|
||
class DataTypeForm(forms.ModelForm): | ||
""" | ||
A form for creating and editing DataTypes. | ||
""" | ||
|
||
class Meta: # noqa: D101 | ||
model = DataType | ||
fields = ["name", "parent", "description"] | ||
|
||
def __init__(self, *args, **kwargs): | ||
self.editor = kwargs.pop("editor") | ||
return super().__init__(*args, **kwargs) | ||
|
||
def clean_parent(self): | ||
""" | ||
Verify that the parent is not the object itself nor a descendent. | ||
""" | ||
parent = self.cleaned_data.get("parent") | ||
if not parent: | ||
return parent | ||
if self.instance.id == parent.id: | ||
raise forms.ValidationError( | ||
"A DataType cannot be assigned to be its own parent." | ||
) | ||
elif self.instance in parent.all_parents: | ||
raise forms.ValidationError( | ||
"{0} is not an allowed parent, as it is a descendent of {1}.".format( | ||
parent.name, self.instance.name | ||
) | ||
) | ||
return parent | ||
|
||
def clean_name(self): | ||
""" | ||
Verify that the name is case insensitive unique. | ||
""" | ||
name = self.cleaned_data.get("name") | ||
try: | ||
dt = DataType.objects.get(name__iexact=name) | ||
except DataType.DoesNotExist: | ||
dt = self.instance | ||
if not dt == self.instance: | ||
raise forms.ValidationError( | ||
"Please provide a unique name for this datatype" | ||
) | ||
return name | ||
|
||
def clean(self, *args, **kwargs): | ||
if self.instance: | ||
if not self.instance.editable: | ||
raise forms.ValidationError( | ||
"Not editable: in use by one or more approved projects." | ||
) | ||
self.instance.editor = self.editor | ||
return super().clean(*args, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# Generated by Django 2.2 on 2019-04-12 19:08 | ||
|
||
import django.contrib.postgres.fields.jsonb | ||
import django.core.validators | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("open_humans", "0014_member_password_reset_redirect"), | ||
("data_import", "0018_auto_20190402_1947"), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="DataType", | ||
fields=[ | ||
( | ||
"id", | ||
models.AutoField( | ||
auto_created=True, | ||
primary_key=True, | ||
serialize=False, | ||
verbose_name="ID", | ||
), | ||
), | ||
( | ||
"name", | ||
models.CharField( | ||
max_length=128, | ||
unique=True, | ||
validators=[ | ||
django.core.validators.RegexValidator( | ||
"^[\\w\\-\\s]+$", | ||
"Only alphanumeric characters, space, dash, and underscore are allowed.", | ||
) | ||
], | ||
), | ||
), | ||
("description", models.CharField(max_length=512)), | ||
("created", models.DateTimeField(auto_now_add=True)), | ||
("modified", models.DateTimeField(auto_now=True)), | ||
( | ||
"history", | ||
django.contrib.postgres.fields.jsonb.JSONField(default=dict), | ||
), | ||
( | ||
"last_editor", | ||
models.ForeignKey( | ||
null=True, | ||
on_delete=django.db.models.deletion.SET_NULL, | ||
to="open_humans.Member", | ||
), | ||
), | ||
( | ||
"parent", | ||
models.ForeignKey( | ||
blank=True, | ||
null=True, | ||
on_delete=django.db.models.deletion.PROTECT, | ||
related_name="children", | ||
to="data_import.DataType", | ||
), | ||
), | ||
], | ||
) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.