Added a model for logging actions

This commit is contained in:
Raphael Michel
2015-12-12 15:41:48 +01:00
parent 493b80a481
commit 83b5fa2fa6
9 changed files with 98 additions and 10 deletions

View File

@@ -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:

View 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)),
],
),
]

View File

@@ -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'
] ]

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View 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='{}')

View File

@@ -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

View File

@@ -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, …