Upgrade to Django 2.1 (#710)

* Upgrade to Django 2.0

* more models

* i18n foo

* Update setup.py

* Fix Sentry exception PRETIXEU-JC

* Enforce slug uniqueness

* Import sorting

* Upgrade to Django 2.1

* Travis config

* Try to fix PostgreSQL failure

* Smaller test matrix

* staticfiles→static

* Include request in all authenticate() calls
This commit is contained in:
Raphael Michel
2018-08-06 12:48:46 +02:00
committed by GitHub
parent 0637490216
commit afd766999c
131 changed files with 491 additions and 263 deletions

View File

@@ -46,7 +46,7 @@ class Migration(migrations.Migration):
('updated', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=255, verbose_name='Application name')),
('redirect_uris', models.TextField(help_text='Allowed URIs list, space separated',
validators=[oauth2_provider.validators.validate_uris],
validators=[oauth2_provider.validators.URIValidator],
verbose_name='Redirection URIs')),
('client_id',
models.CharField(db_index=True, default=oauth2_provider.generators.generate_client_id, max_length=100,

View File

@@ -11,13 +11,13 @@ from oauth2_provider.models import (
AbstractAccessToken, AbstractApplication, AbstractGrant,
AbstractRefreshToken,
)
from oauth2_provider.validators import validate_uris
from oauth2_provider.validators import URIValidator
class OAuthApplication(AbstractApplication):
name = models.CharField(verbose_name=_("Application name"), max_length=255, blank=False)
redirect_uris = models.TextField(
blank=False, validators=[validate_uris],
blank=False, validators=[URIValidator],
verbose_name=_("Redirection URIs"),
help_text=_("Allowed URIs list, space separated")
)

View File

@@ -32,7 +32,7 @@ class CheckinListViewSet(viewsets.ModelViewSet):
serializer_class = CheckinListSerializer
queryset = CheckinList.objects.none()
filter_backends = (DjangoFilterBackend,)
filter_class = CheckinListFilter
filterset_class = CheckinListFilter
permission = 'can_view_orders'
write_permission = 'can_change_event_settings'
@@ -175,7 +175,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
},
}
filter_class = CheckinOrderPositionFilter
filterset_class = CheckinOrderPositionFilter
permission = 'can_view_orders'
write_permission = 'can_change_orders'

View File

@@ -129,7 +129,7 @@ class SubEventViewSet(ConditionalListView, viewsets.ReadOnlyModelViewSet):
serializer_class = SubEventSerializer
queryset = ItemCategory.objects.none()
filter_backends = (DjangoFilterBackend, filters.OrderingFilter)
filter_class = SubEventFilter
filterset_class = SubEventFilter
def get_queryset(self):
return self.request.event.subevents.prefetch_related(

View File

@@ -41,7 +41,7 @@ class ItemViewSet(ConditionalListView, viewsets.ModelViewSet):
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering_fields = ('id', 'position')
ordering = ('position', 'id')
filter_class = ItemFilter
filterset_class = ItemFilter
permission = 'can_change_items'
write_permission = 'can_change_items'
@@ -207,7 +207,7 @@ class ItemCategoryViewSet(ConditionalListView, viewsets.ModelViewSet):
serializer_class = ItemCategorySerializer
queryset = ItemCategory.objects.none()
filter_backends = (DjangoFilterBackend, OrderingFilter)
filter_class = ItemCategoryFilter
filterset_class = ItemCategoryFilter
ordering_fields = ('id', 'position')
ordering = ('position', 'id')
permission = 'can_change_items'
@@ -261,7 +261,7 @@ class QuestionViewSet(ConditionalListView, viewsets.ModelViewSet):
serializer_class = QuestionSerializer
queryset = Question.objects.none()
filter_backends = (DjangoFilterBackend, OrderingFilter)
filter_class = QuestionFilter
filterset_class = QuestionFilter
ordering_fields = ('id', 'position')
ordering = ('position', 'id')
permission = 'can_change_items'
@@ -359,7 +359,7 @@ class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet):
serializer_class = QuotaSerializer
queryset = Quota.objects.none()
filter_backends = (DjangoFilterBackend, OrderingFilter,)
filter_class = QuotaFilter
filterset_class = QuotaFilter
ordering_fields = ('id', 'size')
ordering = ('id',)
permission = 'can_change_items'

View File

