diff -r e00a24b711a0 -r 23416a833ca8 server/python/django2/renkanmanager/models.py --- a/server/python/django2/renkanmanager/models.py Mon Jun 13 14:23:58 2016 +0200 +++ b/server/python/django2/renkanmanager/models.py Wed Jun 15 16:31:43 2016 +0200 @@ -17,29 +17,32 @@ auth_user_model = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') class Workspace(models.Model): - - workspace_guid = models.CharField(max_length=1024, default=uuid.uuid4, unique=True, blank=False, null=False) # typically UUID + + workspace_guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, blank=False, null=False) title = models.CharField(max_length=1024, null=True) creator = models.ForeignKey(auth_user_model, blank=True, null=True, related_name="workspace_creator") creation_date = models.DateTimeField(auto_now_add=True) - + @property def renkan_count(self): - return Renkan.objects.filter(workspace__workspace_guid=self.workspace_guid).count() - + #TODO: check count and related objects + #return Renkan.objects.filter(workspace__workspace_guid=self.workspace_guid).count() + return Renkan.objects.filter(workspace_guid=self.workspace_guid).count() + class Meta: app_label = 'renkanmanager' permissions = ( ('view_workspace', 'Can view workspace'), ) - + class RenkanManager(models.Manager): - + @transaction.atomic def create_renkan(self, creator, title='', content='', source_revision=None, workspace = None): new_renkan = Renkan() new_renkan.creator = creator + #TODO: !!! new_renkan_workspace_guid is not set on the new renkan ! only on the content ! new_renkan_workspace_guid = "" new_renkan_title = title new_renkan_content = content @@ -64,7 +67,7 @@ new_renkan_content_dict = json.loads(new_renkan.validate_json_content(new_renkan_content)) new_renkan_content_dict["created"] = str(initial_revision.creation_date) new_renkan_content_dict["updated"] = str(initial_revision.modification_date) - else: + else: new_renkan_content_dict = { "id": str(new_renkan.renkan_guid), "title": initial_revision.title, @@ -80,57 +83,68 @@ initial_revision.content = json.dumps(new_renkan_content_dict) initial_revision.save() return new_renkan - + class Renkan(models.Model): - - renkan_guid = models.CharField(max_length=256, default=uuid.uuid4, unique=True, blank=False, null=False) # typically UUID - workspace = models.ForeignKey('Workspace', null=True, blank=True, to_field='workspace_guid') - source_revision = models.ForeignKey('Revision', null=True, blank=True, related_name="renkan_source_revision", to_field='revision_guid', on_delete=models.SET_NULL) + + renkan_guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, blank=False, null=False) + workspace_guid = models.CharField(max_length=256, blank=True, null=True) + current_revision_guid = models.CharField(max_length=256, blank=True, null=True) + source_revision_guid = models.CharField(max_length=256, blank=True, null=True) + creator = models.ForeignKey(auth_user_model, blank=True, null=True, related_name="renkan_creator") creation_date = models.DateTimeField(auto_now_add=True) state = models.IntegerField(default=1) - + objects = RenkanManager() - + @property def revision_count(self): - return Revision.objects.filter(parent_renkan__renkan_guid=self.renkan_guid).count() - + #TODO: check related object count + return Revision.objects.filter(parent_renkan_guid=self.renkan_guid).count() + #return Revision.objects.filter(parent_renkan__renkan_guid=self.renkan_guid).count() + @property def is_copy(self): - return bool(self.source_revision) - + #return bool(self.source_revision) + return bool(self.source_revision_guid) + # Current revision object or None if there is none - @property - def current_revision(self): - return Revision.objects.filter(parent_renkan__renkan_guid=self.renkan_guid).order_by('-creation_date').first() - +# @property +# def current_revision(self): +# return Revision.objects.filter(parent_renkan__renkan_guid=self.renkan_guid).order_by('-creation_date').first() + # Current revision title @property def title(self): - if self.current_revision: - return self.current_revision.title - else: - return '' - + current_revision = Revision.objects.get(revision_guid = self.current_revision_guid) + return current_revision.title + #TODO: not good -> 2 requests + #if self.current_revision: + # return self.current_revision.title + #else: + # return '' + # Current revision content @property def content(self): - if self.current_revision: - return self.current_revision.content - else: - return '' - + #TODO: not good -> 2 requests + current_revision = Revision.objects.get(revision_guid = self.current_revision_guid) + return current_revision.content + #if self.current_revision: + # return self.current_revision.content + #else: + # return '' + def __unicode__(self): return self.renkan_guid - + def __str__(self): return self.renkan_guid - + @transaction.atomic def save_renkan(self, updator, timestamp="", title="", content="", create_new_revision=False): """ - Saves over current revision or saves a new revision entirely. + Saves over current revision or saves a new revision entirely. Timestamp must be the current revision modification_date. """ if (not timestamp) or ((self.current_revision is not None) and dateparse.parse_datetime(timestamp) < self.current_revision.modification_date): @@ -144,33 +158,33 @@ revision_to_update.creator = updator else: revision_to_update = Revision.objects.select_for_update().get(revision_guid=self.current_revision.revision_guid) - + updated_content = self.validate_json_content(content) if content else current_revision.content updated_content_dict = json.loads(updated_content) - + # If title is passed as arg to the method, update the title in the json if title: updated_title = title updated_content_dict["title"] = title # If it is not, we use the one in the json instead else: - updated_title = updated_content_dict["title"] - + updated_title = updated_content_dict["title"] + revision_to_update.modification_date = timezone.now() updated_content_dict["updated"] = str(revision_to_update.modification_date) - updated_content = json.dumps(updated_content_dict) + updated_content = json.dumps(updated_content_dict) revision_to_update.title = updated_title revision_to_update.content = updated_content if dt_timestamp == revision_to_update.modification_date: revision_to_update.modification_date += datetime.resolution revision_to_update.last_updated_by = updator revision_to_update.save() - + def validate_json_content(self, content): """ Checks that the json content is valid (keys and structures), raise a ValidationError if format is wrong or value is wrong (for ids), if a key is missing, autocompletes with the empty default value - + Returns the validated json string """ try: @@ -198,7 +212,7 @@ content_to_validate_dict["views"] = [] if "users" not in content_to_validate_dict: content_to_validate_dict["users"] = [] - + if type(content_to_validate_dict["nodes"]) is not list: raise ValidationError("Provided content has an invalid 'nodes' key: not a list") if type(content_to_validate_dict["edges"]) is not list: @@ -208,43 +222,50 @@ if type(content_to_validate_dict["users"]) is not list: raise ValidationError("Provided content has an invalid 'users' key: not a list") return json.dumps(content_to_validate_dict) - - @transaction.atomic - def delete(self): - """ - Deleting a renkan also deletes every related revision - """ - renkan_revisions = Revision.objects.filter(parent_renkan__renkan_guid = self.renkan_guid) - for child_revision in renkan_revisions: - child_revision.delete() - super(Renkan, self).delete() - + + #TODO: + # @transaction.atomic + # def delete(self): + # """ + # Deleting a renkan also deletes every related revision + # """ + # renkan_revisions = Revision.objects.filter(parent_renkan__renkan_guid = self.renkan_guid) + # for child_revision in renkan_revisions: + # child_revision.delete() + # super(Renkan, self).delete() + class Meta: app_label = 'renkanmanager' permissions = ( ('view_renkan', 'Can view renkan'), ) - + class Revision(models.Model): - - revision_guid = models.CharField(max_length=256, default=uuid.uuid4, unique=True) # typically UUID - parent_renkan = models.ForeignKey('Renkan', null=False, blank=False, to_field='renkan_guid') + + revision_guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, blank=False, null=False) + parent_renkan_guid = models.CharField(max_length=256) + #parent_renkan = models.ForeignKey('Renkan', null=False, blank=False, to_field='renkan_guid') title = models.CharField(max_length=1024, null=True, blank=True) content = models.TextField(blank=True, null=True) creator = models.ForeignKey(auth_user_model, blank=True, null=True, related_name="revision_creator") last_updated_by = models.ForeignKey(auth_user_model, blank=True, null=True, related_name="revision_last_updated_by") creation_date = models.DateTimeField(auto_now_add=True) - modification_date = models.DateTimeField() - + modification_date = models.DateTimeField(auto_now=True) + #modification_date = models.DateTimeField() + @property def is_current_revision(self): + try: + parent_project = Renkan.objects.get(renkan_guid=self.parent_renkan_guid) + except Renkan.DoesNotExist: # SHOULD NOT HAPPEN! + raise Http404 + return parent_project.current_revision_guid == self.revision_guid # No need to check if parent_renkan.current_revision is not None, as it won't be if we're calling from a revision - return self.parent_renkan.current_revision.revision_guid == self.revision_guid - + #return self.parent_renkan.current_revision.revision_guid == self.revision_guid + class Meta: app_label = 'renkanmanager' permissions = ( ('view_revision', 'Can view revision'), - ) - + )