Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor TripReport model to be part of Trip model (#111) #190

Merged
merged 4 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions app/core/logging.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging

from logger.models import Trip, TripPhoto, TripReport
from logger.models import Trip, TripPhoto
from users.models import CavingUser

ActionLogger = logging.getLogger("user_actions")
Expand Down Expand Up @@ -33,16 +33,6 @@ def log_trip_action(user: CavingUser, trip: Trip, verb: str, extra: str = ""):
_log_action(user, f"{verb} a trip to {trip}{extra}")


def log_tripreport_action(
user: CavingUser, report: TripReport, verb: str, extra: str = ""
):
trip = _format_trip_for_logging(report.trip)
if extra:
extra = f": {extra}"

_log_action(user, f"{verb} a trip report for the trip to {trip}{extra}")


def log_tripphoto_action(
user: CavingUser, photo: TripPhoto, verb: str, extra: str = ""
):
Expand Down
56 changes: 2 additions & 54 deletions app/core/management/commands/make_test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
from logger.factories import TripFactory, TripReportFactory
from logger.models import Trip
from logger.factories import TripFactory
from users.factories import UserFactory

User = get_user_model()
Expand All @@ -32,13 +31,6 @@ def add_arguments(self, parser):
help="Number of trips to generate",
)

parser.add_argument(
"--reports",
type=int,
default=-1,
help="Number of trip reports to generate",
)

parser.add_argument(
"--friends",
type=int,
Expand Down Expand Up @@ -78,9 +70,6 @@ def handle(self, *args, **options):

self.options = options

if options["reports"] < 0:
options["reports"] = options["trips"] // 10

if options["seed"] != 0:
random.seed(options["seed"])
factory.random.reseed_random(options["seed"])
Expand All @@ -94,12 +83,10 @@ def handle(self, *args, **options):

self._generate_friendships(user_pks)
trips = self._generate_trips(user_pks)
reports = self._generate_trip_reports(user_pks)

if options["verbosity"] >= 1:
self.stdout.write(
f"Done! Generated {len(user_pks)} users, {len(trips)} "
f"trips and {len(reports)} reports."
f"Done! Generated {len(user_pks)} users and {len(trips)} trips."
)

def __get_active_users(self, user_pks=None):
Expand All @@ -110,19 +97,6 @@ def __get_active_users(self, user_pks=None):
users = list(User.objects.filter(pk__in=user_pks, is_active=True))
return users

def __find_trip_without_report(self, trips=None):
if trips is None:
trips = list(Trip.objects.all())

trip = None
while trip is None:
trip = random.choice(trips)
if not trip.has_report:
trip = trip
break

return trip

def _generate_users(self):
"""Generate num_users amount of users"""
num_users = self.options["users"]
Expand Down Expand Up @@ -190,32 +164,6 @@ def _add_comments_to_trip(self, trip, users):

return num_comments

def _generate_trip_reports(self, user_pks=None):
"""Generate num_reports amount of trip reports amongst the users specified"""
num_reports = self.options["reports"]
if self.options["verbosity"] >= 1:
self.stdout.write(f"Generating {num_reports} reports...")
users = self.__get_active_users(user_pks)
user_pks = [user.pk for user in users]

reports = []
trips = list(Trip.objects.filter(user__pk__in=user_pks))
for _ in range(num_reports):
trip = self.__find_trip_without_report(trips)
if trip is None:
break

report = TripReportFactory(trip=trip, user=trip.user)
trips.remove(trip)
reports.append(report)

if self.options["verbosity"] >= 2:
self.stdout.write(
f"Created report with PK {report.pk} for user {trip.user.email}."
)

return reports

def _generate_friendships(self, user_pks=None):
"""Generate friendships between users"""
num_friends = self.options["friends"]
Expand Down
43 changes: 9 additions & 34 deletions app/logger/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
from django.contrib import admin
from django.forms import ModelForm
from logger.forms import DistanceUnitFormMixin
from tinymce.models import HTMLField
from tinymce.widgets import TinyMCE
from unfold.admin import ModelAdmin, TabularInline
from unfold.widgets import UnfoldAdminTextInputWidget

from .models import Trip, TripPhoto, TripReport
from .models import Trip, TripPhoto


class TripAdminForm(DistanceUnitFormMixin, ModelForm):
Expand All @@ -24,22 +26,10 @@ def has_add_permission(self, request, obj=None):
return False


class TripReportInline(TabularInline):
model = TripReport
fk_name = "trip"
extra = 0
max_num = 0
show_change_link = True
fields = ("title",)

def has_add_permission(self, request, obj=None):
return False


@admin.register(Trip)
class TripAdmin(ModelAdmin):
form = TripAdminForm
inlines = [TripPhotoInline, TripReportInline]
inlines = [TripPhotoInline]
search_fields = (
"cave_name",
"cave_entrance",
Expand Down Expand Up @@ -75,7 +65,10 @@ class TripAdmin(ModelAdmin):
formfield_overrides = {
DistanceField: {
"widget": UnfoldAdminTextInputWidget,
}
},
HTMLField: {
"widget": TinyMCE,
},
}
fieldsets = (
(
Expand Down Expand Up @@ -138,6 +131,7 @@ class TripAdmin(ModelAdmin):
},
),
("Notes", {"fields": ("notes",)}),
("Trip report", {"fields": ("trip_report",)}),
)


Expand Down Expand Up @@ -177,22 +171,3 @@ class TripPhotoAdmin(ModelAdmin):
},
),
)