@@ -45,10 +45,10 @@ from pretix.base.signals import order_placed, register_ticket_outputs
class OrderFilter(FilterSet):
email = django_filters.CharFilter(name='email', lookup_expr='iexact')
code = django_filters.CharFilter(name='code', lookup_expr='iexact')
status = django_filters.CharFilter(name='status', lookup_expr='iexact')
modified_since = django_filters.IsoDateTimeFilter(name='last_modified', lookup_expr='gte')
email = django_filters.CharFilter(field_name='email', lookup_expr='iexact')
code = django_filters.CharFilter(field_name='code', lookup_expr='iexact')
status = django_filters.CharFilter(field_name='status', lookup_expr='iexact')
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
class Meta:
model = Order
@@ -61,7 +61,7 @@ class OrderViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering = ('datetime',)
ordering_fields = ('datetime', 'code', 'status')
filter_class = OrderFilter
filterset_class = OrderFilter
lookup_field = 'code'
permission = 'can_view_orders'
write_permission = 'can_change_orders'
@@ -307,7 +307,7 @@ class OrderViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
class OrderPositionFilter(FilterSet):
order = django_filters.CharFilter(name='order', lookup_expr='code__iexact')
order = django_filters.CharFilter(field_name='order', lookup_expr='code__iexact')
has_checkin = django_filters.rest_framework.BooleanFilter(method='has_checkin_qs')
attendee_name = django_filters.CharFilter(method='attendee_name_qs')
search = django_filters.CharFilter(method='search_qs')
@@ -345,7 +345,7 @@ class OrderPositionViewSet(viewsets.ReadOnlyModelViewSet):
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering = ('order__datetime', 'positionid')
ordering_fields = ('order__code', 'order__datetime', 'positionid', 'attendee_name', 'order__status',)
filter_class = OrderPositionFilter
filterset_class = OrderPositionFilter
permission = 'can_view_orders'
def get_queryset(self):
@@ -590,7 +590,7 @@ class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
class InvoiceFilter(FilterSet):
refers = django_filters.CharFilter(method='refers_qs')
number = django_filters.CharFilter(method='nr_qs')
order = django_filters.CharFilter(name='order', lookup_expr='code__iexact')
order = django_filters.CharFilter(field_name='order', lookup_expr='code__iexact')
def refers_qs(self, queryset, name, value):
return queryset.annotate(
@@ -617,7 +617,7 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering = ('nr',)
ordering_fields = ('nr', 'date')
filter_class = InvoiceFilter
filterset_class = InvoiceFilter
permission = 'can_view_orders'
lookup_url_kwarg = 'number'
lookup_field = 'nr'

View File

@@ -12,7 +12,7 @@ class OrganizerViewSet(viewsets.ReadOnlyModelViewSet):
lookup_url_kwarg = 'organizer'
def get_queryset(self):
if self.request.user.is_authenticated():
if self.request.user.is_authenticated:
if self.request.user.has_active_staff_session(self.request.session.session_key):
return Organizer.objects.all()
elif isinstance(self.request.auth, OAuthAccessToken):

View File

@@ -34,7 +34,7 @@ class VoucherViewSet(viewsets.ModelViewSet):
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering = ('id',)
ordering_fields = ('id', 'code', 'max_usages', 'valid_until', 'value')
filter_class = VoucherFilter
filterset_class = VoucherFilter
permission = 'can_view_vouchers'
write_permission = 'can_change_vouchers'

View File

@@ -28,7 +28,7 @@ class WaitingListViewSet(viewsets.ModelViewSet):
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering = ('created',)
ordering_fields = ('id', 'created', 'email', 'item')
filter_class = WaitingListFilter
filterset_class = WaitingListFilter
permission = 'can_view_orders'
write_permission = 'can_change_orders'

View File

@@ -39,7 +39,7 @@ class LoginForm(forms.Form):
password = self.cleaned_data.get('password')
if email and password:
self.user_cache = authenticate(email=email.lower(), password=password)
self.user_cache = authenticate(request=self.request, email=email.lower(), password=password)
if self.user_cache is None:
raise forms.ValidationError(
self.error_messages['invalid_login'],

View File

@@ -3,8 +3,8 @@ from urllib.parse import urlsplit
import pytz
from django.conf import settings
from django.core.urlresolvers import get_script_prefix
from django.http import HttpRequest, HttpResponse
from django.urls import get_script_prefix
from django.utils import timezone, translation
from django.utils.cache import patch_vary_headers
from django.utils.deprecation import MiddlewareMixin

View File

@@ -0,0 +1,56 @@
# Generated by Django 2.0.7 on 2018-07-31 12:43
import django.core.validators
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import pretix.base.validators
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0097_auto_20180722_0804'),
]
operations = [
migrations.AlterModelOptions(
name='logentry',
options={'ordering': ('-datetime', '-id')},
),
migrations.AlterField(
model_name='orderpayment',
name='fee',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='payments', to='pretixbase.OrderFee'),
),
migrations.AlterField(
model_name='organizer',
name='slug',
field=models.SlugField(help_text='Should be short, only contain lowercase letters, numbers, dots, and dashes. Every slug can only be used once. This is being used in URLs to refer to your organizer accounts and your events.', unique=True, validators=[django.core.validators.RegexValidator(message='The slug may only contain letters, numbers, dots and dashes.', regex='^[a-zA-Z0-9.-]+$'), pretix.base.validators.OrganizerSlugBlacklistValidator()], verbose_name='Short form'),
),
migrations.AlterField(
model_name='staffsession',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='staffsessionauditlog',
name='impersonating',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='staffsessionauditlog',
name='session',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='logs', to='pretixbase.StaffSession'),
),
migrations.AlterField(
model_name='user',
name='locale',
field=models.CharField(choices=[('en', 'English'), ('de', 'German'), ('de-informal', 'German (informal)'), ('nl', 'Dutch'), ('da', 'Danish'), ('tr', 'Turkish'), ('pt-br', 'Portuguese (Brazil)')], default='en', max_length=50, verbose_name='Language'),
),
migrations.AlterUniqueTogether(
name='event',
unique_together={('organizer', 'slug')},
),
]

View File

@@ -340,7 +340,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
class StaffSession(models.Model):
user = models.ForeignKey('User')
user = models.ForeignKey('User', on_delete=models.PROTECT)
date_start = models.DateTimeField(auto_now_add=True)
date_end = models.DateTimeField(null=True, blank=True)
session_key = models.CharField(max_length=255)
@@ -351,11 +351,11 @@ class StaffSession(models.Model):
class StaffSessionAuditLog(models.Model):
session = models.ForeignKey('StaffSession', related_name='logs')
session = models.ForeignKey('StaffSession', related_name='logs', on_delete=models.PROTECT)
datetime = models.DateTimeField(auto_now_add=True)
url = models.CharField(max_length=255)
method = models.CharField(max_length=255)
impersonating = models.ForeignKey('User', null=True, blank=True)
impersonating = models.ForeignKey('User', null=True, blank=True, on_delete=models.PROTECT)
class Meta:
ordering = ('datetime',)

View File

