Compare commits
9 Commits
8e80614eee
...
feature/33
Author | SHA1 | Date | |
---|---|---|---|
a22c988e94 | |||
7f2283325c | |||
6b7c71ef30 | |||
067bf36118 | |||
9eef044af9 | |||
a4780a22f2 | |||
0d1d829abe | |||
59cfa82ce9 | |||
d47c85795c |
@@ -65,7 +65,7 @@ class Migration(migrations.Migration):
|
|||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
|
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
|
||||||
('description', models.TextField(blank=True)),
|
('description', models.TextField(blank=True)),
|
||||||
('filename', easy_thumbnails.fields.ThumbnailerImageField(upload_to=lostplaces.models.place.generate_image_upload_path)),
|
('filename', easy_thumbnails.fields.ThumbnailerImageField(upload_to=lostplaces.models.place.generate_place_image_filename)),
|
||||||
('place', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='placeimages', to='lostplaces.place')),
|
('place', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='placeimages', to='lostplaces.place')),
|
||||||
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer')),
|
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer')),
|
||||||
],
|
],
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
# Generated by Django 3.1.1 on 2020-10-04 19:37
|
|
||||||
# Edited by reverend
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.utils.timezone
|
|
||||||
from django.utils.timezone import utc
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('lostplaces', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.DeleteModel(
|
|
||||||
name='Voucher'
|
|
||||||
),
|
|
||||||
migrations.DeleteModel(
|
|
||||||
name='Expireable'
|
|
||||||
)
|
|
||||||
]
|
|
118
django_lostplaces/lostplaces/migrations/0004_gory_fix.py
Normal file
118
django_lostplaces/lostplaces/migrations/0004_gory_fix.py
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Generated by Django 3.1.4 on 2020-12-25 16:02
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import easy_thumbnails.fields
|
||||||
|
from lostplaces.models.models import generate_profile_image_filename
|
||||||
|
from lostplaces.models.place import generate_place_image_filename
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('lostplaces', '0003_voucher'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='explorer',
|
||||||
|
name='bio',
|
||||||
|
field=models.TextField(blank=True, help_text='Describe yourself, your preferences, etc. in a few sentences.', null=True, verbose_name='Biography / Description'),
|
||||||
|
),
|
||||||
|
# migrations.AddField(
|
||||||
|
# model_name='explorer',
|
||||||
|
# name='favorite_places',
|
||||||
|
# field=models.ManyToManyField(blank=True, related_name='explorer_favorites', to='lostplaces.Place', verbose_name='Explorers favorite places'),
|
||||||
|
# ),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='explorer',
|
||||||
|
name='profile_image',
|
||||||
|
field=easy_thumbnails.fields.ThumbnailerImageField(blank=True, help_text='Optional profile image for display in Explorer profile', null=True, upload_to=generate_profile_image_filename, verbose_name='Profile image'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='photoalbum',
|
||||||
|
name='label',
|
||||||
|
field=models.CharField(max_length=100, verbose_name='link text'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='photoalbum',
|
||||||
|
name='submitted_by',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photoalbums', to='lostplaces.explorer', verbose_name='Submitter'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='photoalbum',
|
||||||
|
name='submitted_when',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='photoalbum',
|
||||||
|
name='url',
|
||||||
|
field=models.URLField(verbose_name='URL'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='place',
|
||||||
|
name='description',
|
||||||
|
field=models.TextField(help_text="Description of the place: e.g. how to get there, where to be careful, the place's history...", verbose_name='Description'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='place',
|
||||||
|
name='latitude',
|
||||||
|
field=models.FloatField(help_text='Latitude in decimal format: e. g. 41.40338', validators=[django.core.validators.MinValueValidator(-90), django.core.validators.MaxValueValidator(90)], verbose_name='Latitude'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='place',
|
||||||
|
name='location',
|
||||||
|
field=models.CharField(max_length=50, verbose_name='Location'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='place',
|
||||||
|
name='longitude',
|
||||||
|
field=models.FloatField(help_text='Longitude in decimal format: e. g. 2.17403', validators=[django.core.validators.MinValueValidator(-180), django.core.validators.MaxValueValidator(180)], verbose_name='Longitude'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='place',
|
||||||
|
name='name',
|
||||||
|
field=models.CharField(max_length=50, verbose_name='Name'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='place',
|
||||||
|
name='submitted_by',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='places', to='lostplaces.explorer', verbose_name='Submitter'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='place',
|
||||||
|
name='submitted_when',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='placeimage',
|
||||||
|
name='description',
|
||||||
|
field=models.TextField(blank=True, verbose_name='Description'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='placeimage',
|
||||||
|
name='filename',
|
||||||
|
field=easy_thumbnails.fields.ThumbnailerImageField(help_text='Optional: One or more images to upload', upload_to=generate_place_image_filename, verbose_name='Filename(s)'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='placeimage',
|
||||||
|
name='submitted_by',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer', verbose_name='Submitter'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='placeimage',
|
||||||
|
name='submitted_when',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='voucher',
|
||||||
|
name='created_when',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, verbose_name='Creation date'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='voucher',
|
||||||
|
name='expires_when',
|
||||||
|
field=models.DateTimeField(verbose_name='Expiration date'),
|
||||||
|
),
|
||||||
|
]
|
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.1.4 on 2020-12-25 18:14
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('lostplaces', '0004_auto_20201225_1702'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='explorer',
|
||||||
|
name='visited_places',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='explorer_visits', to='lostplaces.Place', verbose_name='Explorers visited places'),
|
||||||
|
),
|
||||||
|
]
|
@@ -62,6 +62,12 @@ class Explorer(models.Model):
|
|||||||
verbose_name='Explorers favorite places',
|
verbose_name='Explorers favorite places',
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
|
visited_places = models.ManyToManyField(
|
||||||
|
Place,
|
||||||
|
related_name='explorer_visits',
|
||||||
|
verbose_name='Explorers visited places',
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.user.username
|
return self.user.username
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -13,7 +13,7 @@
|
|||||||
viewBox="0 0 512.07 512.07"
|
viewBox="0 0 512.07 512.07"
|
||||||
width="512"
|
width="512"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
sodipodi:docname="favourite_filled.svg"
|
sodipodi:docname="favorite_filled.svg"
|
||||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||||
<metadata
|
<metadata
|
||||||
id="metadata11">
|
id="metadata11">
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
@@ -92,9 +92,21 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% include 'partials/nav/pagination.html' %}
|
{% include 'partials/nav/pagination.html' %}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="LP-Section">
|
||||||
|
<div class="LP-PlaceList">
|
||||||
|
<h1 class="LP-Headline">{% trans 'Visited places' %}</h1>
|
||||||
|
<ul class="LP-PlaceList__List">
|
||||||
|
{% for place in explorer.visited_places.all %}
|
||||||
|
<li class="LP-PlaceList__Item">
|
||||||
|
{% include 'partials/place_teaser.html' with place=place extended=True %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% include 'partials/nav/pagination.html' %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@@ -4,11 +4,11 @@
|
|||||||
{% if request.user %}
|
{% if request.user %}
|
||||||
{% if place in request.user.explorer.favorite_places.all %}
|
{% if place in request.user.explorer.favorite_places.all %}
|
||||||
<a href="{% url 'place_unfavorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Remove from favorites' %}">
|
<a href="{% url 'place_unfavorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Remove from favorites' %}">
|
||||||
<img class="LP-Icon" src="{% static '/icons/favourite_filled.svg' %}" />
|
<img class="LP-Icon" src="{% static '/icons/favorite_filled.svg' %}" />
|
||||||
</a>
|
</a>
|
||||||
{%else%}
|
{%else%}
|
||||||
<a href="{% url 'place_favorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Save as favorite' %}">
|
<a href="{% url 'place_favorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Save as favorite' %}">
|
||||||
<img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" />
|
<img class="LP-Icon" src="{% static '/icons/favorite.svg' %}" />
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
@@ -0,0 +1,14 @@
|
|||||||
|
{%load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% if request.user %}
|
||||||
|
{% if place in request.user.explorer.visited_places.all %}
|
||||||
|
<a href="{% url 'place_visit_delete' place_id=place.id %}" class="LP-Link" title="{% trans 'Remove from visits' %}">
|
||||||
|
<img class="LP-Icon" src="{% static '/icons/pin_filled.svg' %}" />
|
||||||
|
</a>
|
||||||
|
{%else%}
|
||||||
|
<a href="{% url 'place_visit_create' place_id=place.id %}" class="LP-Link" title="{% trans 'Save as visited' %}">
|
||||||
|
<img class="LP-Icon" src="{% static '/icons/pin.svg' %}" />
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
@@ -31,7 +31,7 @@
|
|||||||
<div class="LP-PlaceTeaser__Icons">
|
<div class="LP-PlaceTeaser__Icons">
|
||||||
<ul class="LP-Icon__List">
|
<ul class="LP-Icon__List">
|
||||||
<li class="LP-Icon__Item">{% include 'partials/icons/place_favorite.html' with place=place%}</li>
|
<li class="LP-Icon__Item">{% include 'partials/icons/place_favorite.html' with place=place%}</li>
|
||||||
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/pin.svg' %}" /></li>
|
<li class="LP-Icon__Item">{% include 'partials/icons/place_visited.html' with place=place%}</li>
|
||||||
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li>
|
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
<article class="LP-PlaceDetail">
|
<article class="LP-PlaceDetail">
|
||||||
|
|
||||||
<header class="LP-PlaceDetail__Header">
|
<header class="LP-PlaceDetail__Header">
|
||||||
<h1 class="LP-Headline">{{ place.name }} {% include 'partials/icons/place_favorite.html' %}</h1>
|
<h1 class="LP-Headline">{{ place.name }} {% include 'partials/icons/place_favorite.html' %} {% include 'partials/icons/place_visited.html' %}</h1>
|
||||||
{% if place.placeimages.first.filename.hero.url %}
|
{% if place.placeimages.first.filename.hero.url %}
|
||||||
<figure class="LP-PlaceDetail__Image">
|
<figure class="LP-PlaceDetail__Image">
|
||||||
<img src="{{ place.placeimages.first.filename.hero.url }}" class="LP-Image" />
|
<img src="{{ place.placeimages.first.filename.hero.url }}" class="LP-Image" />
|
||||||
|
@@ -4,6 +4,8 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from lostplaces.views import (
|
from lostplaces.views import (
|
||||||
HomeView,
|
HomeView,
|
||||||
|
FlatView,
|
||||||
|
OSMMapView,
|
||||||
PlaceDetailView,
|
PlaceDetailView,
|
||||||
PlaceListView,
|
PlaceListView,
|
||||||
PlaceCreateView,
|
PlaceCreateView,
|
||||||
@@ -13,37 +15,39 @@ from lostplaces.views import (
|
|||||||
PlaceTagSubmitView,
|
PlaceTagSubmitView,
|
||||||
PlaceFavoriteView,
|
PlaceFavoriteView,
|
||||||
PlaceUnfavoriteView,
|
PlaceUnfavoriteView,
|
||||||
PhotoAlbumCreateView,
|
PlaceVisitCreateView,
|
||||||
PhotoAlbumDeleteView,
|
PlaceVisitDeleteView,
|
||||||
PlaceImageCreateView,
|
PlaceImageCreateView,
|
||||||
PlaceImageDeleteView,
|
PlaceImageDeleteView,
|
||||||
FlatView,
|
PhotoAlbumCreateView,
|
||||||
|
PhotoAlbumDeleteView,
|
||||||
ExplorerProfileView,
|
ExplorerProfileView,
|
||||||
ExplorerProfileUpdateView,
|
ExplorerProfileUpdateView
|
||||||
OSMMapView
|
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', HomeView.as_view(), name='lostplaces_home'),
|
path('', HomeView.as_view(), name='lostplaces_home'),
|
||||||
path('place/<int:pk>/', PlaceDetailView.as_view(), name='place_detail'),
|
|
||||||
path('place/create/', PlaceCreateView.as_view(), name='place_create'),
|
|
||||||
path('photo_album/create/<int:place_id>', PhotoAlbumCreateView.as_view(), name='photo_album_create'),
|
|
||||||
path('photo_album/delete/<int:pk>', PhotoAlbumDeleteView.as_view(), name='photo_album_delete'),
|
|
||||||
path('place/update/<int:pk>/', PlaceUpdateView.as_view(), name='place_edit'),
|
|
||||||
path('place/delete/<int:pk>/', PlaceDeleteView.as_view(), name='place_delete'),
|
|
||||||
path('place/', PlaceListView.as_view(), name='place_list'),
|
|
||||||
path('place_image/create/<int:place_id>', PlaceImageCreateView.as_view(), name='place_image_create'),
|
|
||||||
path('place_image/delete/<int:pk>', PlaceImageDeleteView.as_view(), name='place_image_delete'),
|
|
||||||
path('flat/<slug:slug>/', FlatView, name='flatpage'),
|
path('flat/<slug:slug>/', FlatView, name='flatpage'),
|
||||||
|
path('osm/', OSMMapView.as_view(), name='osm'),
|
||||||
|
|
||||||
# POST-only URLs for tag submission
|
|
||||||
path('place/tag/<int:tagged_id>', PlaceTagSubmitView.as_view(), name='place_tag_submit'),
|
|
||||||
path('place/tag/delete/<int:tagged_id>/<int:tag_id>', PlaceTagDeleteView.as_view(), name='place_tag_delete'),
|
|
||||||
|
|
||||||
path('explorer/<int:explorer_id>/', ExplorerProfileView.as_view(), name='explorer_profile'),
|
path('explorer/<int:explorer_id>/', ExplorerProfileView.as_view(), name='explorer_profile'),
|
||||||
path('explorer/update/', ExplorerProfileUpdateView.as_view(), name='explorer_profile_update'),
|
path('explorer/update/', ExplorerProfileUpdateView.as_view(), name='explorer_profile_update'),
|
||||||
|
|
||||||
path('explorer/favorite/<int:place_id>/', PlaceFavoriteView.as_view(), name='place_favorite'),
|
path('place/', PlaceListView.as_view(), name='place_list'),
|
||||||
path('explorer/unfavorite/<int:place_id>/', PlaceUnfavoriteView.as_view(), name='place_unfavorite'),
|
path('place/<int:pk>/', PlaceDetailView.as_view(), name='place_detail'),
|
||||||
path('osm/', OSMMapView.as_view(), name='osm')
|
path('place/create/', PlaceCreateView.as_view(), name='place_create'),
|
||||||
|
path('place/update/<int:pk>/', PlaceUpdateView.as_view(), name='place_edit'),
|
||||||
|
path('place/delete/<int:pk>/', PlaceDeleteView.as_view(), name='place_delete'),
|
||||||
|
path('place/tag/create/<int:tagged_id>/', PlaceTagSubmitView.as_view(), name='place_tag_submit'),
|
||||||
|
path('place/tag/delete/<int:tagged_id>/<int:tag_id>/', PlaceTagDeleteView.as_view(), name='place_tag_delete'),
|
||||||
|
path('place/fav/create/<int:place_id>/', PlaceFavoriteView.as_view(), name='place_favorite'),
|
||||||
|
path('place/fav/delete/<int:place_id>/', PlaceUnfavoriteView.as_view(), name='place_unfavorite'),
|
||||||
|
path('place/visit/create/<int:place_id>/', PlaceVisitCreateView.as_view(), name='place_visit_create'),
|
||||||
|
path('place/visit/delete/<int:place_id>/', PlaceVisitDeleteView.as_view(), name='place_visit_delete'),
|
||||||
|
|
||||||
|
path('place_image/create/<int:place_id>/', PlaceImageCreateView.as_view(), name='place_image_create'),
|
||||||
|
path('place_image/delete/<int:pk>/', PlaceImageDeleteView.as_view(), name='place_image_delete'),
|
||||||
|
|
||||||
|
path('photo_album/create/<int:place_id>/', PhotoAlbumCreateView.as_view(), name='photo_album_create'),
|
||||||
|
path('photo_album/delete/<int:pk>/', PhotoAlbumDeleteView.as_view(), name='photo_album_delete')
|
||||||
]
|
]
|
||||||
|
@@ -147,3 +147,23 @@ class PlaceUnfavoriteView(IsAuthenticatedMixin, View):
|
|||||||
request.user.explorer.save()
|
request.user.explorer.save()
|
||||||
|
|
||||||
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
||||||
|
|
||||||
|
class PlaceVisitCreateView(IsAuthenticatedMixin, View):
|
||||||
|
|
||||||
|
def get(self, request, place_id):
|
||||||
|
place = get_object_or_404(Place, id=place_id)
|
||||||
|
if request.user is not None:
|
||||||
|
request.user.explorer.visited_places.add(place)
|
||||||
|
request.user.explorer.save()
|
||||||
|
|
||||||
|
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
||||||
|
|
||||||
|
class PlaceVisitDeleteView(IsAuthenticatedMixin, View):
|
||||||
|
|
||||||
|
def get(self, request, place_id):
|
||||||
|
place = get_object_or_404(Place, id=place_id)
|
||||||
|
if request.user is not None:
|
||||||
|
request.user.explorer.visited_places.remove(place)
|
||||||
|
request.user.explorer.save()
|
||||||
|
|
||||||
|
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
||||||
|
Reference in New Issue
Block a user