@admin.register(TripReport)
class TripReportAdmin(ModelAdmin):
list_display = ("user", "title", "trip", "added")
list_display_links = ("title",)
list_filter = ("added", "updated")
ordering = ("-added",)
search_fields = (
"title",
"user__username",
"user__name",
"user__email",
"trip__uuid",
)
search_help_text = (
"Search by title or trip UUID, or by author name, email or username."
)
readonly_fields = ("added", "updated")
21 changes: 1 addition & 20 deletions app/logger/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from factory.django import DjangoModelFactory
from faker import Faker

from .models import Trip, TripReport
from .models import Trip

fake = Faker()

Expand Down Expand Up @@ -261,22 +261,3 @@ def vert_dist_down(self):
def _adjust_kwargs(cls, **kwargs):
kwargs["cave_name"] = kwargs["cave_name"].replace(".", "")
return kwargs


class TripReportFactory(DjangoModelFactory):
class Meta:
model = TripReport

title = factory.Faker("sentence", nb_words=5)
content = factory.Faker("text", max_nb_chars=4000)
trip = factory.Iterator(Trip.objects.filter(report=None))

@classmethod
def _adjust_kwargs(cls, **kwargs):
kwargs["title"] = kwargs["title"].replace(".", "")

user = kwargs.get("user", None)
if user is None:
kwargs["user"] = kwargs["trip"].user

return kwargs
46 changes: 8 additions & 38 deletions app/logger/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from datetime import timedelta

from crispy_bootstrap5.bootstrap5 import FloatingField
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Div, Field, Fieldset, Layout, Submit
from django import forms
Expand All @@ -10,47 +9,11 @@
from users.models import CavingUser

from .mixins import CleanCaveLocationMixin, DistanceUnitFormMixin
from .models import Trip, TripPhoto, TripReport
from .models import Trip, TripPhoto

User = CavingUser


# noinspection PyTypeChecker
class TripReportForm(forms.ModelForm):
class Meta:
model = TripReport
fields = [
"title",
"content",
"privacy",
]

def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user
self.fields["content"].label = ""
self.helper = FormHelper()
self.helper.form_method = "post"
self.helper.layout = Layout(
Fieldset(
"Trip report",
FloatingField("title"),
"content",
"privacy",
css_class="mt-4",
),
)

if self.instance.pk:
self.helper.add_input(
Submit("submit", "Update report", css_class="btn-lg w-100 mt-4")
)
else:
self.helper.add_input(
Submit("submit", "Create report", css_class="btn-lg w-100 mt-4")
)


# noinspection PyTypeChecker
class BaseTripForm(forms.ModelForm):
"""
Expand Down Expand Up @@ -137,6 +100,7 @@ class Meta:
"custom_field_3",
"custom_field_4",
"custom_field_5",
"trip_report",
]
widgets = {
"start": forms.DateTimeInput(attrs={"type": "datetime-local"}),
Expand All @@ -156,6 +120,7 @@ def __init__(self, user, *args, **kwargs):
self.user = user
self.has_custom_fields = False
self.fields["notes"].label = ""
self.fields["trip_report"].label = ""
self.helper = FormHelper()
self.helper.form_method = "post"

Expand Down Expand Up @@ -245,6 +210,11 @@ def __init__(self, user, *args, **kwargs):
"notes",
css_class="mt-4",
),
Fieldset(
"Trip report",
"trip_report",
css_class="mt-4",
),
)

if self.instance.pk:
Expand Down
18 changes: 18 additions & 0 deletions app/logger/migrations/0028_trip_trip_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.6 on 2023-10-20 09:29

import tinymce.models
from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("logger", "0027_remove_tripreport_unique_slug_per_user_and_more"),
]

operations = [
migrations.AddField(
model_name="trip",
name="trip_report",
field=tinymce.models.HTMLField(blank=True),
),
]
27 changes: 27 additions & 0 deletions app/logger/migrations/0029_migrate_trip_report_content_to_trips.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.6 on 2023-10-20 09:34

from django.db import migrations


def migrate_trip_report_content_to_trips(apps, schema_editor):
trip_report = apps.get_model("logger", "TripReport")
trip = apps.get_model("logger", "Trip")

for report in trip_report.objects.all():
trip.objects.filter(pk=report.trip.pk).update(trip_report=report.content)
if report.privacy == "Friends":
trip.objects.filter(pk=report.trip.pk).update(privacy="Friends")
elif report.privacy == "Private":
trip.objects.filter(pk=report.trip.pk).update(privacy="Private")


class Migration(migrations.Migration):
dependencies = [
("logger", "0028_trip_trip_report"),
]

operations = [
migrations.RunPython(
migrate_trip_report_content_to_trips, reverse_code=migrations.RunPython.noop
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 4.2.6 on 2023-10-20 09:44

import tinymce.models
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("logger", "0029_migrate_trip_report_content_to_trips"),
]

operations = [
migrations.AlterField(
model_name="trip",
name="notes",
field=models.TextField(
blank=True,
help_text="Trip notes should contain brief details of the trip, and may be private depending on your account settings. For full trip reports, use the trip report field below.",
),
),
migrations.AlterField(
model_name="trip",
name="trip_report",
field=tinymce.models.HTMLField(
blank=True,
help_text="Trip reports are full, article style reports of a trip and will be visible to anyone who can view the trip.",
),
),
]
Loading