Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentporte committed Sep 23, 2024
1 parent 11b3a24 commit 08fe318
Show file tree
Hide file tree
Showing 27 changed files with 467 additions and 252 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import sys

from django.contrib.contenttypes.models import ContentType
from django.contrib.redirects.models import Redirect
from django.core.management.base import BaseCommand
from taggit.models import TaggedItem

from lacommunaute.documentation.models import Category, Document, DocumentRating
from lacommunaute.forum.models import Forum, ForumRating
from lacommunaute.forum_conversation.models import Topic
from lacommunaute.forum_upvote.models import UpVote
from lacommunaute.stats.models import DocumentationStat, ForumStat


def create_categories_from_catforums():
transpo_dict = {}
redirections = []

for forum in Forum.objects.filter(type=1, level=0):
category = Category.objects.create(
name=forum.name,
short_description=forum.short_description,
description=forum.description,
image=forum.image,
)
redirections.append(
Redirect(site_id=1, old_path=forum.get_absolute_url(), new_path=category.get_absolute_url())
)
print(f"{category} created")
transpo_dict[forum] = category

Redirect.objects.bulk_create(redirections)

return transpo_dict


def create_document_from_forums(category_transpo_dict):
forum_content_type = ContentType.objects.get_for_model(Forum)
document_content_type = ContentType.objects.get_for_model(Document)
transpo_dict = {}
redirections = []

for forum in Forum.objects.filter(parent__type=1):
document = Document.objects.create(
name=forum.name,
short_description=forum.short_description,
description=forum.description,
image=forum.image,
category=category_transpo_dict[forum.parent],
partner=forum.partner,
certified=forum.certified,
)
UpVote.objects.filter(content_type=forum_content_type, object_id=forum.id).update(
content_type=document_content_type, object_id=document.id
)
TaggedItem.objects.filter(content_type=forum_content_type, object_id=forum.id).update(
content_type=document_content_type, object_id=document.id
)
redirections.append(
Redirect(site_id=1, old_path=forum.get_absolute_url(), new_path=document.get_absolute_url())
)
transpo_dict[forum] = document

Redirect.objects.bulk_create(redirections)

return transpo_dict


def migrate_ratings(document_transpo_dict):
document_ratings = [
DocumentRating(
document=document_transpo_dict[rating.forum],
session_id=rating.session_id,
rating=rating.rating,
user=rating.user,
created_at=rating.created,
updated_at=rating.updated,
)
for rating in ForumRating.objects.all()
]
DocumentRating.objects.bulk_create(document_ratings)
ForumRating.objects.all().delete()


def migrate_topics(document_transpo_dict):
main_forum = Forum.objects.get_main_forum()

for forum, document in document_transpo_dict.items():
topics = Topic.objects.filter(forum=forum)
sys.stdout.write(f"*** {len(topics)} topics to migrate from {forum} ({forum.id}) to {main_forum}\n")

for topic in topics:
topic.document = document
topic.forum = main_forum
topic.save()
forum.save()


def migrate_stats(category_transpo_dict, document_transpo_dict):
category_content_type = ContentType.objects.get_for_model(Category)
document_content_type = ContentType.objects.get_for_model(Document)
documentation_stats = []

for forum, category in category_transpo_dict.items():
forum_stats = ForumStat.objects.filter(forum=forum)
documentation_stats += [
DocumentationStat(
content_type=category_content_type,
object_id=category.id,
date=stat.date,
period=stat.period,
visits=stat.visits,
entry_visits=stat.entry_visits,
time_spent=stat.time_spent,
)
for stat in forum_stats
]

for forum, document in document_transpo_dict.items():
forum_stats = ForumStat.objects.filter(forum=forum)
documentation_stats += [
DocumentationStat(
content_type=document_content_type,
object_id=document.id,
date=stat.date,
period=stat.period,
visits=stat.visits,
entry_visits=stat.entry_visits,
time_spent=stat.time_spent,
)
for stat in forum_stats
]

DocumentationStat.objects.bulk_create(documentation_stats)


def del_forums(category_transpo_dict, document_transpo_dict):
forums_to_delete = list(category_transpo_dict.keys()) + list(document_transpo_dict.keys())
return Forum.objects.filter(pk__in=[forum.pk for forum in forums_to_delete]).delete()


class Command(BaseCommand):
help = "migration des forums de fiches pratiques vers la documentation"

def handle(self, *args, **options):
sys.stdout.write("let's go!\n")

category_transpo_dict = create_categories_from_catforums()
sys.stdout.write("Categories created\n")

document_transpo_dict = create_document_from_forums(category_transpo_dict)
sys.stdout.write("Documents created\n")

migrate_ratings(document_transpo_dict)
sys.stdout.write("Ratings migrated\n")

migrate_topics(document_transpo_dict)
sys.stdout.write("Topics migrated\n")

migrate_stats(category_transpo_dict, document_transpo_dict)
sys.stdout.write("Stats migrated\n")

deleted_forums = del_forums(category_transpo_dict, document_transpo_dict)
sys.stdout.write(f"{deleted_forums} forums deleted\n")

sys.stdout.write("that's all folks!")
sys.stdout.flush()
13 changes: 13 additions & 0 deletions lacommunaute/documentation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ class Meta:
def __str__(self):
return f"{self.name}"

def get_absolute_url(self, with_fqdn=False):
absolute_url = reverse(
"documentation:document_detail",
kwargs={
"category_pk": self.category.pk,
"slug": self.slug,
"pk": self.pk,
},
)
if with_fqdn:
return f"{settings.COMMU_PROTOCOL}://{settings.COMMU_FQDN}{absolute_url}"
return absolute_url