@@ -8,12 +8,12 @@ from pretix.base.models import LoggedModel
class CheckinList(LoggedModel):
event = models.ForeignKey('Event', related_name='checkin_lists')
event = models.ForeignKey('Event', related_name='checkin_lists', on_delete=models.CASCADE)
name = models.CharField(max_length=190)
all_products = models.BooleanField(default=True, verbose_name=_("All products (including newly created ones)"))
limit_products = models.ManyToManyField('Item', verbose_name=_("Limit to products"), blank=True)
subevent = models.ForeignKey('SubEvent', null=True, blank=True,
verbose_name=pgettext_lazy('subevent', 'Date'))
verbose_name=pgettext_lazy('subevent', 'Date'), on_delete=models.CASCADE)
include_pending = models.BooleanField(verbose_name=pgettext_lazy('checkin', 'Include pending orders'),
default=False,
help_text=_('With this option, people will be able to check in even if the '
@@ -157,7 +157,7 @@ class Checkin(models.Model):
"""
A check-in object is created when a person enters the event.
"""
position = models.ForeignKey('pretixbase.OrderPosition', related_name='checkins')
position = models.ForeignKey('pretixbase.OrderPosition', related_name='checkins', on_delete=models.CASCADE)
datetime = models.DateTimeField(default=now)
nonce = models.CharField(max_length=190, null=True, blank=True)
list = models.ForeignKey(

View File

@@ -265,6 +265,7 @@ class Event(EventMixin, LoggedModel):
verbose_name = _("Event")
verbose_name_plural = _("Events")
ordering = ("date_from", "name")
unique_together = (('organizer', 'slug'),)
def __str__(self):
return str(self.name)

View File

@@ -64,14 +64,14 @@ class Invoice(models.Model):
:param file: The filename of the rendered invoice
:type file: File
"""
order = models.ForeignKey('Order', related_name='invoices', db_index=True)
order = models.ForeignKey('Order', related_name='invoices', db_index=True, on_delete=models.CASCADE)
organizer = models.ForeignKey('Organizer', related_name='invoices', db_index=True, on_delete=models.PROTECT)
event = models.ForeignKey('Event', related_name='invoices', db_index=True)
event = models.ForeignKey('Event', related_name='invoices', db_index=True, on_delete=models.CASCADE)
prefix = models.CharField(max_length=160, db_index=True)
invoice_no = models.CharField(max_length=19, db_index=True)
full_invoice_no = models.CharField(max_length=190, db_index=True)
is_cancellation = models.BooleanField(default=False)
refers = models.ForeignKey('Invoice', related_name='refered', null=True, blank=True)
refers = models.ForeignKey('Invoice', related_name='refered', null=True, blank=True, on_delete=models.CASCADE)
invoice_from = models.TextField()
invoice_to = models.TextField()
date = models.DateField(default=today)
@@ -175,7 +175,7 @@ class InvoiceLine(models.Model):
:param tax_name: The name of the applied tax rate
:type tax_name: str
"""
invoice = models.ForeignKey('Invoice', related_name='lines')
invoice = models.ForeignKey('Invoice', related_name='lines', on_delete=models.CASCADE)
position = models.PositiveIntegerField(default=0)
description = models.TextField()
gross_value = models.DecimalField(max_digits=10, decimal_places=2)

View File

@@ -447,7 +447,8 @@ class ItemVariation(models.Model):
"""
item = models.ForeignKey(
Item,
related_name='variations'
related_name='variations',
on_delete=models.CASCADE
)
value = I18nCharField(
max_length=255,
@@ -562,12 +563,14 @@ class ItemAddOn(models.Model):
"""
base_item = models.ForeignKey(
Item,
related_name='addons'
related_name='addons',
on_delete=models.CASCADE
)
addon_category = models.ForeignKey(
ItemCategory,
related_name='addon_to',
verbose_name=_('Category')
verbose_name=_('Category'),
on_delete=models.CASCADE
)
min_count = models.PositiveIntegerField(
default=0,
@@ -679,7 +682,8 @@ class Question(LoggedModel):
event = models.ForeignKey(
Event,
related_name="questions"
related_name="questions",
on_delete=models.CASCADE
)
question = I18nTextField(
verbose_name=_("Question")
@@ -831,7 +835,7 @@ class Question(LoggedModel):
class QuestionOption(models.Model):
question = models.ForeignKey('Question', related_name='options')
question = models.ForeignKey('Question', related_name='options', on_delete=models.CASCADE)
identifier = models.CharField(max_length=190)
answer = I18nCharField(verbose_name=_('Answer'))
position = models.IntegerField(default=0)

View File

@@ -119,7 +119,8 @@ class Order(LoggedModel):
event = models.ForeignKey(
Event,
verbose_name=_("Event"),
related_name="orders"
related_name="orders",
on_delete=models.CASCADE
)
email = models.EmailField(
null=True, blank=True,
@@ -226,11 +227,11 @@ class Order(LoggedModel):
pending_sum_rc=-1 * F('payment_sum') + Coalesce(F('refund_sum'), 0),
).annotate(
is_overpaid=Case(
When(~Q(status__in=[Order.STATUS_REFUNDED, Order.STATUS_CANCELED]) & Q(pending_sum_t__lt=0),
When(~Q(status__in=(Order.STATUS_REFUNDED, Order.STATUS_CANCELED)) & Q(pending_sum_t__lt=0),
then=Value('1')),
When(Q(status__in=[Order.STATUS_REFUNDED, Order.STATUS_CANCELED]) & Q(pending_sum_rc__lt=0),
When(Q(status__in=(Order.STATUS_REFUNDED, Order.STATUS_CANCELED)) & Q(pending_sum_rc__lt=0),
then=Value('1')),
When(Q(status__in=[Order.STATUS_EXPIRED, Order.STATUS_PENDING]) & Q(pending_sum_t__lte=0),
When(Q(status__in=(Order.STATUS_EXPIRED, Order.STATUS_PENDING)) & Q(pending_sum_t__lte=0),
then=Value('1')),
default=Value('0'),
output_field=models.IntegerField()
@@ -544,14 +545,14 @@ class QuestionAnswer(models.Model):
"""
orderposition = models.ForeignKey(
'OrderPosition', null=True, blank=True,
related_name='answers'
related_name='answers', on_delete=models.CASCADE
)
cartposition = models.ForeignKey(
'CartPosition', null=True, blank=True,
related_name='answers'
related_name='answers', on_delete=models.CASCADE
)
question = models.ForeignKey(
Question, related_name='answers'
Question, related_name='answers', on_delete=models.CASCADE
)
options = models.ManyToManyField(
QuestionOption, related_name='answers', blank=True
@@ -699,7 +700,7 @@ class AbstractPosition(models.Model):
help_text=_("Empty, if this product is not an admission ticket")
)
voucher = models.ForeignKey(
'Voucher', null=True, blank=True
'Voucher', null=True, blank=True, on_delete=models.CASCADE
)
addon_to = models.ForeignKey(
'self', null=True, blank=True, on_delete=models.CASCADE, related_name='addons'
@@ -829,7 +830,7 @@ class OrderPayment(models.Model):
)
fee = models.ForeignKey(
'OrderFee',
null=True, blank=True, related_name='payments'
null=True, blank=True, related_name='payments', on_delete=models.SET_NULL
)
migrated = models.BooleanField(default=False)
@@ -1444,7 +1445,8 @@ class CartPosition(AbstractPosition):
"""
event = models.ForeignKey(
Event,
verbose_name=_("Event")
verbose_name=_("Event"),
on_delete=models.CASCADE
)
cart_id = models.CharField(
max_length=255, null=True, blank=True, db_index=True,
@@ -1488,7 +1490,7 @@ class CartPosition(AbstractPosition):
class InvoiceAddress(models.Model):
last_modified = models.DateTimeField(auto_now=True)
order = models.OneToOneField(Order, null=True, blank=True, related_name='invoice_address')
order = models.OneToOneField(Order, null=True, blank=True, related_name='invoice_address', on_delete=models.CASCADE)
is_business = models.BooleanField(default=False, verbose_name=_('Business customer'))
company = models.CharField(max_length=255, blank=True, verbose_name=_('Company name'))
name = models.CharField(max_length=255, verbose_name=_('Full name'), blank=True)

View File

@@ -42,6 +42,7 @@ class Organizer(LoggedModel):
OrganizerSlugBlacklistValidator()
],
verbose_name=_("Short form"),
unique=True
)
class Meta:

View File

@@ -60,7 +60,7 @@ EU_CURRENCIES = {
class TaxRule(LoggedModel):
event = models.ForeignKey('Event', related_name='tax_rules')
event = models.ForeignKey('Event', related_name='tax_rules', on_delete=models.CASCADE)
name = I18nCharField(
verbose_name=_('Name'),
help_text=_('Should be short, e.g. "VAT"'),

View File

@@ -137,14 +137,14 @@ class Voucher(LoggedModel):
item = models.ForeignKey(
Item, related_name='vouchers',
verbose_name=_("Product"),
null=True, blank=True,
null=True, blank=True, on_delete=models.CASCADE,
help_text=_(
"This product is added to the user's cart if the voucher is redeemed."
)
)
variation = models.ForeignKey(
ItemVariation, related_name='vouchers',
null=True, blank=True,
null=True, blank=True, on_delete=models.CASCADE,
verbose_name=_("Product variation"),
help_text=_(
"This variation of the product select above is being used."
@@ -152,7 +152,7 @@ class Voucher(LoggedModel):
)
quota = models.ForeignKey(
Quota, related_name='quota',
null=True, blank=True,
null=True, blank=True, on_delete=models.CASCADE,
verbose_name=_("Quota"),
help_text=_(
"If enabled, the voucher is valid for any product affected by this quota."

View File

@@ -43,10 +43,11 @@ class WaitingListEntry(LoggedModel):
'Voucher',
verbose_name=_("Assigned voucher"),
null=True, blank=True,
related_name='waitinglistentries'
related_name='waitinglistentries',
on_delete=models.CASCADE
)
item = models.ForeignKey(
Item, related_name='waitinglistentries',
Item, related_name='waitinglistentries', on_delete=models.CASCADE,
verbose_name=_("Product"),
help_text=_(
"The product the user waits for."
@@ -54,7 +55,7 @@ class WaitingListEntry(LoggedModel):
)
variation = models.ForeignKey(
ItemVariation, related_name='waitinglistentries',
null=True, blank=True,
null=True, blank=True, on_delete=models.CASCADE,
verbose_name=_("Product variation"),
help_text=_(
"The variation of the product selected above."

View File

@@ -171,7 +171,7 @@ def build_cancellation(invoice: Invoice):
def generate_cancellation(invoice: Invoice, trigger_pdf=True):
cancellation = copy.copy(invoice)
cancellation = copy.deepcopy(invoice)
cancellation.pk = None
cancellation.invoice_no = None
cancellation.prefix = None

View File

@@ -923,7 +923,7 @@ class OrderChangeManager:
op.save()
try:
ia = copy.copy(self.order.invoice_address)
ia = copy.deepcopy(self.order.invoice_address)
ia.pk = None
ia.order = split_order
ia.save()
@@ -947,7 +947,7 @@ class OrderChangeManager:
split_order.total += fee.value
for fee in self.order.fees.exclude(fee_type=OrderFee.FEE_TYPE_PAYMENT):
new_fee = copy.copy(fee)
new_fee = copy.deepcopy(fee)
new_fee.pk = None
new_fee.order = split_order
split_order.total += new_fee.value

View File

@@ -1,6 +1,6 @@
{% load compress %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>

View File

@@ -1,6 +1,6 @@
{% load compress %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>

View File

@@ -63,7 +63,7 @@ ALLOWED_PROTOCOLS = ['http', 'https', 'mailto', 'tel']
def safelink_callback(attrs, new=False):
url = attrs.get((None, 'href'), '/')
if not is_safe_url(url) and not url.startswith('mailto:') and not url.startswith('tel:'):
if not is_safe_url(url, allowed_hosts=None) and not url.startswith('mailto:') and not url.startswith('tel:'):
signer = signing.Signer(salt='safe-redirect')
attrs[None, 'href'] = reverse('redirect') + '?url=' + urllib.parse.quote(signer.sign(url))
attrs[None, 'target'] = '_blank'

View File

@@ -15,6 +15,6 @@ def url_replace(request, *pairs):
if key in dict_:
del dict_[key]
else:
dict_[key] = p
dict_[key] = str(p)
key = None
return dict_.urlencode(safe='[]')

View File

@@ -1,7 +1,8 @@
from django.utils import timezone
from django.utils.translation.trans_real import DjangoTranslation
from django.views.decorators.cache import cache_page
from django.views.decorators.http import etag
from django.views.i18n import get_javascript_catalog, render_javascript_catalog
from django.views.i18n import JavaScriptCatalog, render_javascript_catalog
# Yes, we want to regenerate this every time the module has been imported to
# refresh the cache at least at every code deployment
@@ -18,6 +19,6 @@ js_info_dict = {
@etag(lambda *s, **k: import_date)
@cache_page(3600, key_prefix='js18n-%s' % import_date)
def js_catalog(request, lang):
packages = ['pretix']
catalog, plural = get_javascript_catalog(lang, 'djangojs', packages)
return render_javascript_catalog(catalog, plural)
c = JavaScriptCatalog()
c.translation = DjangoTranslation(lang, domain='djangojs')
return render_javascript_catalog(c.get_catalog(), c.get_plural())

View File

@@ -1,8 +1,8 @@
import urllib.parse
from django.core import signing
from django.core.urlresolvers import reverse
from django.http import HttpResponseBadRequest, HttpResponseRedirect
from django.urls import reverse
def redir_view(request):

View File

@@ -2,8 +2,8 @@ import sys
from importlib import import_module
from django.conf import settings
from django.core.urlresolvers import Resolver404, get_script_prefix, resolve
from django.db.models import Q
from django.urls import Resolver404, get_script_prefix, resolve
from django.utils.translation import get_language
from pretix.base.models.auth import StaffSession

View File

@@ -78,7 +78,7 @@ class QuotaForm(I18nModelForm):
self.instance = kwargs.get('instance', None)
self.event = kwargs.get('event')
items = kwargs.pop('items', None) or self.event.items.prefetch_related('variations')
self.original_instance = copy.copy(self.instance) if self.instance else None
self.original_instance = copy.deepcopy(self.instance) if self.instance else None
initial = kwargs.get('initial', {})
if self.instance and self.instance.pk:
initial['itemvars'] = [str(i.pk) for i in self.instance.items.all()] + [
@@ -370,6 +370,7 @@ class ItemVariationsFormSet(I18nFormSet):
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
use_required_attribute=False,
locales=self.locales,
event=self.event
)
@@ -430,6 +431,7 @@ class ItemAddOnsFormSet(I18nFormSet):
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
use_required_attribute=False,
locales=self.locales,
event=self.event
)

View File

@@ -150,6 +150,7 @@ class QuotaFormSet(I18nInlineFormSet):
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
use_required_attribute=False,
locales=self.locales,
event=self.event,
items=self.items
@@ -196,6 +197,7 @@ class CheckinListFormSet(I18nInlineFormSet):
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
use_required_attribute=False,
event=self.event,
)
self.add_fields(form, None)

View File

@@ -45,7 +45,7 @@ class VoucherForm(I18nModelForm):
instance = kwargs.get('instance')
initial = kwargs.get('initial')
if instance:
self.initial_instance_data = copy.copy(instance)
self.initial_instance_data = copy.deepcopy(instance)
try:
if instance.variation:
initial['itemvar'] = '%d-%d' % (instance.item.pk, instance.variation.pk)
@@ -139,7 +139,7 @@ class VoucherForm(I18nModelForm):
if 'codes' in data:
data['codes'] = [a.strip() for a in data.get('codes', '').strip().split("\n") if a]
cnt = len(data['codes']) * data['max_usages']
cnt = len(data['codes']) * data.get('max_usages', 0)
else:
cnt = data['max_usages']
@@ -217,7 +217,7 @@ class VoucherBulkForm(VoucherForm):
def save(self, event, *args, **kwargs):
objs = []
for code in self.cleaned_data['codes']:
obj = copy.copy(self.instance)
obj = copy.deepcopy(self.instance)
obj.event = event
obj.code = code
data = dict(self.cleaned_data)

View File

@@ -2,9 +2,9 @@ from urllib.parse import quote, urljoin, urlparse
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME, logout
from django.core.urlresolvers import get_script_prefix, resolve, reverse
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect, resolve_url
from django.urls import get_script_prefix, resolve, reverse
from django.utils.deprecation import MiddlewareMixin
from django.utils.encoding import force_str
from django.utils.translation import ugettext as _

View File

@@ -1,6 +1,6 @@
{% load compress %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/auth/base.html" %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block content %}
<form class="form-signin" action="" method="post">

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/auth/base.html" %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block content %}
<form class="form-signin" action="" method="post">

View File

@@ -1,7 +1,7 @@
{% extends "pretixcontrol/auth/base.html" %}
{% load bootstrap3 %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% block content %}
<form class="form-signin" action="" method="post">
{% bootstrap_form_errors form type='all' layout='inline' %}

View File

@@ -1,7 +1,7 @@
{% extends "pretixcontrol/auth/base.html" %}
{% load bootstrap3 %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% load compress %}
{% block content %}
<form class="form-signin" action="" method="post" id="u2f-form">

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/auth/base.html" %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block content %}
{% if not error %}

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/auth/base.html" %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block content %}
<form class="form-signin" action="" method="post">

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/auth/base.html" %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block content %}
<form class="form-signin" action="" method="post">

View File

@@ -1,5 +1,5 @@
{% load compress %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load hijack_tags %}
{% load statici18n %}

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% block title %}{{ request.event.name }}{% endblock %}
{% block nav %}

View File

@@ -2,7 +2,7 @@
{% load i18n %}
{% load eventurl %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% block title %}{{ request.event.name }}{% endblock %}
{% block content %}
<h1>

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/items/base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% block title %}{% trans "Event logs" %}{% endblock %}
{% block inside %}
<h1>{% trans "Event logs" %}</h1>

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/event/settings_base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% load bootstrap3 %}
{% block inside %}

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/event/settings_base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% load bootstrap3 %}
{% load eventurl %}
{% load eventsignal %}

View File

@@ -1,4 +1,4 @@
{% load staticfiles %}
{% load static %}
{% load i18n %}
<ul class="list-group">
{% for log in obj.all_logentries %}

View File

@@ -1,6 +1,6 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% load compress %}
{% block title %}{% trans "PDF Editor" %}{% endblock %}
{% block custom_header %}

View File

@@ -1,4 +1,4 @@
{% load staticfiles %}
{% load static %}
{% for family, styles in fonts.items %}
{% for style, formats in styles.items %}

View File

@@ -1,7 +1,7 @@
{% extends "pretixcontrol/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% load compress %}
{% block title %}{% trans "Add a two-factor authentication device" %}{% endblock %}
{% block content %}

View File

@@ -2,7 +2,7 @@
{% load i18n %}
{% load bootstrap3 %}
{% load compress %}
{% load staticfiles %}
{% load static %}
{% block content %}
<form class="form-signin" id="u2f-form" action="" method="post">
{% csrf_token %}

View File

@@ -48,13 +48,13 @@ def login(request):
request.session['pretix_auth_2fa_user'] = form.user_cache.pk
request.session['pretix_auth_2fa_time'] = str(int(time.time()))
twofa_url = reverse('control:auth.login.2fa')
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
twofa_url += '?next=' + quote(request.GET.get('next'))
return redirect(twofa_url)
else:
auth_login(request, form.user_cache)
request.session['pretix_auth_login_time'] = int(time.time())
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
return redirect(reverse('control:index'))
else:
@@ -72,7 +72,7 @@ def logout(request):
auth_logout(request)
request.session['pretix_auth_login_time'] = 0
next = reverse('control:auth.login')
if 'next' in request.GET and is_safe_url(request.GET.get('next')):
if 'next' in request.GET and is_safe_url(request.GET.get('next'), allowed_hosts=None):
next += '?next=' + quote(request.GET.get('next'))
return redirect(next)
@@ -94,7 +94,7 @@ def register(request):
locale=request.LANGUAGE_CODE,
timezone=request.timezone if hasattr(request, 'timezone') else settings.TIME_ZONE
)
user = authenticate(email=user.email, password=form.cleaned_data['password'])
user = authenticate(request=request, email=user.email, password=form.cleaned_data['password'])
user.log_action('pretix.control.auth.user.created', user=user)
auth_login(request, user)
request.session['pretix_auth_login_time'] = int(time.time())
@@ -148,7 +148,7 @@ def invite(request, token):
locale=request.LANGUAGE_CODE,
timezone=request.timezone if hasattr(request, 'timezone') else settings.TIME_ZONE
)
user = authenticate(email=user.email, password=form.cleaned_data['password'])
user = authenticate(request=request, email=user.email, password=form.cleaned_data['password'])
user.log_action('pretix.control.auth.user.created', user=user)
auth_login(request, user)
request.session['pretix_auth_login_time'] = int(time.time())
@@ -329,7 +329,7 @@ class Login2FAView(TemplateView):
request.session['pretix_auth_login_time'] = int(time.time())
del request.session['pretix_auth_2fa_user']
del request.session['pretix_auth_2fa_time']
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
return redirect(reverse('control:index'))
else:

View File

@@ -1,10 +1,10 @@
import dateutil.parser
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Max, OuterRef, Subquery
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.timezone import is_aware, make_aware, now
from django.utils.translation import ugettext_lazy as _

View File

@@ -2,7 +2,6 @@ from decimal import Decimal
import pytz
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.db.models import (
Count, Exists, IntegerField, Max, Min, OuterRef, Q, Subquery, Sum,
)
@@ -10,6 +9,7 @@ from django.db.models.functions import Coalesce, Greatest
from django.dispatch import receiver
from django.shortcuts import render
from django.template.loader import get_template
from django.urls import reverse
from django.utils import formats
from django.utils.formats import date_format
from django.utils.html import escape

View File

@@ -9,7 +9,6 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.files import File
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import ProtectedError
from django.http import (
@@ -17,6 +16,7 @@ from django.http import (
JsonResponse,
)
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils import translation
from django.utils.formats import date_format
from django.utils.functional import cached_property

View File

@@ -2,12 +2,12 @@ import json
from django.contrib import messages
from django.core.files import File
from django.core.urlresolvers import resolve, reverse
from django.db import transaction
from django.db.models import Count, F, Q
from django.forms.models import inlineformset_factory
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import redirect
from django.urls import resolve, reverse
from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import ugettext, ugettext_lazy as _

View File

@@ -1,5 +1,4 @@
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import (
F, IntegerField, Max, Min, OuterRef, Prefetch, Subquery, Sum,
@@ -7,6 +6,7 @@ from django.db.models import (
from django.db.models.functions import Coalesce, Greatest
from django.http import JsonResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.translation import ugettext, ugettext_lazy as _

View File

@@ -10,11 +10,11 @@ import vat_moss.id
from django.conf import settings
from django.contrib import messages
from django.core.files import File
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Count
from django.http import FileResponse, Http404, HttpResponseNotAllowed
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils import formats
from django.utils.formats import date_format
from django.utils.functional import cached_property
@@ -275,7 +275,7 @@ class OrderRefundCancel(OrderView):
messages.success(self.request, _('The refund has been canceled.'))
else:
messages.error(self.request, _('This refund can not be canceled at the moment.'))
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next")):
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None):
return redirect(self.request.GET.get("next"))
return redirect(self.get_order_url())
@@ -310,7 +310,7 @@ class OrderRefundProcess(OrderView):
messages.success(self.request, _('The refund has been processed.'))
else:
messages.error(self.request, _('This refund can not be processed at the moment.'))
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next")):
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None):
return redirect(self.request.GET.get("next"))
return redirect(self.get_order_url())
@@ -336,7 +336,7 @@ class OrderRefundDone(OrderView):
messages.success(self.request, _('The refund has been marked as done.'))
else:
messages.error(self.request, _('This refund can not be processed at the moment.'))
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next")):
if "next" in self.request.GET and is_safe_url(self.request.GET.get("next"), allowed_hosts=None):
return redirect(self.request.GET.get("next"))
return redirect(self.get_order_url())

View File

@@ -2,11 +2,11 @@ from django import forms
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.core.files import File
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import Count
from django.forms import inlineformset_factory
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (

View File

@@ -3,13 +3,13 @@ from datetime import datetime
from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule, rruleset
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db import transaction
from django.db.models import F, IntegerField, OuterRef, Prefetch, Subquery, Sum
from django.db.models.functions import Coalesce
from django.forms import inlineformset_factory
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.timezone import make_aware
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
@@ -424,7 +424,7 @@ class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateVi
kwargs = super().get_form_kwargs()
kwargs['event'] = self.request.event
if self.copy_from:
i = copy.copy(self.copy_from)
i = copy.deepcopy(self.copy_from)
i.pk = None
kwargs['instance'] = i
else:

View File

@@ -7,8 +7,8 @@ from urllib.parse import quote
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.http import is_safe_url
@@ -73,7 +73,7 @@ class ReauthView(TemplateView):
t = int(time.time())
request.session['pretix_auth_login_time'] = t
request.session['pretix_auth_last_used'] = t
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
return redirect(reverse('control:index'))
else:
@@ -544,7 +544,7 @@ class StartStaffSession(StaffMemberRequiredMixin, RecentAuthenticationRequiredMi
session_key=request.session.session_key
)
if "next" in request.GET and is_safe_url(request.GET.get("next")):
if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None):
return redirect(request.GET.get("next"))
else:
return redirect(reverse("control:index"))

View File

@@ -1,13 +1,16 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import get_object_or_404, redirect
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, resolve_url
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.http import is_safe_url
from django.utils.translation import ugettext_lazy as _
from django.views import View
from django.views.generic import ListView
from hijack.helpers import login_user, release_hijack
from pretix.base.models import User
from pretix.base.services.mail import SendMailException
@@ -161,3 +164,78 @@ class UserCreateView(AdministratorPermissionRequiredMixin, RecentAuthenticationR
def form_valid(self, form):
messages.success(self.request, _('The new user has been created.'))
return super().form_valid(form)
# TODO: COMPAT methods: Remove after https://github.com/arteria/django-hijack/pull/178 is merged
def login_user(request, hijacked):
from hijack.helpers import (
check_hijack_authorization, get_used_backend, no_update_last_login, login,
hijack_started, hijack_settings
)
hijacker = request.user
hijack_history = [request.user._meta.pk.value_to_string(hijacker)]
if request.session.get('hijack_history'):
hijack_history = request.session['hijack_history'] + hijack_history
check_hijack_authorization(request, hijacked)
backend = get_used_backend(request)
hijacked.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
with no_update_last_login():
# Actually log user in
login(request, hijacked)
hijack_started.send(
sender=None, request=request,
hijacker=hijacker, hijacked=hijacked,
# send IDs for backward compatibility
hijacker_id=hijacker.pk, hijacked_id=hijacked.pk)
request.session['hijack_history'] = hijack_history
request.session['is_hijacked_user'] = True
request.session['display_hijack_warning'] = True
request.session.modified = True
return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGIN_REDIRECT_URL)
def redirect_to_next(request, default_url):
redirect_to = request.GET.get('next', '')
if not is_safe_url(redirect_to, allowed_hosts=None):
redirect_to = default_url
return HttpResponseRedirect(resolve_url(redirect_to))
def release_hijack(request):
from hijack.helpers import (
get_used_backend, no_update_last_login, login, hijack_ended, hijack_settings
)
hijack_history = request.session.get('hijack_history', False)
if not hijack_history:
raise PermissionDenied
hijacker = None
hijacked = None
if hijack_history:
hijacked = request.user
user_pk = hijack_history.pop()
hijacker = get_object_or_404(get_user_model(), pk=user_pk)
backend = get_used_backend(request)
hijacker.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
with no_update_last_login():
login(request, hijacker)
if hijack_history:
request.session['hijack_history'] = hijack_history
request.session['is_hijacked_user'] = True
request.session['display_hijack_warning'] = True
else:
request.session.pop('hijack_history', None)
request.session.pop('is_hijacked_user', None)
request.session.pop('display_hijack_warning', None)
request.session.modified = True
hijack_ended.send(
sender=None, request=request,
hijacker=hijacker, hijacked=hijacked,
# send IDs for backward compatibility
hijacker_id=hijacker.pk, hijacked_id=hijacked.pk)
return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGOUT_REDIRECT_URL)

View File

@@ -3,7 +3,6 @@ import io
from defusedcsv import csv
from django.conf import settings
from django.contrib import messages
from django.core.urlresolvers import resolve, reverse
from django.db import transaction
from django.db.models import Sum
from django.http import (
@@ -11,6 +10,7 @@ from django.http import (
JsonResponse,
)
from django.shortcuts import redirect
from django.urls import resolve, reverse
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (

View File

@@ -1,7 +1,7 @@
from urllib.parse import urljoin
from django.conf import settings
from django.core.urlresolvers import reverse
from django.urls import reverse
def build_absolute_uri(urlname, args=None, kwargs=None):

View File

@@ -1,5 +1,6 @@
from django.apps import AppConfig
from django.urls import RegexURLPattern
from django.urls import URLPattern
from django.urls.resolvers import RegexPattern
class PretixMultidomainConfig(AppConfig):
@@ -10,10 +11,9 @@ class PretixMultidomainConfig(AppConfig):
default_app_config = 'pretix.multidomain.PretixMultidomainConfig'
def event_url(regex, view, kwargs=None, name=None, require_live=True):
def event_url(route, view, name=None, require_live=True):
if callable(view):
r = RegexURLPattern(regex, view, kwargs, name)
r._require_live = require_live
return r
else:
raise TypeError('view must be a callable.')
pattern = RegexPattern(route, name=name, is_endpoint=True)
pattern._require_live = require_live
return URLPattern(pattern, view, {}, name)
raise TypeError('view must be a callable.')

View File

@@ -7,9 +7,9 @@ from django.contrib.sessions.middleware import (
)
from django.core.cache import cache
from django.core.exceptions import DisallowedHost
from django.core.urlresolvers import set_urlconf
from django.http.request import split_domain_port
from django.middleware.csrf import CsrfViewMiddleware as BaseCsrfMiddleware
from django.urls import set_urlconf
from django.utils.cache import patch_vary_headers
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import cookie_date

View File

@@ -7,7 +7,7 @@ from pretix.base.models import Organizer
class KnownDomain(models.Model):
domainname = models.CharField(max_length=255, primary_key=True)
organizer = models.ForeignKey(Organizer, blank=True, null=True, related_name='domains')
organizer = models.ForeignKey(Organizer, blank=True, null=True, related_name='domains', on_delete=models.CASCADE)
class Meta:
verbose_name = _("Known domain")

View File

@@ -7,5 +7,5 @@ def plugin_event_urls(urllist, plugin):
plugin_event_urls(entry.url_patterns, plugin)
elif hasattr(entry, 'callback'):
entry.callback = _event_view(entry.callback, require_plugin=plugin,
require_live=getattr(entry, '_require_live', True))
require_live=getattr(entry.pattern, '_require_live', True))
return urllist

View File

@@ -1,8 +1,8 @@
from django import template
from django.core.urlresolvers import NoReverseMatch
from django.template import TemplateSyntaxError
from django.template.base import kwarg_re
from django.template.defaulttags import URLNode
from django.urls import NoReverseMatch
from django.utils.encoding import smart_text
from django.utils.html import conditional_escape

View File

@@ -1,7 +1,7 @@
from urllib.parse import urljoin, urlsplit
from django.conf import settings
from django.core.urlresolvers import reverse
from django.urls import reverse
from pretix.base.models import Event, Organizer

View File

@@ -47,7 +47,7 @@ class BankImportJobSerializer(serializers.ModelSerializer):
class JobFilter(FilterSet):
event = django_filters.CharFilter(name='event', lookup_expr='slug')
event = django_filters.CharFilter(field_name='event', lookup_expr='slug')
class Meta:
model = BankImportJob
@@ -58,7 +58,7 @@ class BankImportJobViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
serializer_class = BankImportJobSerializer
queryset = BankImportJob.objects.none()
filter_backends = (DjangoFilterBackend,)
filter_class = JobFilter
filterset_class = JobFilter
permission = 'can_view_orders'
def get_queryset(self):

View File

@@ -16,8 +16,8 @@ class BankImportJob(models.Model):
(STATE_COMPLETED, 'completed'),
)
event = models.ForeignKey('pretixbase.Event', null=True)
organizer = models.ForeignKey('pretixbase.Organizer', null=True)
event = models.ForeignKey('pretixbase.Event', null=True, on_delete=models.CASCADE)
organizer = models.ForeignKey('pretixbase.Organizer', null=True, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
state = models.CharField(max_length=32, choices=STATES, default=STATE_PENDING)
@@ -48,9 +48,9 @@ class BankTransaction(models.Model):
(STATE_DISCARDED, 'manually discarded'),
)
event = models.ForeignKey('pretixbase.Event', null=True)
organizer = models.ForeignKey('pretixbase.Organizer', null=True)
import_job = models.ForeignKey('BankImportJob', related_name='transactions')
event = models.ForeignKey('pretixbase.Event', null=True, on_delete=models.CASCADE)
organizer = models.ForeignKey('pretixbase.Organizer', null=True, on_delete=models.CASCADE)
import_job = models.ForeignKey('BankImportJob', related_name='transactions', on_delete=models.CASCADE)
state = models.CharField(max_length=32, choices=STATES, default=STATE_UNCHECKED)
message = models.TextField()
checksum = models.CharField(max_length=190, db_index=True)
@@ -58,7 +58,7 @@ class BankTransaction(models.Model):
reference = models.TextField(blank=True)
amount = models.DecimalField(max_digits=10, decimal_places=2)
date = models.CharField(max_length=50)
order = models.ForeignKey('pretixbase.Order', null=True, blank=True)
order = models.ForeignKey('pretixbase.Order', null=True, blank=True, on_delete=models.CASCADE)
comment = models.TextField(blank=True)
def calculate_checksum(self):

View File

@@ -1,6 +1,6 @@
from django.core.urlresolvers import resolve, reverse
from django.dispatch import receiver
from django.template.loader import get_template
from django.urls import resolve, reverse
from django.utils.translation import ugettext_lazy as _
from pretix.base.signals import register_payment_providers

View File

@@ -1,4 +1,4 @@
{% load staticfiles %}
{% load static %}
{% load compress %}
{% compress css %}

View File

@@ -1,6 +1,6 @@
{% extends basetpl %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% block inner %}
<h2>{% trans "Import result" %}</h2>
{% if job.state == "running" or job.state == "pending" %}

View File

@@ -1,7 +1,7 @@
{% load i18n %}
{% load rich_text %}
{% load money %}
{% load staticfiles %}
{% load static %}
<div class="table-responsive">
{% csrf_token %}
<table class="table table-condensed transaction-list" data-url="{% if request.event %}{% url "plugins:banktransfer:import.action" event=request.event.slug organizer=request.organizer.slug %}{% else %}{% url "plugins:banktransfer:import.action" organizer=request.organizer.slug %}{% endif %}">

View File

@@ -4,11 +4,11 @@ import logging
from datetime import timedelta
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db.models import Count, Q
from django.db.models.functions import Concat
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import ugettext as _

View File

@@ -3,5 +3,5 @@ from django.db import models
class ReferencedPayPalObject(models.Model):
reference = models.CharField(max_length=190, db_index=True, unique=True)
order = models.ForeignKey('pretixbase.Order')
payment = models.ForeignKey('pretixbase.OrderPayment', null=True, blank=True)
order = models.ForeignKey('pretixbase.Order', on_delete=models.CASCADE)
payment = models.ForeignKey('pretixbase.OrderPayment', null=True, blank=True, on_delete=models.CASCADE)

View File

@@ -1,6 +1,6 @@
{% load compress %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>

View File

@@ -6,7 +6,7 @@ from django.utils.translation import ugettext_lazy as _
class AppConfiguration(models.Model):
event = models.ForeignKey('pretixbase.Event')
event = models.ForeignKey('pretixbase.Event', on_delete=models.CASCADE)
key = models.CharField(max_length=190, db_index=True)
all_items = models.BooleanField(default=True, verbose_name=_('Can scan all products'))
items = models.ManyToManyField('pretixbase.Item', blank=True, verbose_name=_('Can scan these products'))

View File

@@ -1,6 +1,6 @@
from django.core.urlresolvers import resolve, reverse
from django.dispatch import receiver
from django.urls import resolve, reverse
from django.utils.translation import ugettext_lazy as _
from pretix.base.signals import logentry_display

View File

@@ -1,7 +1,7 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% block title %}{% trans "Check-in device configuration" %}{% endblock %}
{% block content %}
<h1>{% trans "Check-in device configuration" %}</h1>

View File

@@ -1,7 +1,7 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load staticfiles %}
{% load static %}
{% block title %}{% trans "Device configuration" %}{% endblock %}
{% block content %}
{% if config.app == "pretixdroid" %}

View File

@@ -1,5 +1,5 @@
from django.core.urlresolvers import resolve, reverse
from django.dispatch import receiver
from django.urls import resolve, reverse
from django.utils.translation import ugettext_lazy as _
from pretix.base.signals import logentry_display

View File

@@ -1,5 +1,5 @@
from django.core.urlresolvers import resolve, reverse
from django.dispatch import receiver
from django.urls import resolve, reverse
from django.utils.translation import ugettext_lazy as _
from pretix.base.signals import order_paid, order_placed

View File

@@ -1,7 +1,7 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load compress %}
{% load staticfiles %}
{% load static %}
{% load escapejson %}
{% block title %}{% trans "Statistics" %}{% endblock %}
{% block content %}

View File

@@ -3,5 +3,5 @@ from django.db import models
class ReferencedStripeObject(models.Model):
reference = models.CharField(max_length=190, db_index=True, unique=True)
order = models.ForeignKey('pretixbase.Order')
payment = models.ForeignKey('pretixbase.OrderPayment', null=True, blank=True)
order = models.ForeignKey('pretixbase.Order', on_delete=models.CASCADE)
payment = models.ForeignKey('pretixbase.OrderPayment', null=True, blank=True, on_delete=models.CASCADE)

View File

@@ -2,9 +2,9 @@ import json
from collections import OrderedDict
from django import forms
from django.core.urlresolvers import resolve
from django.dispatch import receiver
from django.template.loader import get_template
from django.urls import resolve
from django.utils.translation import ugettext_lazy as _
from pretix.base.settings import settings_hierarkey

View File

@@ -1,4 +1,4 @@
{% load staticfiles %}
{% load static %}
{% load compress %}
{% load i18n %}

View File

@@ -1,6 +1,6 @@
{% load compress %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>

View File

@@ -138,6 +138,7 @@ class AddOnsForm(forms.Form):
if override_price:
price = override_price
print(price, repr(price), type(price), repr(item.default_price))
if self.price_included:
price = TAXED_ZERO
else:

View File

@@ -1,4 +1,4 @@
from django.core.urlresolvers import resolve
from django.urls import resolve
from django.utils.deprecation import MiddlewareMixin
from pretix.presale.signals import process_response

View File

@@ -1,5 +1,5 @@
{% load compress %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load safelink %}
{% load statici18n %}

View File

@@ -1,6 +1,6 @@
{% extends "pretixpresale/base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% load thumb %}
{% load eventurl %}
{% load safelink %}

View File

@@ -1,6 +1,6 @@
{% load i18n %}
{% load compress %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>

View File

@@ -1,6 +1,6 @@
{% extends "pretixpresale/base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% load thumb %}
{% load eventurl %}
{% block thetitle %}

View File

@@ -1,6 +1,6 @@
{% load compress %}
{% load i18n %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>

Some files were not shown because too many files have changed in this diff Show More