first stuff for custom positions
This commit is contained in:
parent
e144156b8a
commit
407e3ba06b
12 changed files with 655 additions and 267 deletions
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,56 @@
|
||||||
|
# Generated by Django 2.2.8 on 2019-12-27 12:51
|
||||||
|
|
||||||
|
import c3nav.mapdata.fields
|
||||||
|
import c3nav.mapdata.models.locations
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('mapdata', '0081_auto_20191225_1015'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Position',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=32, verbose_name='name')),
|
||||||
|
('secret', models.CharField(default=c3nav.mapdata.models.locations.get_position_secret, max_length=32, unique=True, verbose_name='secret')),
|
||||||
|
('last_location_update', models.DateTimeField(null=True, verbose_name='last location update')),
|
||||||
|
('location_id', models.CharField(max_length=48, null=True, verbose_name='location')),
|
||||||
|
('api_secret', models.CharField(default=c3nav.mapdata.models.locations.get_position_api_secret, max_length=64, verbose_name='api secret')),
|
||||||
|
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dynamic_positions', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Dynamic position',
|
||||||
|
'verbose_name_plural': 'Dynamic position',
|
||||||
|
'default_related_name': 'dynamic_positions',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='DynamicLocation',
|
||||||
|
fields=[
|
||||||
|
('locationslug_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='dynamic_locations', serialize=False, to='mapdata.LocationSlug')),
|
||||||
|
('title', c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, fallback_value='{model} {pk}', plural_name='titles', verbose_name='Title')),
|
||||||
|
('can_search', models.BooleanField(default=True, verbose_name='can be searched')),
|
||||||
|
('can_describe', models.BooleanField(default=True, verbose_name='can describe')),
|
||||||
|
('icon', models.CharField(blank=True, help_text='any material icons name', max_length=32, null=True, verbose_name='icon')),
|
||||||
|
('label_override', c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, plural_name='label_overrides', verbose_name='Label override')),
|
||||||
|
('position_secret', models.CharField(blank=True, max_length=32, null=True, verbose_name='position secret')),
|
||||||
|
('access_restriction', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='dynamic_locations', to='mapdata.AccessRestriction', verbose_name='Access Restriction')),
|
||||||
|
('groups', models.ManyToManyField(blank=True, related_name='dynamic_locations', to='mapdata.LocationGroup', verbose_name='Location Groups')),
|
||||||
|
('label_settings', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='dynamic_locations', to='mapdata.LabelSettings', verbose_name='label settings')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Dynamic location',
|
||||||
|
'verbose_name_plural': 'Dynamic locations',
|
||||||
|
'default_related_name': 'dynamic_locations',
|
||||||
|
},
|
||||||
|
bases=('mapdata.locationslug', models.Model),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,11 +1,14 @@
|
||||||
|
import string
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import FieldDoesNotExist, Prefetch
|
from django.db.models import FieldDoesNotExist, Prefetch
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.text import format_lazy
|
from django.utils.text import format_lazy
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -15,6 +18,7 @@ from c3nav.mapdata.fields import I18nField
|
||||||
from c3nav.mapdata.grid import grid
|
from c3nav.mapdata.grid import grid
|
||||||
from c3nav.mapdata.models.access import AccessRestrictionMixin
|
from c3nav.mapdata.models.access import AccessRestrictionMixin
|
||||||
from c3nav.mapdata.models.base import SerializableMixin, TitledMixin
|
from c3nav.mapdata.models.base import SerializableMixin, TitledMixin
|
||||||
|
from c3nav.mapdata.utils.fields import LocationById
|
||||||
from c3nav.mapdata.utils.models import get_submodels
|
from c3nav.mapdata.utils.models import get_submodels
|
||||||
|
|
||||||
|
|
||||||
|
@ -452,3 +456,52 @@ class LabelSettings(SerializableMixin, models.Model):
|
||||||
verbose_name_plural = _('Label Settings')
|
verbose_name_plural = _('Label Settings')
|
||||||
default_related_name = 'labelsettings'
|
default_related_name = 'labelsettings'
|
||||||
ordering = ('min_zoom', '-font_size')
|
ordering = ('min_zoom', '-font_size')
|
||||||
|
|
||||||
|
|
||||||
|
class DynamicLocation(SpecificLocation, models.Model):
|
||||||
|
position_secret = models.CharField(_('position secret'), max_length=32, null=True, blank=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Dynamic location')
|
||||||
|
verbose_name_plural = _('Dynamic locations')
|
||||||
|
default_related_name = 'dynamic_locations'
|
||||||
|
|
||||||
|
"""
|
||||||
|
def _serialize(self, **kwargs):
|
||||||
|
result = super()._serialize(**kwargs)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def grid_square(self):
|
||||||
|
return grid.get_squares_for_bounds(self.geometry.bounds) or ''
|
||||||
|
|
||||||
|
def details_display(self, editor_url=True, **kwargs):
|
||||||
|
result = super().details_display(**kwargs)
|
||||||
|
if editor_url:
|
||||||
|
result['editor_url'] = reverse('editor.areas.edit', kwargs={'space': self.space_id, 'pk': self.pk})
|
||||||
|
return result
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_position_secret():
|
||||||
|
return get_random_string(32, string.ascii_letters+string.digits)
|
||||||
|
|
||||||
|
|
||||||
|
def get_position_api_secret():
|
||||||
|
return get_random_string(64, string.ascii_letters+string.digits)
|
||||||
|
|
||||||
|
|
||||||
|
class Position(models.Model):
|
||||||
|
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||||
|
name = models.CharField(_('name'), max_length=32)
|
||||||
|
secret = models.CharField(_('secret'), unique=True, max_length=32, default=get_position_secret)
|
||||||
|
last_location_update = models.DateTimeField(_('last location update'), null=True)
|
||||||
|
location_id = models.CharField(_('location'), null=True, max_length=48)
|
||||||
|
api_secret = models.CharField(_('api secret'), max_length=64, default=get_position_api_secret)
|
||||||
|
|
||||||
|
coordinates = LocationById()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Dynamic position')
|
||||||
|
verbose_name_plural = _('Dynamic position')
|
||||||
|
default_related_name = 'dynamic_positions'
|
||||||
|
|
|
@ -3,7 +3,6 @@ import string
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
@ -15,7 +14,7 @@ from c3nav.mapdata.fields import I18nField
|
||||||
from c3nav.mapdata.models.geometry.level import LevelGeometryMixin
|
from c3nav.mapdata.models.geometry.level import LevelGeometryMixin
|
||||||
from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
|
from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
|
||||||
from c3nav.mapdata.models.locations import SpecificLocation
|
from c3nav.mapdata.models.locations import SpecificLocation
|
||||||
from c3nav.mapdata.utils.locations import get_location_by_id_for_request
|
from c3nav.mapdata.utils.fields import LocationById
|
||||||
from c3nav.mapdata.utils.models import get_submodels
|
from c3nav.mapdata.utils.models import get_submodels
|
||||||
from c3nav.site.tasks import send_report_notification
|
from c3nav.site.tasks import send_report_notification
|
||||||
|
|
||||||
|
@ -24,39 +23,6 @@ def get_report_secret():
|
||||||
return get_random_string(32, string.ascii_letters)
|
return get_random_string(32, string.ascii_letters)
|
||||||
|
|
||||||
|
|
||||||
class LocationById():
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.name = None
|
|
||||||
self.cached_id = None
|
|
||||||
self.cached_value = None
|
|
||||||
|
|
||||||
def __set_name__(self, owner, name):
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def __get__(self, instance, owner=None):
|
|
||||||
value_id = getattr(instance, self.name+'_id')
|
|
||||||
if value_id is None:
|
|
||||||
self.cached_pk = None
|
|
||||||
self.cached_value = None
|
|
||||||
return None
|
|
||||||
|
|
||||||
if value_id == self.cached_id:
|
|
||||||
return self.cached_value
|
|
||||||
|
|
||||||
value = get_location_by_id_for_request(value_id, getattr(instance, 'request', None))
|
|
||||||
if value is None:
|
|
||||||
raise ObjectDoesNotExist
|
|
||||||
self.cached_id = value_id
|
|
||||||
self.cached_value = value
|
|
||||||
return value
|
|
||||||
|
|
||||||
def __set__(self, instance, value):
|
|
||||||
self.cached_id = value.pk
|
|
||||||
self.cached_value = value
|
|
||||||
setattr(instance, self.name+'_id', value.pk)
|
|
||||||
|
|
||||||
|
|
||||||
class Report(models.Model):
|
class Report(models.Model):
|
||||||
CATEGORIES = (
|
CATEGORIES = (
|
||||||
('location-issue', _('location issue')),
|
('location-issue', _('location issue')),
|
||||||
|
|
35
src/c3nav/mapdata/utils/fields.py
Normal file
35
src/c3nav/mapdata/utils/fields.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
|
|
||||||
|
class LocationById():
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.name = None
|
||||||
|
self.cached_id = None
|
||||||
|
self.cached_value = None
|
||||||
|
|
||||||
|
def __set_name__(self, owner, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __get__(self, instance, owner=None):
|
||||||
|
value_id = getattr(instance, self.name+'_id')
|
||||||
|
if value_id is None:
|
||||||
|
self.cached_pk = None
|
||||||
|
self.cached_value = None
|
||||||
|
return None
|
||||||
|
|
||||||
|
if value_id == self.cached_id:
|
||||||
|
return self.cached_value
|
||||||
|
|
||||||
|
from c3nav.mapdata.utils.locations import get_location_by_id_for_request
|
||||||
|
value = get_location_by_id_for_request(value_id, getattr(instance, 'request', None))
|
||||||
|
if value is None:
|
||||||
|
raise ObjectDoesNotExist
|
||||||
|
self.cached_id = value_id
|
||||||
|
self.cached_value = value
|
||||||
|
return value
|
||||||
|
|
||||||
|
def __set__(self, instance, value):
|
||||||
|
self.cached_id = value.pk
|
||||||
|
self.cached_value = value
|
||||||
|
setattr(instance, self.name+'_id', value.pk)
|
|
@ -3,6 +3,7 @@ from django.forms import ModelForm
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from c3nav.mapdata.forms import I18nModelFormMixin
|
from c3nav.mapdata.forms import I18nModelFormMixin
|
||||||
|
from c3nav.mapdata.models.locations import Position
|
||||||
from c3nav.mapdata.models.report import Report, ReportUpdate
|
from c3nav.mapdata.models.report import Report, ReportUpdate
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,3 +47,9 @@ class ReportUpdateForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ReportUpdate
|
model = ReportUpdate
|
||||||
fields = ['open', 'comment', 'public']
|
fields = ['open', 'comment', 'public']
|
||||||
|
|
||||||
|
|
||||||
|
class PositionForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Position
|
||||||
|
fields = ['name']
|
||||||
|
|
|
@ -41,6 +41,15 @@
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{% trans 'You can create custom positions.' %}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="button" href="{% url 'site.position_list' %}">{% trans 'Manage your positions' %}</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<p>
|
<p>
|
||||||
<a class="button" href="{% url 'site.logout' %}">{% trans 'Log out' %}</a>
|
<a class="button" href="{% url 'site.logout' %}">{% trans 'Log out' %}</a>
|
||||||
|
|
16
src/c3nav/site/templates/site/position_create.html
Normal file
16
src/c3nav/site/templates/site/position_create.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{% extends 'site/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="account">
|
||||||
|
<h2>{% trans 'Create position' %}</h2>
|
||||||
|
{% include 'site/fragment_messages.html' %}
|
||||||
|
<p><a href="{% url 'site.position_list' %}">« {% trans 'back to overview' %}</a></p>
|
||||||
|
|
||||||
|
<form method="post" action="{{ request.path_info }}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<button type="submit">{% trans 'Submit' %}</button>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
30
src/c3nav/site/templates/site/position_detail.html
Normal file
30
src/c3nav/site/templates/site/position_detail.html
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{% extends 'site/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="account">
|
||||||
|
{% include 'site/fragment_messages.html' %}
|
||||||
|
<h2>{% trans 'Position:' %} {{ position.name }}</h2>
|
||||||
|
<p><a href="{% url 'site.position_list' %}">« {% trans 'back to overview' %}</a></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>{% trans 'Secret' %}:</strong>
|
||||||
|
<code>{{ position.secret }}</code>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>{% trans 'API secret' %}:</strong>
|
||||||
|
<code>{{ position.api_secret }}</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<form method="post" action="{{ request.path_info }}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<label><input type="checkbox" name="reset_secret" value="1"> {% trans 'reset secret' %}</label>
|
||||||
|
<label><input type="checkbox" name="reset_api_secret" value="1"> {% trans 'reset API secret' %}</label>
|
||||||
|
<label><input type="checkbox" name="delete" value="1"> {% trans 'delete this position' %}</label>
|
||||||
|
<button type="submit">{% trans 'Update position' %}</button>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
18
src/c3nav/site/templates/site/position_list.html
Normal file
18
src/c3nav/site/templates/site/position_list.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends 'site/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<main class="account">
|
||||||
|
{% include 'site/fragment_messages.html' %}
|
||||||
|
<h2>{% trans 'Your positions' %}</h2>
|
||||||
|
<p>(still work in progress, stay tuned for more information)</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for position in positions %}
|
||||||
|
<li><a href="{% url 'site.position_detail' pk=position.pk %}">{{ position.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a class="button" href="{% url 'site.position_create' %}">{% trans 'Create position' %}</a>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
|
@ -1,8 +1,8 @@
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from c3nav.site.views import (about_view, access_redeem_view, account_view, change_password_view, choose_language,
|
from c3nav.site.views import (about_view, access_redeem_view, account_view, change_password_view, choose_language,
|
||||||
login_view, logout_view, map_index, qr_code, register_view, report_create, report_detail,
|
login_view, logout_view, map_index, position_create, position_detail, position_list,
|
||||||
report_list)
|
qr_code, register_view, report_create, report_detail, report_list)
|
||||||
|
|
||||||
slug = r'(?P<slug>[a-z0-9-_.:]+)'
|
slug = r'(?P<slug>[a-z0-9-_.:]+)'
|
||||||
coordinates = r'(?P<coordinates>[a-z0-9-_:]+:-?\d+(\.\d+)?:-?\d+(\.\d+)?)'
|
coordinates = r'(?P<coordinates>[a-z0-9-_:]+:-?\d+(\.\d+)?:-?\d+(\.\d+)?)'
|
||||||
|
@ -35,4 +35,7 @@ urlpatterns = [
|
||||||
url(r'^report/l/(?P<location>\d+)/$', report_create, name='site.report_create'),
|
url(r'^report/l/(?P<location>\d+)/$', report_create, name='site.report_create'),
|
||||||
url(r'^report/r/(?P<origin>[^/]+)/(?P<destination>[^/]+)/(?P<options>[^/]+)/$',
|
url(r'^report/r/(?P<origin>[^/]+)/(?P<destination>[^/]+)/(?P<options>[^/]+)/$',
|
||||||
report_create, name='site.report_create'),
|
report_create, name='site.report_create'),
|
||||||
|
url(r'^positions/$', position_list, name='site.position_list'),
|
||||||
|
url(r'^positions/create/$', position_create, name='site.position_create'),
|
||||||
|
url(r'^positions/(?P<pk>\d+)/$', position_detail, name='site.position_detail'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -28,14 +28,15 @@ from c3nav.control.forms import AccessPermissionForm, SignedPermissionDataError
|
||||||
from c3nav.mapdata.grid import grid
|
from c3nav.mapdata.grid import grid
|
||||||
from c3nav.mapdata.models import Location, Source
|
from c3nav.mapdata.models import Location, Source
|
||||||
from c3nav.mapdata.models.access import AccessPermissionToken
|
from c3nav.mapdata.models.access import AccessPermissionToken
|
||||||
from c3nav.mapdata.models.locations import LocationRedirect, SpecificLocation
|
from c3nav.mapdata.models.locations import (LocationRedirect, Position, SpecificLocation, get_position_api_secret,
|
||||||
|
get_position_secret)
|
||||||
from c3nav.mapdata.models.report import Report, ReportUpdate
|
from c3nav.mapdata.models.report import Report, ReportUpdate
|
||||||
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,
|
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,
|
||||||
levels_by_short_label_for_request)
|
levels_by_short_label_for_request)
|
||||||
from c3nav.mapdata.utils.user import can_access_editor, get_user_data
|
from c3nav.mapdata.utils.user import can_access_editor, get_user_data
|
||||||
from c3nav.mapdata.views import set_tile_access_cookie
|
from c3nav.mapdata.views import set_tile_access_cookie
|
||||||
from c3nav.routing.models import RouteOptions
|
from c3nav.routing.models import RouteOptions
|
||||||
from c3nav.site.forms import ReportUpdateForm
|
from c3nav.site.forms import PositionForm, ReportUpdateForm
|
||||||
from c3nav.site.models import Announcement, SiteUpdate
|
from c3nav.site.models import Announcement, SiteUpdate
|
||||||
|
|
||||||
|
|
||||||
|
@ -433,6 +434,7 @@ def report_create(request, coordinates=None, location=None, origin=None, destina
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url='site.login')
|
||||||
def report_list(request, filter):
|
def report_list(request, filter):
|
||||||
page = request.GET.get('page', 1)
|
page = request.GET.get('page', 1)
|
||||||
|
|
||||||
|
@ -481,3 +483,66 @@ def report_detail(request, pk, secret=None):
|
||||||
'form': form,
|
'form': form,
|
||||||
'update_form': update_form,
|
'update_form': update_form,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url='site.login')
|
||||||
|
def position_list(request):
|
||||||
|
return render(request, 'site/position_list.html', {
|
||||||
|
'positions': Position.objects.filter(owner=request.user),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url='site.login')
|
||||||
|
def position_create(request):
|
||||||
|
if Position.objects.filter(owner=request.user).count() >= 20:
|
||||||
|
messages.error(request, _('You can\'t create more than 20 positions.'))
|
||||||
|
|
||||||
|
position = Position()
|
||||||
|
position.owner = request.user
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = PositionForm(instance=position, data=request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
messages.success(request, _('Position created.'))
|
||||||
|
return redirect(reverse('site.position_detail', kwargs={'pk': position.pk}))
|
||||||
|
else:
|
||||||
|
form = PositionForm(instance=position)
|
||||||
|
|
||||||
|
return render(request, 'site/position_create.html', {
|
||||||
|
'form': form,
|
||||||
|
})
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url='site.login')
|
||||||
|
def position_detail(request, pk):
|
||||||
|
position = get_object_or_404(Position.objects.filter(owner=request.user), pk=pk)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
with transaction.atomic():
|
||||||
|
if request.POST.get('delete', None):
|
||||||
|
position.delete()
|
||||||
|
messages.success(request, _('Position deleted.'))
|
||||||
|
return redirect(reverse('site.position_list'))
|
||||||
|
|
||||||
|
if request.POST.get('reset_secret', None):
|
||||||
|
position.secret = get_position_secret()
|
||||||
|
|
||||||
|
if request.POST.get('reset_api_secret', None):
|
||||||
|
position.api_secret = get_position_api_secret()
|
||||||
|
|
||||||
|
form = PositionForm(instance=position, data=request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
messages.success(request, _('Position updated.'))
|
||||||
|
return redirect(reverse('site.position_detail', kwargs={'pk': position.pk}))
|
||||||
|
else:
|
||||||
|
form = PositionForm(instance=position)
|
||||||
|
|
||||||
|
return render(request, 'site/position_detail.html', {
|
||||||
|
'position': position,
|
||||||
|
'form': form,
|
||||||
|
})
|
||||||
|
pass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue