forked from CGM_Public/pretix_original
Added a model for logging actions
This commit is contained in:
@@ -70,4 +70,8 @@ Carts and Orders
|
|||||||
.. autoclass:: pretix.base.models.QuestionAnswer
|
.. autoclass:: pretix.base.models.QuestionAnswer
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. _cleanerversion: https://github.com/swisscom/cleanerversion
|
Logging
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. autoclass:: pretix.base.models.LogEntry
|
||||||
|
:members:
|
||||||
|
|||||||
31
src/pretix/base/migrations/0003_logentry.py
Normal file
31
src/pretix/base/migrations/0003_logentry.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9 on 2015-12-12 13:32
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
|
('pretixbase', '0002_auto_20151212_1123'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='LogEntry',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('object_id', models.PositiveIntegerField()),
|
||||||
|
('datetime', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('action_type', models.CharField(max_length=255)),
|
||||||
|
('data', models.TextField(default='{}')),
|
||||||
|
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
||||||
|
('event', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pretixbase.Event')),
|
||||||
|
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -5,6 +5,7 @@ from .items import (
|
|||||||
Item, ItemCategory, ItemVariation, Property, PropertyValue, Question,
|
Item, ItemCategory, ItemVariation, Property, PropertyValue, Question,
|
||||||
Quota, VariationsField, itempicture_upload_to,
|
Quota, VariationsField, itempicture_upload_to,
|
||||||
)
|
)
|
||||||
|
from .log import LogEntry
|
||||||
from .orders import (
|
from .orders import (
|
||||||
CachedTicket, CartPosition, ObjectWithAnswers, Order, OrderPosition,
|
CachedTicket, CartPosition, ObjectWithAnswers, Order, OrderPosition,
|
||||||
QuestionAnswer, generate_secret,
|
QuestionAnswer, generate_secret,
|
||||||
@@ -16,5 +17,5 @@ __all__ = [
|
|||||||
'ItemCategory', 'Item', 'Property', 'PropertyValue', 'ItemVariation', 'VariationsField', 'Question',
|
'ItemCategory', 'Item', 'Property', 'PropertyValue', 'ItemVariation', 'VariationsField', 'Question',
|
||||||
'Quota', 'Order', 'CachedTicket', 'QuestionAnswer', 'ObjectWithAnswers', 'OrderPosition',
|
'Quota', 'Order', 'CachedTicket', 'QuestionAnswer', 'ObjectWithAnswers', 'OrderPosition',
|
||||||
'CartPosition', 'EventSetting', 'OrganizerSetting', 'EventLock', 'cachedfile_name', 'itempicture_upload_to',
|
'CartPosition', 'EventSetting', 'OrganizerSetting', 'EventLock', 'cachedfile_name', 'itempicture_upload_to',
|
||||||
'generate_secret'
|
'generate_secret', 'LogEntry'
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from django.contrib.contenttypes.fields import GenericRelation
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_delete
|
from django.db.models.signals import post_delete
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
@@ -26,3 +27,21 @@ def cached_file_delete(sender, instance, **kwargs):
|
|||||||
if instance.file:
|
if instance.file:
|
||||||
# Pass false so FileField doesn't save the model.
|
# Pass false so FileField doesn't save the model.
|
||||||
instance.file.delete(False)
|
instance.file.delete(False)
|
||||||
|
|
||||||
|
|
||||||
|
class LoggedModel(models.Model):
|
||||||
|
logentries = GenericRelation('LogEntry')
|
||||||
|
|
||||||
|
def log_action(self, user, action, data):
|
||||||
|
from .log import LogEntry
|
||||||
|
from .event import Event
|
||||||
|
|
||||||
|
event = None
|
||||||
|
if isinstance(self, Event):
|
||||||
|
event = self
|
||||||
|
elif hasattr(self, 'event'):
|
||||||
|
event = self.event
|
||||||
|
LogEntry.objects.create(content_object=self, user=user, action=action, data=data, event=event)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|||||||
@@ -11,13 +11,14 @@ from django.utils.timezone import now
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from pretix.base.i18n import I18nCharField
|
from pretix.base.i18n import I18nCharField
|
||||||
|
from pretix.base.models.base import LoggedModel
|
||||||
from pretix.base.settings import SettingsProxy
|
from pretix.base.settings import SettingsProxy
|
||||||
|
|
||||||
from .auth import User
|
from .auth import User
|
||||||
from .organizer import Organizer
|
from .organizer import Organizer
|
||||||
|
|
||||||
|
|
||||||
class Event(models.Model):
|
class Event(LoggedModel):
|
||||||
"""
|
"""
|
||||||
This model represents an event. An event is anything you can buy
|
This model represents an event. An event is anything you can buy
|
||||||
tickets for.
|
tickets for.
|
||||||
|
|||||||
@@ -10,12 +10,13 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
||||||
from pretix.base.i18n import I18nCharField, I18nTextField
|
from pretix.base.i18n import I18nCharField, I18nTextField
|
||||||
|
from pretix.base.models.base import LoggedModel
|
||||||
|
|
||||||
from ..types import VariationDict
|
from ..types import VariationDict
|
||||||
from .event import Event
|
from .event import Event
|
||||||
|
|
||||||
|
|
||||||
class ItemCategory(models.Model):
|
class ItemCategory(LoggedModel):
|
||||||
"""
|
"""
|
||||||
Items can be sorted into these categories.
|
Items can be sorted into these categories.
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ def itempicture_upload_to(instance, filename: str) -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Item(models.Model):
|
class Item(LoggedModel):
|
||||||
"""
|
"""
|
||||||
An item is a thing which can be sold. It belongs to an event and may or may not belong to a category.
|
An item is a thing which can be sold. It belongs to an event and may or may not belong to a category.
|
||||||
Items are often also called 'products' but are named 'items' internally due to historic reasons.
|
Items are often also called 'products' but are named 'items' internally due to historic reasons.
|
||||||
@@ -539,7 +540,7 @@ class VariationsField(models.ManyToManyField):
|
|||||||
return super(RelatedField, self).formfield(**defaults)
|
return super(RelatedField, self).formfield(**defaults)
|
||||||
|
|
||||||
|
|
||||||
class Question(models.Model):
|
class Question(LoggedModel):
|
||||||
"""
|
"""
|
||||||
A question is an input field that can be used to extend a ticket
|
A question is an input field that can be used to extend a ticket
|
||||||
by custom information, e.g. "Attendee age". A question can allow one o several
|
by custom information, e.g. "Attendee age". A question can allow one o several
|
||||||
@@ -613,7 +614,7 @@ class Question(models.Model):
|
|||||||
self.event.get_cache().clear()
|
self.event.get_cache().clear()
|
||||||
|
|
||||||
|
|
||||||
class Quota(models.Model):
|
class Quota(LoggedModel):
|
||||||
"""
|
"""
|
||||||
A quota is a "pool of tickets". It is there to limit the number of items
|
A quota is a "pool of tickets". It is there to limit the number of items
|
||||||
of a certain type to be sold. For example, you could have a quota of 500
|
of a certain type to be sold. For example, you could have a quota of 500
|
||||||
|
|||||||
30
src/pretix/base/models/log.py
Normal file
30
src/pretix/base/models/log.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class LogEntry(models.Model):
|
||||||
|
"""
|
||||||
|
Represents a change or action that has been performed on another object
|
||||||
|
in the database. This uses django.contrib.contenttypes to allow a
|
||||||
|
relation to an arbitrary database object.
|
||||||
|
|
||||||
|
:param user: The user that performed the action
|
||||||
|
:type user: User
|
||||||
|
:param action_type: The type of action that has been performed. This is
|
||||||
|
used to look up the renderer used to describe the action in a human-
|
||||||
|
readable way. This should be some namespaced value using dotted
|
||||||
|
notationto avaoid duplicates, e.g.
|
||||||
|
``"pretix.plugins.banktransfer.incoming_transfer"``.
|
||||||
|
:type action_type: str
|
||||||
|
:param data: Arbitrary data that can be used by the log action renderer
|
||||||
|
:type data: str
|
||||||
|
"""
|
||||||
|
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
||||||
|
object_id = models.PositiveIntegerField()
|
||||||
|
content_object = GenericForeignKey('content_type', 'object_id')
|
||||||
|
datetime = models.DateTimeField(auto_now_add=True)
|
||||||
|
user = models.ForeignKey('User', null=True, blank=True, on_delete=models.PROTECT)
|
||||||
|
event = models.ForeignKey('Event', null=True, blank=True, on_delete=models.CASCADE)
|
||||||
|
action_type = models.CharField(max_length=255)
|
||||||
|
data = models.TextField(default='{}')
|
||||||
@@ -7,7 +7,7 @@ from django.utils.timezone import now
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
|
||||||
from .base import CachedFile
|
from .base import CachedFile, LoggedModel
|
||||||
from .event import Event
|
from .event import Event
|
||||||
from .items import Item, ItemVariation, Question, Quota
|
from .items import Item, ItemVariation, Question, Quota
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ def generate_secret():
|
|||||||
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(16))
|
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(16))
|
||||||
|
|
||||||
|
|
||||||
class Order(models.Model):
|
class Order(LoggedModel):
|
||||||
"""
|
"""
|
||||||
An order is created when a user clicks 'buy' on his cart. It holds
|
An order is created when a user clicks 'buy' on his cart. It holds
|
||||||
several OrderPositions and is connected to an user. It has an
|
several OrderPositions and is connected to an user. It has an
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ from django.db import models
|
|||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from pretix.base.models.base import LoggedModel
|
||||||
from pretix.base.settings import SettingsProxy
|
from pretix.base.settings import SettingsProxy
|
||||||
|
|
||||||
from .auth import User
|
from .auth import User
|
||||||
|
|
||||||
|
|
||||||
class Organizer(models.Model):
|
class Organizer(LoggedModel):
|
||||||
"""
|
"""
|
||||||
This model represents an entity organizing events, e.g. a company, institution,
|
This model represents an entity organizing events, e.g. a company, institution,
|
||||||
charity, person, …
|
charity, person, …
|
||||||
|
|||||||
Reference in New Issue
Block a user