# use AbstractDatedModel after ForumRanting migration
class DocumentRating(models.Model):
Expand Down
4 changes: 4 additions & 0 deletions lacommunaute/documentation/tests/tests_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ def test_slug_is_unique(self, db):
DocumentFactory(for_snapshot=True)
with pytest.raises(IntegrityError):
DocumentFactory(for_snapshot=True)

def test_get_absolute_url(self, db):
document = DocumentFactory()
assert document.get_absolute_url() == f"/documentation/{document.category.pk}/{document.slug}-{document.pk}/"
7 changes: 6 additions & 1 deletion lacommunaute/documentation/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
CategoryDetailView,
CategoryListView,
CategoryUpdateView,
CategoryCreateView,
DocumentDetailView,
)


Expand All @@ -17,4 +17,9 @@
path("<str:slug>-<int:pk>/", CategoryDetailView.as_view(), name="category_detail"),
path("create/", CategoryCreateView.as_view(), name="category_create"),
path("<str:slug>-<int:pk>/update/", CategoryUpdateView.as_view(), name="category_update"),
path(
"<int:category_pk>/<str:slug>-<int:pk>/",
DocumentDetailView.as_view(),
name="document_detail",
),
]
6 changes: 6 additions & 0 deletions lacommunaute/documentation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,9 @@ def get_context_data(self, **kwargs):
context["title"] = f"Mettre à jour la catégorie {self.object.name}"
context["back_url"] = self.object.get_absolute_url()
return context


class DocumentDetailView(DetailView):
model = Document
template_name = "documentation/document_detail.html"
context_object_name = "document"
7 changes: 6 additions & 1 deletion lacommunaute/forum/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@

class ForumAdmin(BaseForumAdmin):
fieldsets = BaseForumAdmin.fieldsets
fieldsets[0][1]["fields"] += ("short_description", "certified", "tags", "partner")
fieldsets[0][1]["fields"] += (
"short_description",
"certified",
"tags",
"partner",
)


@admin.register(ForumRating)
Expand Down
38 changes: 6 additions & 32 deletions lacommunaute/forum/forms.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
from django import forms
from django.conf import settings
from django.forms import CharField, CheckboxSelectMultiple, ModelMultipleChoiceField
from taggit.models import Tag

from lacommunaute.forum.models import Forum
from lacommunaute.partner.models import Partner
from lacommunaute.utils.iframe import wrap_iframe_in_div_tag


Expand All @@ -24,39 +21,16 @@ class ForumForm(forms.ModelForm):
label="Banniere de couverture, format 1200 x 630 pixels recommandé",
widget=forms.FileInput(attrs={"accept": settings.SUPPORTED_IMAGE_FILE_TYPES.keys()}),
)
certified = forms.BooleanField(required=False, label="Certifiée par la communauté de l'inclusion")
partner = forms.ModelChoiceField(
label="Sélectionner un partenaire",
queryset=Partner.objects.all(),
required=False,
)
tags = ModelMultipleChoiceField(
label="Sélectionner un ou plusieurs tags",
queryset=Tag.objects.all(),
widget=CheckboxSelectMultiple,
required=False,
)
new_tags = CharField(required=False, label="Ajouter un tag ou plusieurs tags (séparés par des virgules)")

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.pk:
self.fields["tags"].initial = self.instance.tags.all()

def save(self, commit=True):
forum = super().save(commit=False)
forum.description = wrap_iframe_in_div_tag(self.cleaned_data.get("description"))

if commit:
forum.save()
forum.tags.set(self.cleaned_data["tags"])
(
forum.tags.add(*[tag.strip() for tag in self.cleaned_data["new_tags"].split(",")])
if self.cleaned_data.get("new_tags")
else None
)
return forum

class Meta:
model = Forum
fields = ["name", "short_description", "description", "image", "certified", "partner"]
fields = [
"name",
"short_description",
"description",
"image",
]
15 changes: 7 additions & 8 deletions lacommunaute/forum/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,22 @@ def get_main_forum(self):


class Forum(AbstractForum):
# to be removed after documentation refactor
short_description = models.CharField(
max_length=400, blank=True, null=True, verbose_name="Description courte (SEO)"
)
# to be removed after documentation refactor
image = models.ImageField(
storage=S3Boto3Storage(bucket_name=settings.AWS_STORAGE_BUCKET_NAME, file_overwrite=False),
validators=[validate_image_size],
)
# to be removed after documentation refactor
certified = models.BooleanField(default=False, verbose_name="Certifié par la communauté de l'inclusion")

# to be removed after documentation refactor
upvotes = GenericRelation(UpVote, related_query_name="forum")

# to be removed after documentation refactor
tags = TaggableManager()
# to be removed after documentation refactor
partner = models.ForeignKey(Partner, on_delete=models.CASCADE, null=True, blank=True)

objects = ForumQuerySet().as_manager()
Expand All @@ -55,12 +59,6 @@ def count_unanswered_topics(self):
def upvotes_count(self):
return self.upvotes.count()

@cached_property
def is_in_documentation_area(self):
return (self.type == Forum.FORUM_CAT and self.get_level() == 0) or (
self.get_level() > 0 and self.get_ancestors().first().type == Forum.FORUM_CAT
)

@cached_property
def is_toplevel_discussion_area(self):
return self == Forum.objects.get_main_forum()
Expand All @@ -72,6 +70,7 @@ def get_average_rating(self):
return ForumRating.objects.filter(forum=self).aggregate(models.Avg("rating"))["rating__avg"]


# to be removed after documentation refactor
class ForumRating(DatedModel):
session_id = models.CharField(max_length=40)
forum = models.ForeignKey(Forum, on_delete=models.CASCADE)
Expand Down
Loading

0 comments on commit 08fe318

Please sign in to comment.