forked from DGNum/gestioCOF
Upgrade to Django 1.11
- Deprecation warnings using Django 1.8 are resolved. - Deprecation warnings using Django 1.11 are resolved. - Admin: grappelli is no longer used. - Upgrade to django-autocomplete-light v3 (v2 is not 1.11 compatible). * autocomplete.modelform_factory being dropped, code uses dal Select2 views and widgets.
This commit is contained in:
parent
36ce038050
commit
b0b0542407
44 changed files with 341 additions and 278 deletions
15
bda/admin.py
15
bda/admin.py
|
@ -1,6 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import autocomplete_light
|
||||
from datetime import timedelta
|
||||
from custommail.shortcuts import send_mass_custom_mail
|
||||
|
||||
|
@ -9,6 +8,9 @@ from django.db.models import Sum, Count
|
|||
from django.template.defaultfilters import pluralize
|
||||
from django.utils import timezone
|
||||
from django import forms
|
||||
|
||||
from dal.autocomplete import ModelSelect2
|
||||
|
||||
from bda.models import Spectacle, Salle, Participant, ChoixSpectacle,\
|
||||
Attribution, Tirage, Quote, CategorieSpectacle, SpectacleRevente
|
||||
|
||||
|
@ -24,8 +26,17 @@ class ReadOnlyMixin(object):
|
|||
return readonly_fields + self.readonly_fields_update
|
||||
|
||||
|
||||
class ChoixSpectacleAdminForm(forms.ModelForm):
|
||||
class Meta:
|
||||
widgets = {
|
||||
'participant': ModelSelect2(url='bda-participant-autocomplete'),
|
||||
'spectacle': ModelSelect2(url='bda-spectacle-autocomplete'),
|
||||
}
|
||||
|
||||
|
||||
class ChoixSpectacleInline(admin.TabularInline):
|
||||
model = ChoixSpectacle
|
||||
form = ChoixSpectacleAdminForm
|
||||
sortable_field_name = "priority"
|
||||
|
||||
|
||||
|
@ -180,7 +191,7 @@ class AttributionAdmin(ReadOnlyMixin, admin.ModelAdmin):
|
|||
|
||||
|
||||
class ChoixSpectacleAdmin(admin.ModelAdmin):
|
||||
form = autocomplete_light.modelform_factory(ChoixSpectacle, exclude=[])
|
||||
form = ChoixSpectacleAdminForm
|
||||
|
||||
def tirage(self, obj):
|
||||
return obj.participant.tirage
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import autocomplete_light
|
||||
|
||||
from bda.models import Participant, Spectacle
|
||||
|
||||
autocomplete_light.register(
|
||||
Participant, search_fields=('user__username', 'user__first_name',
|
||||
'user__last_name'),
|
||||
autocomplete_js_attributes={'placeholder': 'participant...'})
|
||||
|
||||
autocomplete_light.register(
|
||||
Spectacle, search_fields=('title', ),
|
||||
autocomplete_js_attributes={'placeholder': 'spectacle...'})
|
|
@ -59,7 +59,7 @@ class Migration(migrations.Migration):
|
|||
('price', models.FloatField(verbose_name=b"Prix d'une place", blank=True)),
|
||||
('slots', models.IntegerField(verbose_name=b'Places')),
|
||||
('priority', models.IntegerField(default=1000, verbose_name=b'Priorit\xc3\xa9')),
|
||||
('location', models.ForeignKey(to='bda.Salle')),
|
||||
('location', models.ForeignKey(to='bda.Salle', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('priority', 'date', 'title'),
|
||||
|
@ -79,27 +79,27 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='participant',
|
||||
name='user',
|
||||
field=models.OneToOneField(to=settings.AUTH_USER_MODEL),
|
||||
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='choixspectacle',
|
||||
name='participant',
|
||||
field=models.ForeignKey(to='bda.Participant'),
|
||||
field=models.ForeignKey(to='bda.Participant', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='choixspectacle',
|
||||
name='spectacle',
|
||||
field=models.ForeignKey(related_name='participants', to='bda.Spectacle'),
|
||||
field=models.ForeignKey(related_name='participants', to='bda.Spectacle', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='attribution',
|
||||
name='participant',
|
||||
field=models.ForeignKey(to='bda.Participant'),
|
||||
field=models.ForeignKey(to='bda.Participant', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='attribution',
|
||||
name='spectacle',
|
||||
field=models.ForeignKey(related_name='attribues', to='bda.Spectacle'),
|
||||
field=models.ForeignKey(related_name='attribues', to='bda.Spectacle', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='choixspectacle',
|
||||
|
|
|
@ -55,7 +55,7 @@ class Migration(migrations.Migration):
|
|||
migrations.AlterField(
|
||||
model_name='participant',
|
||||
name='user',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
),
|
||||
# Create fields `spectacle` for `Participant` and `Spectacle` models.
|
||||
# These fields are not nullable, but we first create them as nullable
|
||||
|
@ -63,22 +63,22 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='participant',
|
||||
name='tirage',
|
||||
field=models.ForeignKey(to='bda.Tirage', null=True),
|
||||
field=models.ForeignKey(to='bda.Tirage', null=True, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='spectacle',
|
||||
name='tirage',
|
||||
field=models.ForeignKey(to='bda.Tirage', null=True),
|
||||
field=models.ForeignKey(to='bda.Tirage', null=True, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.RunPython(fill_tirage_fields, migrations.RunPython.noop),
|
||||
migrations.AlterField(
|
||||
model_name='participant',
|
||||
name='tirage',
|
||||
field=models.ForeignKey(to='bda.Tirage'),
|
||||
field=models.ForeignKey(to='bda.Tirage', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='spectacle',
|
||||
name='tirage',
|
||||
field=models.ForeignKey(to='bda.Tirage'),
|
||||
field=models.ForeignKey(to='bda.Tirage', on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -73,6 +73,7 @@ class Migration(migrations.Migration):
|
|||
model_name='spectacle',
|
||||
name='category',
|
||||
field=models.ForeignKey(blank=True, to='bda.CategorieSpectacle',
|
||||
on_delete=models.CASCADE,
|
||||
null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
|
@ -84,6 +85,7 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='quote',
|
||||
name='spectacle',
|
||||
field=models.ForeignKey(to='bda.Spectacle'),
|
||||
field=models.ForeignKey(to='bda.Spectacle',
|
||||
on_delete=models.CASCADE),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -47,12 +47,14 @@ class Migration(migrations.Migration):
|
|||
model_name='spectaclerevente',
|
||||
name='attribution',
|
||||
field=models.OneToOneField(to='bda.Attribution',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='revente'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='spectaclerevente',
|
||||
name='seller',
|
||||
field=models.ForeignKey(to='bda.Participant',
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name='Vendeur',
|
||||
related_name='original_shows'),
|
||||
),
|
||||
|
@ -60,6 +62,7 @@ class Migration(migrations.Migration):
|
|||
model_name='spectaclerevente',
|
||||
name='soldTo',
|
||||
field=models.ForeignKey(to='bda.Participant',
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name='Vendue à', null=True,
|
||||
blank=True),
|
||||
),
|
||||
|
|
|
@ -59,9 +59,12 @@ class CategorieSpectacle(models.Model):
|
|||
|
||||
class Spectacle(models.Model):
|
||||
title = models.CharField("Titre", max_length=300)
|
||||
category = models.ForeignKey(CategorieSpectacle, blank=True, null=True)
|
||||
category = models.ForeignKey(
|
||||
CategorieSpectacle, on_delete=models.CASCADE,
|
||||
blank=True, null=True,
|
||||
)
|
||||
date = models.DateTimeField("Date & heure")
|
||||
location = models.ForeignKey(Salle)
|
||||
location = models.ForeignKey(Salle, on_delete=models.CASCADE)
|
||||
vips = models.TextField('Personnalités', blank=True)
|
||||
description = models.TextField("Description", blank=True)
|
||||
slots_description = models.TextField("Description des places", blank=True)
|
||||
|
@ -71,7 +74,7 @@ class Spectacle(models.Model):
|
|||
max_length=500)
|
||||
price = models.FloatField("Prix d'une place")
|
||||
slots = models.IntegerField("Places")
|
||||
tirage = models.ForeignKey(Tirage)
|
||||
tirage = models.ForeignKey(Tirage, on_delete=models.CASCADE)
|
||||
listing = models.BooleanField("Les places sont sur listing")
|
||||
rappel_sent = models.DateTimeField("Mail de rappel envoyé", blank=True,
|
||||
null=True)
|
||||
|
@ -135,7 +138,7 @@ class Spectacle(models.Model):
|
|||
|
||||
|
||||
class Quote(models.Model):
|
||||
spectacle = models.ForeignKey(Spectacle)
|
||||
spectacle = models.ForeignKey(Spectacle, on_delete=models.CASCADE)
|
||||
text = models.TextField('Citation')
|
||||
author = models.CharField('Auteur', max_length=200)
|
||||
|
||||
|
@ -149,7 +152,7 @@ PAYMENT_TYPES = (
|
|||
|
||||
|
||||
class Participant(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
choices = models.ManyToManyField(Spectacle,
|
||||
through="ChoixSpectacle",
|
||||
related_name="chosen_by")
|
||||
|
@ -160,7 +163,7 @@ class Participant(models.Model):
|
|||
paymenttype = models.CharField("Moyen de paiement",
|
||||
max_length=6, choices=PAYMENT_TYPES,
|
||||
blank=True)
|
||||
tirage = models.ForeignKey(Tirage)
|
||||
tirage = models.ForeignKey(Tirage, on_delete=models.CASCADE)
|
||||
choicesrevente = models.ManyToManyField(Spectacle,
|
||||
related_name="subscribed",
|
||||
blank=True)
|
||||
|
@ -176,8 +179,11 @@ DOUBLE_CHOICES = (
|
|||
|
||||
|
||||
class ChoixSpectacle(models.Model):
|
||||
participant = models.ForeignKey(Participant)
|
||||
spectacle = models.ForeignKey(Spectacle, related_name="participants")
|
||||
participant = models.ForeignKey(Participant, on_delete=models.CASCADE)
|
||||
spectacle = models.ForeignKey(
|
||||
Spectacle, on_delete=models.CASCADE,
|
||||
related_name="participants",
|
||||
)
|
||||
priority = models.PositiveIntegerField("Priorité")
|
||||
double_choice = models.CharField("Nombre de places",
|
||||
default="1", choices=DOUBLE_CHOICES,
|
||||
|
@ -204,8 +210,11 @@ class ChoixSpectacle(models.Model):
|
|||
|
||||
|
||||
class Attribution(models.Model):
|
||||
participant = models.ForeignKey(Participant)
|
||||
spectacle = models.ForeignKey(Spectacle, related_name="attribues")
|
||||
participant = models.ForeignKey(Participant, on_delete=models.CASCADE)
|
||||
spectacle = models.ForeignKey(
|
||||
Spectacle, on_delete=models.CASCADE,
|
||||
related_name="attribues",
|
||||
)
|
||||
given = models.BooleanField("Donnée", default=False)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -214,18 +223,25 @@ class Attribution(models.Model):
|
|||
|
||||
|
||||
class SpectacleRevente(models.Model):
|
||||
attribution = models.OneToOneField(Attribution,
|
||||
related_name="revente")
|
||||
attribution = models.OneToOneField(
|
||||
Attribution, on_delete=models.CASCADE,
|
||||
related_name="revente",
|
||||
)
|
||||
date = models.DateTimeField("Date de mise en vente",
|
||||
default=timezone.now)
|
||||
answered_mail = models.ManyToManyField(Participant,
|
||||
related_name="wanted",
|
||||
blank=True)
|
||||
seller = models.ForeignKey(Participant,
|
||||
related_name="original_shows",
|
||||
verbose_name="Vendeur")
|
||||
soldTo = models.ForeignKey(Participant, blank=True, null=True,
|
||||
verbose_name="Vendue à")
|
||||
seller = models.ForeignKey(
|
||||
Participant, on_delete=models.CASCADE,
|
||||
verbose_name="Vendeur",
|
||||
related_name="original_shows",
|
||||
)
|
||||
soldTo = models.ForeignKey(
|
||||
Participant, on_delete=models.CASCADE,
|
||||
verbose_name="Vendue à",
|
||||
blank=True, null=True,
|
||||
)
|
||||
|
||||
notif_sent = models.BooleanField("Notification envoyée",
|
||||
default=False)
|
||||
|
|
|
@ -32,6 +32,12 @@ urlpatterns = [
|
|||
url(r'^spectacles/unpaid/(?P<tirage_id>\d+)$',
|
||||
views.unpaid,
|
||||
name="bda-unpaid"),
|
||||
url(r'^spectacles/autocomplete$',
|
||||
views.spectacle_autocomplete,
|
||||
name="bda-spectacle-autocomplete"),
|
||||
url(r'^participants/autocomplete$',
|
||||
views.participant_autocomplete,
|
||||
name="bda-participant-autocomplete"),
|
||||
url(r'^liste-revente/(?P<tirage_id>\d+)$',
|
||||
views.list_revente,
|
||||
name="bda-liste-revente"),
|
||||
|
|
25
bda/views.py
25
bda/views.py
|
@ -33,6 +33,8 @@ from bda.forms import (
|
|||
InscriptionInlineFormSet,
|
||||
)
|
||||
|
||||
from utils.views.autocomplete import Select2QuerySetView
|
||||
|
||||
|
||||
@cof_required
|
||||
def etat_places(request, tirage_id):
|
||||
|
@ -813,3 +815,26 @@ def catalogue(request, request_type):
|
|||
return JsonResponse(data_return, safe=False)
|
||||
# Si la requête n'est pas de la forme attendue, on quitte avec une erreur
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
|
||||
##
|
||||
# Autocomplete views
|
||||
#
|
||||
# https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#create-an-autocomplete-view
|
||||
##
|
||||
|
||||
|
||||
class ParticipantAutocomplete(Select2QuerySetView):
|
||||
model = Participant
|
||||
search_fields = ('user__username', 'user__first_name', 'user__last_name')
|
||||
|
||||
|
||||
participant_autocomplete = buro_required(ParticipantAutocomplete.as_view())
|
||||
|
||||
|
||||
class SpectacleAutocomplete(Select2QuerySetView):
|
||||
model = Spectacle
|
||||
search_fields = ('title',)
|
||||
|
||||
|
||||
spectacle_autocomplete = buro_required(SpectacleAutocomplete.as_view())
|
||||
|
|
|
@ -57,17 +57,22 @@ BASE_DIR = os.path.dirname(
|
|||
# Application definition
|
||||
INSTALLED_APPS = [
|
||||
'gestioncof',
|
||||
|
||||
# Must be before 'django.contrib.admin'.
|
||||
# https://django-autocomplete-light.readthedocs.io/en/master/install.html
|
||||
'dal',
|
||||
'dal_select2',
|
||||
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'grappelli',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.admindocs',
|
||||
|
||||
'bda',
|
||||
'autocomplete_light',
|
||||
'captcha',
|
||||
'django_cas_ng',
|
||||
'bootstrapform',
|
||||
|
@ -96,7 +101,7 @@ INSTALLED_APPS = [
|
|||
'kfet.cms',
|
||||
]
|
||||
|
||||
MIDDLEWARE_CLASSES = [
|
||||
MIDDLEWARE = [
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
|
@ -124,9 +129,9 @@ TEMPLATES = [
|
|||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'django.core.context_processors.i18n',
|
||||
'django.core.context_processors.media',
|
||||
'django.core.context_processors.static',
|
||||
'django.template.context_processors.i18n',
|
||||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.static',
|
||||
'wagtailmenus.context_processors.wagtailmenus',
|
||||
'djconfig.context_processors.config',
|
||||
'gestioncof.shared.context_processor',
|
||||
|
|
|
@ -4,7 +4,7 @@ The settings that are not listed here are imported from .common
|
|||
"""
|
||||
|
||||
from .common import * # NOQA
|
||||
from .common import INSTALLED_APPS, MIDDLEWARE_CLASSES
|
||||
from .common import INSTALLED_APPS, MIDDLEWARE
|
||||
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
|
@ -37,10 +37,11 @@ def show_toolbar(request):
|
|||
return DEBUG
|
||||
|
||||
INSTALLED_APPS += ["debug_toolbar", "debug_panel"]
|
||||
MIDDLEWARE_CLASSES = (
|
||||
["debug_panel.middleware.DebugPanelMiddleware"]
|
||||
+ MIDDLEWARE_CLASSES
|
||||
)
|
||||
|
||||
MIDDLEWARE = [
|
||||
"debug_panel.middleware.DebugPanelMiddleware"
|
||||
] + MIDDLEWARE
|
||||
|
||||
DEBUG_TOOLBAR_CONFIG = {
|
||||
'SHOW_TOOLBAR_CALLBACK': show_toolbar,
|
||||
}
|
||||
|
|
25
cof/urls.py
25
cof/urls.py
|
@ -4,8 +4,6 @@
|
|||
Fichier principal de configuration des urls du projet GestioCOF
|
||||
"""
|
||||
|
||||
import autocomplete_light
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls.static import static
|
||||
|
@ -24,7 +22,6 @@ from gestioncof.urls import export_patterns, petitcours_patterns, \
|
|||
clubs_patterns
|
||||
from gestioncof.autocomplete import autocomplete
|
||||
|
||||
autocomplete_light.autodiscover()
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -49,18 +46,22 @@ urlpatterns = [
|
|||
name="cof-denied"),
|
||||
url(r'^cas/login$', django_cas_views.login, name="cas_login_view"),
|
||||
url(r'^cas/logout$', django_cas_views.logout),
|
||||
url(r'^outsider/login$', gestioncof_views.login_ext),
|
||||
url(r'^outsider/login$', gestioncof_views.login_ext,
|
||||
name="ext_login_view"),
|
||||
url(r'^outsider/logout$', django_views.logout, {'next_page': 'home'}),
|
||||
url(r'^login$', gestioncof_views.login, name="cof-login"),
|
||||
url(r'^logout$', gestioncof_views.logout, name="cof-logout"),
|
||||
# Infos persos
|
||||
url(r'^profile$', gestioncof_views.profile),
|
||||
url(r'^outsider/password-change$', django_views.password_change),
|
||||
url(r'^profile$', gestioncof_views.profile,
|
||||
name='profile'),
|
||||
url(r'^outsider/password-change$', django_views.password_change,
|
||||
name='password_change'),
|
||||
url(r'^outsider/password-change-done$',
|
||||
django_views.password_change_done,
|
||||
name='password_change_done'),
|
||||
# Inscription d'un nouveau membre
|
||||
url(r'^registration$', gestioncof_views.registration),
|
||||
url(r'^registration$', gestioncof_views.registration,
|
||||
name='registration'),
|
||||
url(r'^registration/clipper/(?P<login_clipper>[\w-]+)/'
|
||||
r'(?P<fullname>.*)$',
|
||||
gestioncof_views.registration_form2, name="clipper-registration"),
|
||||
|
@ -70,7 +71,8 @@ urlpatterns = [
|
|||
name="empty-registration"),
|
||||
# Autocompletion
|
||||
url(r'^autocomplete/registration$', autocomplete),
|
||||
url(r'^autocomplete/', include('autocomplete_light.urls')),
|
||||
url(r'^user/autocomplete$', gestioncof_views.user_autocomplete,
|
||||
name='cof-user-autocomplete'),
|
||||
# Interface admin
|
||||
url(r'^admin/logout/', gestioncof_views.logout),
|
||||
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
|
@ -78,10 +80,11 @@ urlpatterns = [
|
|||
csv_views.admin_list_export,
|
||||
{'fields': ['username', ]}),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^grappelli/', include('grappelli.urls')),
|
||||
# Liens utiles du COF et du BdA
|
||||
url(r'^utile_cof$', gestioncof_views.utile_cof),
|
||||
url(r'^utile_bda$', gestioncof_views.utile_bda),
|
||||
url(r'^utile_cof$', gestioncof_views.utile_cof,
|
||||
name='utile_cof'),
|
||||
url(r'^utile_bda$', gestioncof_views.utile_bda,
|
||||
name='utile_bda'),
|
||||
url(r'^utile_bda/bda_diff$', gestioncof_views.liste_bdadiff),
|
||||
url(r'^utile_cof/diff_cof$', gestioncof_views.liste_diffcof),
|
||||
url(r'^utile_bda/bda_revente$', gestioncof_views.liste_bdarevente),
|
||||
|
|
|
@ -13,7 +13,7 @@ from django.core.urlresolvers import reverse
|
|||
from django.utils.safestring import mark_safe
|
||||
from django.db.models import Q
|
||||
|
||||
import autocomplete_light
|
||||
from dal.autocomplete import ModelSelect2
|
||||
|
||||
|
||||
def add_link_field(target_model='', field='', link_text=str,
|
||||
|
@ -217,8 +217,16 @@ def user_str(self):
|
|||
User.__str__ = user_str
|
||||
|
||||
|
||||
class EventRegistrationAdminForm(forms.ModelForm):
|
||||
class Meta:
|
||||
widgets = {
|
||||
'user': ModelSelect2(url='cof-user-autocomplete'),
|
||||
}
|
||||
|
||||
|
||||
class EventRegistrationAdmin(admin.ModelAdmin):
|
||||
form = autocomplete_light.modelform_factory(EventRegistration, exclude=[])
|
||||
form = EventRegistrationAdminForm
|
||||
|
||||
list_display = ('__str__', 'event', 'user', 'paid')
|
||||
list_filter = ('paid',)
|
||||
search_fields = ('user__username', 'user__first_name', 'user__last_name',
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import autocomplete_light
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
autocomplete_light.register(
|
||||
User, search_fields=('username', 'first_name', 'last_name'),
|
||||
attrs={'placeholder': 'membre...'}
|
||||
)
|
|
@ -48,7 +48,7 @@ class Migration(migrations.Migration):
|
|||
('is_buro', models.BooleanField(default=False, verbose_name=b'Membre du Bur\xc3\xb4')),
|
||||
('petits_cours_accept', models.BooleanField(default=False, verbose_name=b'Recevoir des petits cours')),
|
||||
('petits_cours_remarques', models.TextField(default=b'', verbose_name='Remarques et pr\xe9cisions pour les petits cours', blank=True)),
|
||||
('user', models.OneToOneField(related_name='profile', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(related_name='profile', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Profil COF',
|
||||
|
@ -91,7 +91,7 @@ class Migration(migrations.Migration):
|
|||
('name', models.CharField(max_length=200, verbose_name=b'Champ')),
|
||||
('fieldtype', models.CharField(default=b'text', max_length=10, verbose_name=b'Type', choices=[(b'text', 'Texte long'), (b'char', 'Texte court')])),
|
||||
('default', models.TextField(verbose_name=b'Valeur par d\xc3\xa9faut', blank=True)),
|
||||
('event', models.ForeignKey(related_name='commentfields', to='gestioncof.Event')),
|
||||
('event', models.ForeignKey(related_name='commentfields', to='gestioncof.Event', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Champ',
|
||||
|
@ -102,7 +102,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('content', models.TextField(null=True, verbose_name=b'Contenu', blank=True)),
|
||||
('commentfield', models.ForeignKey(related_name='values', to='gestioncof.EventCommentField')),
|
||||
('commentfield', models.ForeignKey(related_name='values', to='gestioncof.EventCommentField', on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -111,7 +111,7 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('name', models.CharField(max_length=200, verbose_name=b'Option')),
|
||||
('multi_choices', models.BooleanField(default=False, verbose_name=b'Choix multiples')),
|
||||
('event', models.ForeignKey(related_name='options', to='gestioncof.Event')),
|
||||
('event', models.ForeignKey(related_name='options', to='gestioncof.Event', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Option',
|
||||
|
@ -122,7 +122,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('value', models.CharField(max_length=200, verbose_name=b'Valeur')),
|
||||
('event_option', models.ForeignKey(related_name='choices', to='gestioncof.EventOption')),
|
||||
('event_option', models.ForeignKey(related_name='choices', to='gestioncof.EventOption', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Choix',
|
||||
|
@ -133,10 +133,10 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('paid', models.BooleanField(default=False, verbose_name=b'A pay\xc3\xa9')),
|
||||
('event', models.ForeignKey(to='gestioncof.Event')),
|
||||
('event', models.ForeignKey(to='gestioncof.Event', on_delete=models.CASCADE)),
|
||||
('filledcomments', models.ManyToManyField(to='gestioncof.EventCommentField', through='gestioncof.EventCommentValue')),
|
||||
('options', models.ManyToManyField(to='gestioncof.EventOptionChoice')),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Inscription',
|
||||
|
@ -240,7 +240,7 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('question', models.CharField(max_length=200, verbose_name=b'Question')),
|
||||
('multi_answers', models.BooleanField(default=False, verbose_name=b'Choix multiples')),
|
||||
('survey', models.ForeignKey(related_name='questions', to='gestioncof.Survey')),
|
||||
('survey', models.ForeignKey(related_name='questions', to='gestioncof.Survey', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Question',
|
||||
|
@ -251,7 +251,7 @@ class Migration(migrations.Migration):
|
|||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('answer', models.CharField(max_length=200, verbose_name=b'R\xc3\xa9ponse')),
|
||||
('survey_question', models.ForeignKey(related_name='answers', to='gestioncof.SurveyQuestion')),
|
||||
('survey_question', models.ForeignKey(related_name='answers', to='gestioncof.SurveyQuestion', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'R\xe9ponse',
|
||||
|
@ -265,12 +265,12 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='surveyanswer',
|
||||
name='survey',
|
||||
field=models.ForeignKey(to='gestioncof.Survey'),
|
||||
field=models.ForeignKey(to='gestioncof.Survey', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='surveyanswer',
|
||||
name='user',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursdemande',
|
||||
|
@ -280,47 +280,47 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='petitcoursdemande',
|
||||
name='traitee_par',
|
||||
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursattributioncounter',
|
||||
name='matiere',
|
||||
field=models.ForeignKey(verbose_name='Matiere', to='gestioncof.PetitCoursSubject'),
|
||||
field=models.ForeignKey(verbose_name='Matiere', to='gestioncof.PetitCoursSubject', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursattributioncounter',
|
||||
name='user',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursattribution',
|
||||
name='demande',
|
||||
field=models.ForeignKey(verbose_name='Demande', to='gestioncof.PetitCoursDemande'),
|
||||
field=models.ForeignKey(verbose_name='Demande', to='gestioncof.PetitCoursDemande', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursattribution',
|
||||
name='matiere',
|
||||
field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject'),
|
||||
field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursattribution',
|
||||
name='user',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursability',
|
||||
name='matiere',
|
||||
field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject'),
|
||||
field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='petitcoursability',
|
||||
name='user',
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='eventcommentvalue',
|
||||
name='registration',
|
||||
field=models.ForeignKey(related_name='comments', to='gestioncof.EventRegistration'),
|
||||
field=models.ForeignKey(related_name='comments', to='gestioncof.EventRegistration', on_delete=models.CASCADE),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='surveyanswer',
|
||||
|
|
|
@ -23,7 +23,8 @@ class Migration(migrations.Migration):
|
|||
('subscribe_to_events', models.BooleanField(default=True)),
|
||||
('subscribe_to_my_shows', models.BooleanField(default=True)),
|
||||
('other_shows', models.ManyToManyField(to='bda.Spectacle')),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
|
|
|
@ -49,7 +49,10 @@ class CofProfile(models.Model):
|
|||
(COTIZ_GRATIS, _("Gratuit")),
|
||||
)
|
||||
|
||||
user = models.OneToOneField(User, related_name="profile")
|
||||
user = models.OneToOneField(
|
||||
User, on_delete=models.CASCADE,
|
||||
related_name="profile",
|
||||
)
|
||||
login_clipper = models.CharField(
|
||||
"Login clipper", max_length=32, blank=True
|
||||
)
|
||||
|
@ -130,7 +133,10 @@ class Event(models.Model):
|
|||
|
||||
|
||||
class EventCommentField(models.Model):
|
||||
event = models.ForeignKey(Event, related_name="commentfields")
|
||||
event = models.ForeignKey(
|
||||
Event, on_delete=models.CASCADE,
|
||||
related_name="commentfields",
|
||||
)
|
||||
name = models.CharField("Champ", max_length=200)
|
||||
fieldtype = models.CharField("Type", max_length=10,
|
||||
choices=TYPE_COMMENT_FIELD, default="text")
|
||||
|
@ -144,9 +150,14 @@ class EventCommentField(models.Model):
|
|||
|
||||
|
||||
class EventCommentValue(models.Model):
|
||||
commentfield = models.ForeignKey(EventCommentField, related_name="values")
|
||||
registration = models.ForeignKey("EventRegistration",
|
||||
related_name="comments")
|
||||
commentfield = models.ForeignKey(
|
||||
EventCommentField, on_delete=models.CASCADE,
|
||||
related_name="values",
|
||||
)
|
||||
registration = models.ForeignKey(
|
||||
"EventRegistration", on_delete=models.CASCADE,
|
||||
related_name="comments",
|
||||
)
|
||||
content = models.TextField("Contenu", blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -154,7 +165,10 @@ class EventCommentValue(models.Model):
|
|||
|
||||
|
||||
class EventOption(models.Model):
|
||||
event = models.ForeignKey(Event, related_name="options")
|
||||
event = models.ForeignKey(
|
||||
Event, on_delete=models.CASCADE,
|
||||
related_name="options",
|
||||
)
|
||||
name = models.CharField("Option", max_length=200)
|
||||
multi_choices = models.BooleanField("Choix multiples", default=False)
|
||||
|
||||
|
@ -166,7 +180,10 @@ class EventOption(models.Model):
|
|||
|
||||
|
||||
class EventOptionChoice(models.Model):
|
||||
event_option = models.ForeignKey(EventOption, related_name="choices")
|
||||
event_option = models.ForeignKey(
|
||||
EventOption, on_delete=models.CASCADE,
|
||||
related_name="choices",
|
||||
)
|
||||
value = models.CharField("Valeur", max_length=200)
|
||||
|
||||
class Meta:
|
||||
|
@ -178,8 +195,8 @@ class EventOptionChoice(models.Model):
|
|||
|
||||
|
||||
class EventRegistration(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
event = models.ForeignKey(Event)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
event = models.ForeignKey(Event, on_delete=models.CASCADE)
|
||||
options = models.ManyToManyField(EventOptionChoice)
|
||||
filledcomments = models.ManyToManyField(EventCommentField,
|
||||
through=EventCommentValue)
|
||||
|
@ -207,7 +224,10 @@ class Survey(models.Model):
|
|||
|
||||
|
||||
class SurveyQuestion(models.Model):
|
||||
survey = models.ForeignKey(Survey, related_name="questions")
|
||||
survey = models.ForeignKey(
|
||||
Survey, on_delete=models.CASCADE,
|
||||
related_name="questions",
|
||||
)
|
||||
question = models.CharField("Question", max_length=200)
|
||||
multi_answers = models.BooleanField("Choix multiples", default=False)
|
||||
|
||||
|
@ -219,7 +239,10 @@ class SurveyQuestion(models.Model):
|
|||
|
||||
|
||||
class SurveyQuestionAnswer(models.Model):
|
||||
survey_question = models.ForeignKey(SurveyQuestion, related_name="answers")
|
||||
survey_question = models.ForeignKey(
|
||||
SurveyQuestion, on_delete=models.CASCADE,
|
||||
related_name="answers",
|
||||
)
|
||||
answer = models.CharField("Réponse", max_length=200)
|
||||
|
||||
class Meta:
|
||||
|
@ -230,8 +253,8 @@ class SurveyQuestionAnswer(models.Model):
|
|||
|
||||
|
||||
class SurveyAnswer(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
survey = models.ForeignKey(Survey)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
|
||||
answers = models.ManyToManyField(SurveyQuestionAnswer,
|
||||
related_name="selected_by")
|
||||
|
||||
|
@ -247,7 +270,7 @@ class SurveyAnswer(models.Model):
|
|||
|
||||
class CalendarSubscription(models.Model):
|
||||
token = models.UUIDField()
|
||||
user = models.OneToOneField(User)
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||
other_shows = models.ManyToManyField(Spectacle)
|
||||
subscribe_to_events = models.BooleanField(default=True)
|
||||
subscribe_to_my_shows = models.BooleanField(default=True)
|
||||
|
|
|
@ -35,8 +35,11 @@ class PetitCoursSubject(models.Model):
|
|||
|
||||
|
||||
class PetitCoursAbility(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière"))
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
matiere = models.ForeignKey(
|
||||
PetitCoursSubject, on_delete=models.CASCADE,
|
||||
verbose_name=_("Matière"),
|
||||
)
|
||||
niveau = models.CharField(_("Niveau"),
|
||||
choices=LEVELS_CHOICES,
|
||||
max_length=choices_length(LEVELS_CHOICES))
|
||||
|
@ -84,7 +87,10 @@ class PetitCoursDemande(models.Model):
|
|||
remarques = models.TextField(_("Remarques et précisions"), blank=True)
|
||||
|
||||
traitee = models.BooleanField(_("Traitée"), default=False)
|
||||
traitee_par = models.ForeignKey(User, blank=True, null=True)
|
||||
traitee_par = models.ForeignKey(
|
||||
User, on_delete=models.CASCADE,
|
||||
blank=True, null=True,
|
||||
)
|
||||
processed = models.DateTimeField(_("Date de traitement"),
|
||||
blank=True, null=True)
|
||||
created = models.DateTimeField(_("Date de création"), auto_now_add=True)
|
||||
|
@ -126,9 +132,15 @@ class PetitCoursDemande(models.Model):
|
|||
|
||||
|
||||
class PetitCoursAttribution(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
demande = models.ForeignKey(PetitCoursDemande, verbose_name=_("Demande"))
|
||||
matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière"))
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
demande = models.ForeignKey(
|
||||
PetitCoursDemande, on_delete=models.CASCADE,
|
||||
verbose_name=_("Demande"),
|
||||
)
|
||||
matiere = models.ForeignKey(
|
||||
PetitCoursSubject, on_delete=models.CASCADE,
|
||||
verbose_name=_("Matière"),
|
||||
)
|
||||
date = models.DateTimeField(_("Date d'attribution"), auto_now_add=True)
|
||||
rank = models.IntegerField("Rang dans l'email")
|
||||
selected = models.BooleanField(_("Sélectionné par le demandeur"),
|
||||
|
@ -145,8 +157,11 @@ class PetitCoursAttribution(models.Model):
|
|||
|
||||
|
||||
class PetitCoursAttributionCounter(models.Model):
|
||||
user = models.ForeignKey(User)
|
||||
matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matiere"))
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
matiere = models.ForeignKey(
|
||||
PetitCoursSubject, on_delete=models.CASCADE,
|
||||
verbose_name=_("Matiere"),
|
||||
)
|
||||
count = models.IntegerField("Nombre d'envois", default=0)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from custommail.shortcuts import render_custom_mail
|
||||
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
|
@ -13,6 +12,7 @@ from django.conf import settings
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from gestioncof.models import CofProfile
|
||||
from gestioncof.petits_cours_models import (
|
||||
|
@ -287,7 +287,7 @@ def _traitement_post(request, demande):
|
|||
attrib.save()
|
||||
demande.traitee = True
|
||||
demande.traitee_par = request.user
|
||||
demande.processed = datetime.now()
|
||||
demande.processed = timezone.now()
|
||||
demande.save()
|
||||
return render(request,
|
||||
"gestioncof/traitement_demande_petit_cours_success.html",
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block extrahead %}
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
|
||||
{% include 'autocomplete_light/static.html' %}
|
||||
{% endblock %}
|
|
@ -1,78 +0,0 @@
|
|||
{% extends "admin/base_site.html" %}
|
||||
|
||||
<!-- LOADING -->
|
||||
{% load i18n grp_tags log %}
|
||||
|
||||
<!-- JAVASCRIPTS -->
|
||||
{% block javascripts %}
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
<!-- COLTYPE/BODYCLASS-- >
|
||||
{% block bodyclass %}dashboard{% endblock %}
|
||||
{% block content-class %}content-grid{% endblock %}
|
||||
|
||||
<!-- BREADCRUMBS -->
|
||||
{% block breadcrumbs %}
|
||||
<ul class="grp-horizontal-list">
|
||||
<li>{% trans "Home" %}</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% block content_title %}
|
||||
{% if title %}
|
||||
<header><h1>{{ title }}</h1></header>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
<!-- CONTENT -->
|
||||
{% block content %}
|
||||
<div class="g-d-c">
|
||||
<div class="g-d-12 g-d-f">
|
||||
|
||||
{% for app in app_list %}
|
||||
<div class="grp-module" id="app_{{ app.name|lower }}">
|
||||
<h2><a href="{{ app.app_url }}" class="grp-section">{% trans app.name %}</a></h2>
|
||||
{% for model in app.models %}
|
||||
<div class="grp-row">
|
||||
{% if model.perms.change %}<a href="{{ model.admin_url }}"><strong>{{ model.name }}</strong></a>{% else %}<span><strong>{{ model.name }}</strong></span>{% endif %}
|
||||
{% if model.perms.add or model.perms.change %}
|
||||
<ul class="grp-actions">
|
||||
{% if model.perms.add %}<li class="grp-add-link"><a href="{{ model.admin_url }}add/">{% trans 'Add' %}</a></li>{% endif %}
|
||||
{% if model.perms.change %}<li class="grp-change-link"><a href="{{ model.admin_url }}">{% trans 'Change' %}</a></li>{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% empty %}
|
||||
<p>{% trans "You don´t have permission to edit anything." %}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="g-d-6 g-d-l">
|
||||
<div class="grp-module" id="grp-recent-actions-module">
|
||||
<h2>{% trans 'Recent Actions' %}</h2>
|
||||
<div class="grp-module">
|
||||
<h3>{% trans 'My Actions' %}</h3>
|
||||
{% get_admin_log 20 as admin_log for_user user %}
|
||||
{% if not admin_log %}
|
||||
<p>{% trans 'None available' %}</p>
|
||||
{% else %}
|
||||
<ul class="grp-listing-small">
|
||||
{% for entry in admin_log %}
|
||||
<li class="grp-row{% if entry.is_addition %} grp-add-link{% endif %}{% if entry.is_change %} grp-change-link{% endif %}{% if entry.is_deletion %} grp-delete-link{% endif %}">
|
||||
{% if entry.is_deletion %}
|
||||
<span>{{ entry.object_repr }}</span>
|
||||
{% else %}
|
||||
<a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
|
||||
{% endif %}
|
||||
<span class="grp-font-color-quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
{% block content %}
|
||||
<header>
|
||||
<div class="container banner">
|
||||
<a href="{% url "gestioncof.views.home" %}">
|
||||
<a href="{% url "home" %}">
|
||||
<h1>GestioCOF</h1>
|
||||
{% block homelink %}
|
||||
<span class="glyphicon glyphicon-home" aria-hidden=true></span>
|
||||
|
@ -11,7 +11,7 @@
|
|||
</a>
|
||||
<div class="secondary">
|
||||
<span class="hidden-xxs"> | </span>
|
||||
<span><a href="{% url "gestioncof.views.logout" %}">Se déconnecter <span class="glyphicon glyphicon-log-out"></span></a></span>
|
||||
<span><a href="{% url "cof-logout" %}">Se déconnecter <span class="glyphicon glyphicon-log-out"></span></a></span>
|
||||
</div>
|
||||
<h2 class="member-status">{% if user.first_name %}{{ user.first_name }}{% else %}<tt>{{ user.username }}</tt>{% endif %}, {% if user.profile.is_cof %}<tt class="user-is-cof">au COF{% else %}<tt class="user-is-not-cof">non-COF{% endif %}</tt></h2>
|
||||
</div><!-- /.container -->
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{% if event.details %}
|
||||
<p>{{ event.details }}</p>
|
||||
{% endif %}
|
||||
<form method="post" action="{% url 'gestioncof.views.event' event.id %}">
|
||||
<form method="post" action="{% url 'event.details' event.id %}">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" class="btn-submit" value="Enregistrer" />
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<div class="hm-block">
|
||||
<ul>
|
||||
{% for event in open_events %}
|
||||
<li><a href="{% url "gestioncof.views.event" event.id %}">{{ event.title }}</a></li>
|
||||
<li><a href="{% url "event.details" event.id %}">{{ event.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -24,7 +24,7 @@
|
|||
<div class="hm-block">
|
||||
<ul>
|
||||
{% for survey in open_surveys %}
|
||||
<li><a href="{% url "gestioncof.views.survey" survey.id %}">{{ survey.title }}</a></li>
|
||||
<li><a href="{% url "survey.details" survey.id %}">{{ survey.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -69,11 +69,11 @@
|
|||
<h3 class="block-title">Divers<span class="pull-right glyphicon glyphicon-question-sign"></span></h3>
|
||||
<div class="hm-block">
|
||||
<ul>
|
||||
<li><a href="{% url "gestioncof.views.calendar" %}">Calendrier dynamique</a></li>
|
||||
<li><a href="{% url "calendar" %}">Calendrier dynamique</a></li>
|
||||
{% if user.profile.is_cof %}<li><a href="{% url "petits-cours-inscription" %}">Inscription pour donner des petits cours</a></li>{% endif %}
|
||||
|
||||
<li><a href="{% url "gestioncof.views.profile" %}">Éditer mon profil</a></li>
|
||||
{% if not user.profile.login_clipper %}<li><a href="{% url "django.contrib.auth.views.password_change" %}">Changer mon mot de passe</a></li>{% endif %}
|
||||
<li><a href="{% url "profile" %}">Éditer mon profil</a></li>
|
||||
{% if not user.profile.login_clipper %}<li><a href="{% url "password_change" %}">Changer mon mot de passe</a></li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -86,16 +86,16 @@
|
|||
<h4>Général</h4>
|
||||
<li><a href="{% url "admin:index" %}">Administration générale</a></li>
|
||||
<li><a href="{% url "petits-cours-demandes-list" %}">Demandes de petits cours</a></li>
|
||||
<li><a href="{% url "gestioncof.views.registration" %}">Inscription d'un nouveau membre</a></li>
|
||||
<li><a href="{% url "registration" %}">Inscription d'un nouveau membre</a></li>
|
||||
<li><a href="{% url "liste-clubs" %}">Gestion des clubs</a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<h4>Évènements & Sondages</h4>
|
||||
{% for event in events %}
|
||||
<li><a href="{% url "gestioncof.views.event_status" event.id %}">Événement : {{ event.title }}</a></li>
|
||||
<li><a href="{% url "event.details.status" event.id %}">Événement : {{ event.title }}</a></li>
|
||||
{% endfor %}
|
||||
{% for survey in surveys %}
|
||||
<li><a href="{% url "gestioncof.views.survey_status" survey.id %}">Sondage : {{ survey.title }}</a></li>
|
||||
<li><a href="{% url "survey.details.status" survey.id %}">Sondage : {{ survey.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -120,8 +120,8 @@
|
|||
<h3 class="block-title">Liens utiles<span class="pull-right glyphicon glyphicon-link"></span></h3>
|
||||
<div class="hm-block">
|
||||
<ul>
|
||||
<li><a href="{% url "gestioncof.views.utile_cof" %}">Liens utiles du COF</a></li>
|
||||
<li><a href="{% url "gestioncof.views.utile_bda" %}">Liens utiles BdA</a></li>
|
||||
<li><a href="{% url "utile_cof" %}">Liens utiles du COF</a></li>
|
||||
<li><a href="{% url "utile_bda" %}">Liens utiles BdA</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<p class="error">Identifiants incorrects.</p>
|
||||
{% endif %}
|
||||
<form class="form-horizontal" method="post"
|
||||
action="{% url 'gestioncof.views.login_ext' %}?next={{ next|urlencode }}">
|
||||
action="{% url 'ext_login_view' %}?next={{ next|urlencode }}">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<input class="form-control" id="id_username" maxlength="254" name="username" type="text" placeholder="Nom d'utilisateur">
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
<div class="container-fluid">
|
||||
<div class="row" style="margin:0;">
|
||||
<a aria-label="Compte clipper"
|
||||
href="{% url 'django_cas_ng.views.login' %}?next={{ next|urlencode }}">
|
||||
href="{% url 'cas_login_view' %}?next={{ next|urlencode }}">
|
||||
<div class="col-xs-12 col-sm-6" id="login_clipper">
|
||||
Compte clipper
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Extérieur"
|
||||
href="{% url 'gestioncof.views.login_ext' %}?next={{ next|urlencode }}">
|
||||
href="{% url 'ext_login_view' %}?next={{ next|urlencode }}">
|
||||
<div class="col-xs-12 col-sm-6" id="login_outsider">
|
||||
Extérieur
|
||||
</div>
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
|
||||
{% block realcontent %}
|
||||
<h2>Mot de passe modifié avec succès !</h2>
|
||||
<h3><a href="{% url "gestioncof.views.home" %}">Retour au menu principal</a></h3>
|
||||
<h3><a href="{% url "home" %}">Retour au menu principal</a></h3>
|
||||
{% endblock %}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
{% block realcontent %}
|
||||
<h2>Changement de mot de passe</h2>
|
||||
<form class="form-horizontal" method="post" action="{% url 'django.contrib.auth.views.password_change' %}">
|
||||
<form class="form-horizontal" method="post" action="{% url 'password_change' %}">
|
||||
{% csrf_token %}
|
||||
{{ form | bootstrap }}
|
||||
<input type="submit" class="btn btn-primary pull-right" value="Changer" />
|
||||
|
|
|
@ -36,19 +36,23 @@ petitcours_patterns = [
|
|||
]
|
||||
|
||||
surveys_patterns = [
|
||||
url(r'^(?P<survey_id>\d+)/status$', views.survey_status),
|
||||
url(r'^(?P<survey_id>\d+)$', views.survey),
|
||||
url(r'^(?P<survey_id>\d+)/status$', views.survey_status,
|
||||
name='survey.details.status'),
|
||||
url(r'^(?P<survey_id>\d+)$', views.survey,
|
||||
name='survey.details'),
|
||||
]
|
||||
|
||||
events_patterns = [
|
||||
url(r'^(?P<event_id>\d+)$', views.event),
|
||||
url(r'^(?P<event_id>\d+)/status$', views.event_status),
|
||||
url(r'^(?P<event_id>\d+)$', views.event,
|
||||
name='event.details'),
|
||||
url(r'^(?P<event_id>\d+)/status$', views.event_status,
|
||||
name='event.details.status'),
|
||||
]
|
||||
|
||||
calendar_patterns = [
|
||||
url(r'^subscription$', 'gestioncof.views.calendar'),
|
||||
url(r'^(?P<token>[a-z0-9-]+)/calendar.ics$',
|
||||
'gestioncof.views.calendar_ics')
|
||||
url(r'^subscription$', views.calendar,
|
||||
name='calendar'),
|
||||
url(r'^(?P<token>[a-z0-9-]+)/calendar.ics$', views.calendar_ics)
|
||||
]
|
||||
|
||||
clubs_patterns = [
|
||||
|
|
|
@ -20,6 +20,8 @@ from django.contrib import messages
|
|||
|
||||
from django_cas_ng.views import logout as cas_logout_view
|
||||
|
||||
from utils.views.autocomplete import Select2QuerySetView
|
||||
|
||||
from gestioncof.models import Survey, SurveyAnswer, SurveyQuestion, \
|
||||
SurveyQuestionAnswer
|
||||
from gestioncof.models import Event, EventRegistration, EventOption, \
|
||||
|
@ -54,8 +56,8 @@ def home(request):
|
|||
|
||||
|
||||
def login(request):
|
||||
if request.user.is_authenticated():
|
||||
return redirect("gestioncof.views.home")
|
||||
if request.user.is_authenticated:
|
||||
return redirect("home")
|
||||
context = {}
|
||||
if request.method == "GET" and 'next' in request.GET:
|
||||
context['next'] = request.GET['next']
|
||||
|
@ -786,3 +788,18 @@ class ConfigUpdate(FormView):
|
|||
def form_valid(self, form):
|
||||
form.save()
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
##
|
||||
# Autocomplete views
|
||||
#
|
||||
# https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#create-an-autocomplete-view
|
||||
##
|
||||
|
||||
|
||||
class UserAutocomplete(Select2QuerySetView):
|
||||
model = User
|
||||
search_fields = ('username', 'first_name', 'last_name')
|
||||
|
||||
|
||||
user_autocomplete = buro_required(UserAutocomplete.as_view())
|
||||
|
|
|
@ -13,8 +13,11 @@ class TemporaryAuthMiddleware:
|
|||
values from CofProfile and Account of this user.
|
||||
|
||||
"""
|
||||
def process_request(self, request):
|
||||
if request.user.is_authenticated():
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
if request.user.is_authenticated:
|
||||
# avoid multiple db accesses in views and templates
|
||||
request.user = (
|
||||
User.objects
|
||||
|
@ -31,6 +34,8 @@ class TemporaryAuthMiddleware:
|
|||
request.real_user = request.user
|
||||
request.user = temp_request_user
|
||||
|
||||
return self.get_response(request)
|
||||
|
||||
def get_kfet_password(self, request):
|
||||
return (
|
||||
request.META.get('HTTP_KFETPASSWORD') or
|
||||
|
|
|
@ -286,6 +286,8 @@ class TemporaryAuthTests(TestCase):
|
|||
|
||||
self.factory = RequestFactory()
|
||||
|
||||
self.middleware = TemporaryAuthMiddleware(mock.Mock())
|
||||
|
||||
user1_acc = Account(trigramme='000')
|
||||
user1_acc.change_pwd('kfet_user1')
|
||||
user1_acc.save({'username': 'user1'})
|
||||
|
@ -312,7 +314,7 @@ class TemporaryAuthTests(TestCase):
|
|||
request = self.factory.get('/', HTTP_KFETPASSWORD='kfet_user2')
|
||||
request.user = self.user1
|
||||
|
||||
TemporaryAuthMiddleware().process_request(request)
|
||||
self.middleware(request)
|
||||
|
||||
self.assertEqual(request.user, self.user2)
|
||||
self.assertEqual(request.real_user, self.user1)
|
||||
|
@ -325,7 +327,7 @@ class TemporaryAuthTests(TestCase):
|
|||
request = self.factory.post('/', {'KFETPASSWORD': 'kfet_user2'})
|
||||
request.user = self.user1
|
||||
|
||||
TemporaryAuthMiddleware().process_request(request)
|
||||
self.middleware(request)
|
||||
|
||||
self.assertEqual(request.user, self.user2)
|
||||
self.assertEqual(request.real_user, self.user1)
|
||||
|
@ -337,7 +339,7 @@ class TemporaryAuthTests(TestCase):
|
|||
request = self.factory.post('/', {'KFETPASSWORD': 'invalid'})
|
||||
request.user = self.user1
|
||||
|
||||
TemporaryAuthMiddleware().process_request(request)
|
||||
self.middleware(request)
|
||||
|
||||
self.assertEqual(request.user, self.user1)
|
||||
self.assertFalse(hasattr(request, 'real_user'))
|
||||
|
|
|
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='KFetPage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(serialize=False, primary_key=True, parent_link=True, auto_created=True, to='wagtailcore.Page')),
|
||||
('page_ptr', models.OneToOneField(serialize=False, primary_key=True, parent_link=True, auto_created=True, to='wagtailcore.Page', on_delete=models.CASCADE)),
|
||||
('no_header', models.BooleanField(verbose_name='Sans en-tête', help_text="Coché, l'en-tête (avec le titre) de la page n'est pas affiché.", default=False)),
|
||||
('content', wagtail.wagtailcore.fields.StreamField((('rich', wagtail.wagtailcore.blocks.RichTextBlock(label='Éditeur')), ('carte', kfet.cms.models.MenuBlock()), ('group_team', wagtail.wagtailcore.blocks.StructBlock((('show_only', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Nombre initial de membres affichés. Laisser vide pour tou-te-s les afficher.', required=False, label='Montrer seulement')), ('members', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailsnippets.blocks.SnippetChooserBlock(kfet.cms.models.MemberTeam), classname='team-group', label='K-Fêt-eux-ses'))))), ('group', wagtail.wagtailcore.blocks.StreamBlock((('rich', wagtail.wagtailcore.blocks.RichTextBlock(label='Éditeur')), ('carte', kfet.cms.models.MenuBlock()), ('group_team', wagtail.wagtailcore.blocks.StructBlock((('show_only', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Nombre initial de membres affichés. Laisser vide pour tou-te-s les afficher.', required=False, label='Montrer seulement')), ('members', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailsnippets.blocks.SnippetChooserBlock(kfet.cms.models.MemberTeam), classname='team-group', label='K-Fêt-eux-ses')))))), label='Contenu groupé'))), verbose_name='Contenu')),
|
||||
('layout', models.CharField(max_length=255, choices=[('kfet/base_col_1.html', 'Une colonne : centrée sur la page'), ('kfet/base_col_2.html', 'Deux colonnes : fixe à gauche, contenu à droite'), ('kfet/base_col_mult.html', 'Contenu scindé sur plusieurs colonnes')], help_text='Comment cette page devrait être affichée ?', verbose_name='Template', default='kfet/base_col_mult.html')),
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.db import models
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.validators import RegexValidator
|
||||
from django.contrib.auth.models import User
|
||||
from gestioncof.models import CofProfile
|
||||
from django.urls import reverse
|
||||
from django.utils.six.moves import reduce
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
{% load i18n static %}
|
||||
{% load wagtailcore_tags %}
|
||||
|
||||
{% slugurl "kfet" as kfet_home_url %}
|
||||
|
||||
<nav class="navbar navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="{% slugurl "k-fet" %}">
|
||||
<a class="navbar-brand" href="{{ kfet_home_url }}">
|
||||
<img src="{% static 'kfet/img/logo3.png' %}">
|
||||
</a>
|
||||
</div>
|
||||
|
@ -99,7 +101,7 @@
|
|||
{% endif %}
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="{% url "cof-logout" %}?next={% slugurl "k-fet" %}">
|
||||
<a href="{% url "cof-logout" %}?next={{ kfet_home_url|urlencode }}">
|
||||
<span class="glyphicon glyphicon-log-out"></span><span>Déconnexion</span>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -108,13 +110,13 @@
|
|||
{% endif %}
|
||||
{% if user.is_authenticated and not perms.kfet.is_team %}
|
||||
<li>
|
||||
<a href="{% url "cof-logout" %}?next={% slugurl "k-fet" %}" title="Déconnexion">
|
||||
<a href="{% url "cof-logout" %}?next={{ kfet_home_url|urlencode }}" title="Déconnexion">
|
||||
<span class="glyphicon glyphicon-log-out"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% elif not user.is_authenticated %}
|
||||
<li>
|
||||
<a href="{% url "cof-login" %}?next={{ request.path }}" title="Connexion">
|
||||
<a href="{% url "cof-login" %}?next={{ request.path|urlencode }}" title="Connexion">
|
||||
<span>Connexion</span><!--
|
||||
--><span class="glyphicon glyphicon-log-in"></span>
|
||||
</a>
|
||||
|
|
|
@ -452,7 +452,7 @@ class AccountGroupUpdateViewTests(ViewTestCaseMixin, TestCase):
|
|||
'kfet.manage_perms',
|
||||
)
|
||||
self.group = Group.objects.create(name='K-Fêt - Group')
|
||||
self.group.permissions = self.perms.values()
|
||||
self.group.permissions.set(self.perms.values())
|
||||
|
||||
def test_get_ok(self):
|
||||
r = self.client.get(self.url)
|
||||
|
|
|
@ -57,7 +57,7 @@ class TestCaseMixin:
|
|||
'path': request.get_full_path(),
|
||||
'username': (
|
||||
"'{}'".format(request.user)
|
||||
if request.user.is_authenticated()
|
||||
if request.user.is_authenticated
|
||||
else 'anonymous'
|
||||
),
|
||||
'code': response.status_code,
|
||||
|
@ -96,7 +96,7 @@ class TestCaseMixin:
|
|||
'path': request.get_full_path(),
|
||||
'username': (
|
||||
"'%s'" % request.user
|
||||
if request.user.is_authenticated()
|
||||
if request.user.is_authenticated
|
||||
else 'anonymous'
|
||||
),
|
||||
'form_ctx': form_ctx,
|
||||
|
|
|
@ -184,5 +184,5 @@ def user_add_perms(user, perms_labels):
|
|||
|
||||
# If permissions have already been fetched for this user, we need to reload
|
||||
# it to avoid using of the previous permissions cache.
|
||||
# https://docs.djangoproject.com/en/1.11/topics/auth/default/#permission-caching
|
||||
# https://docs.djangoproject.com/en/dev/topics/auth/default/#permission-caching
|
||||
return User.objects.get(pk=user.pk)
|
||||
|
|
|
@ -861,30 +861,34 @@ def account_read_json(request):
|
|||
'trigramme': account.trigramme }
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
@teamkfet_required
|
||||
def kpsul_checkout_data(request):
|
||||
pk = request.POST.get('pk', 0)
|
||||
if not pk:
|
||||
pk = 0
|
||||
data = (Checkout.objects
|
||||
|
||||
data = (
|
||||
Checkout.objects
|
||||
.annotate(
|
||||
last_statement_by_first_name=F('statements__by__cofprofile__user__first_name'),
|
||||
last_statement_by_last_name=F('statements__by__cofprofile__user__last_name'),
|
||||
last_statement_by_trigramme=F('statements__by__trigramme'),
|
||||
last_statement_balance=F('statements__balance_new'),
|
||||
last_statement_at=F('statements__at'))
|
||||
.values(
|
||||
'id', 'name', 'balance', 'valid_from', 'valid_to',
|
||||
'last_statement_balance', 'last_statement_at',
|
||||
'last_statement_by_trigramme', 'last_statement_by_last_name',
|
||||
'last_statement_by_first_name')
|
||||
.select_related(
|
||||
'statements'
|
||||
'statements__by',
|
||||
'statements__by__cofprofile__user')
|
||||
.filter(pk=pk)
|
||||
.order_by('statements__at')
|
||||
.last())
|
||||
.values(
|
||||
'id', 'name', 'balance', 'valid_from', 'valid_to',
|
||||
'last_statement_balance', 'last_statement_at',
|
||||
'last_statement_by_trigramme', 'last_statement_by_last_name',
|
||||
'last_statement_by_first_name')
|
||||
.last()
|
||||
)
|
||||
if data is None:
|
||||
raise Http404
|
||||
return JsonResponse(data)
|
||||
|
@ -1312,13 +1316,13 @@ def history_json(request):
|
|||
|
||||
# Construction de la requête (sur les opérations) pour le prefetch
|
||||
queryset_prefetch = Operation.objects.select_related(
|
||||
'canceled_by__trigramme', 'addcost_for__trigramme',
|
||||
'article__name')
|
||||
'article', 'canceled_by', 'addcost_for')
|
||||
|
||||
# Construction de la requête principale
|
||||
opegroups = (OperationGroup.objects
|
||||
.prefetch_related(Prefetch('opes', queryset = queryset_prefetch))
|
||||
.select_related('on_acc__trigramme', 'valid_by__trigramme')
|
||||
opegroups = (
|
||||
OperationGroup.objects
|
||||
.prefetch_related(Prefetch('opes', queryset=queryset_prefetch))
|
||||
.select_related('on_acc', 'valid_by')
|
||||
.order_by('at')
|
||||
)
|
||||
# Application des filtres
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
-r requirements.txt
|
||||
-e git://github.com/jazzband/django-debug-toolbar.git@88ddc7bdf39c7ff660eac054eab225ac22926754#egg=django-debug-toolbar
|
||||
django-debug-toolbar
|
||||
django-debug-panel
|
||||
ipython
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
configparser==3.5.0
|
||||
Django==1.8.*
|
||||
django-autocomplete-light==2.3.3
|
||||
Django==1.11.*
|
||||
django-autocomplete-light==3.1.3
|
||||
django-autoslug==1.9.3
|
||||
django-cas-ng==3.5.7
|
||||
django-djconfig==0.5.3
|
||||
django-grappelli==2.8.1
|
||||
django-recaptcha==1.0.5
|
||||
django-recaptcha==1.2.1
|
||||
django-redis-cache==1.7.1
|
||||
icalendar
|
||||
psycopg2
|
||||
Pillow==3.3.0
|
||||
six==1.10.0
|
||||
unicodecsv==0.14.1
|
||||
icalendar==3.10
|
||||
Pillow
|
||||
six
|
||||
unicodecsv
|
||||
django-bootstrap-form==3.2.1
|
||||
asgiref==1.1.1
|
||||
daphne==1.3.0
|
||||
|
@ -26,8 +25,5 @@ python-dateutil
|
|||
wagtail==1.10.*
|
||||
wagtailmenus==2.2.*
|
||||
|
||||
# Remove this when we switch to Django 1.11
|
||||
djangorestframework==3.6.4
|
||||
|
||||
# Production tools
|
||||
wheel
|
||||
|
|
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
0
utils/views/__init__.py
Normal file
0
utils/views/__init__.py
Normal file
26
utils/views/autocomplete.py
Normal file
26
utils/views/autocomplete.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from django.db.models import Q
|
||||
|
||||
from dal import autocomplete
|
||||
|
||||
|
||||
class Select2QuerySetView(autocomplete.Select2QuerySetView):
|
||||
model = None
|
||||
search_fields = []
|
||||
|
||||
def get_queryset_filter(self):
|
||||
q = self.q
|
||||
filter_q = Q()
|
||||
|
||||
if not q:
|
||||
return filter_q
|
||||
|
||||
words = q.split()
|
||||
|
||||
for word in words:
|
||||
for field in self.search_fields:
|
||||
filter_q |= Q(**{'{}__icontains'.format(field): word})
|
||||
|
||||
return filter_q
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(self.get_queryset_filter())
|
Loading…
Reference in a new issue