@@ -329,3 +329,249 @@ class Migration(migrations.Migration):
329329 ),
330330 ]
331331```
332+
333+
334+ ## Example 3 from AuditLog
335+ [ Auditlog] ( https://github.com/jjkester/django-auditlog )
336+ ([ project documentation] ( https://django-auditlog.readthedocs.io/en/latest/ ) )
337+ is a [ Django] ( /django.html ) app that logs changes to Python objects,
338+ similar to the Django admin's logs but with more details and
339+ output formats. Auditlog's source code is provided as open source under the
340+ [ MIT license] ( https://github.com/jjkester/django-auditlog/blob/master/LICENSE ) .
341+
342+ [ ** AuditLog / src / auditlog_tests / models.py** ] ( https://github.com/jjkester/django-auditlog/blob/master/src/auditlog_tests/models.py )
343+
344+ ``` python
345+ import uuid
346+
347+ from django.contrib.postgres.fields import ArrayField
348+ ~~ from django.db import models
349+ from auditlog.models import AuditlogHistoryField
350+ from auditlog.registry import auditlog
351+
352+ from multiselectfield import MultiSelectField
353+
354+
355+ @auditlog.register ()
356+ class SimpleModel (models .Model ):
357+ """
358+ A simple model with no special things going on.
359+ """
360+
361+ ~~ text = models.TextField(blank = True )
362+ boolean = models.BooleanField(default = False )
363+ integer = models.IntegerField(blank = True , null = True )
364+ datetime = models.DateTimeField(auto_now = True )
365+
366+ history = AuditlogHistoryField()
367+
368+
369+ class AltPrimaryKeyModel (models .Model ):
370+ """
371+ A model with a non-standard primary key.
372+ """
373+
374+ key = models.CharField(max_length = 100 , primary_key = True )
375+
376+ ~~ text = models.TextField(blank = True )
377+ boolean = models.BooleanField(default = False )
378+ integer = models.IntegerField(blank = True , null = True )
379+ datetime = models.DateTimeField(auto_now = True )
380+
381+ history = AuditlogHistoryField(pk_indexable = False )
382+
383+
384+ class UUIDPrimaryKeyModel (models .Model ):
385+ """
386+ A model with a UUID primary key.
387+ """
388+
389+ id = models.UUIDField(primary_key = True , default = uuid.uuid4, editable = False )
390+
391+ ~~ text = models.TextField(blank = True )
392+ boolean = models.BooleanField(default = False )
393+ integer = models.IntegerField(blank = True , null = True )
394+ datetime = models.DateTimeField(auto_now = True )
395+
396+ history = AuditlogHistoryField(pk_indexable = False )
397+
398+
399+ class ProxyModel (SimpleModel ):
400+ """
401+ A model that is a proxy for another model.
402+ """
403+
404+ class Meta :
405+ proxy = True
406+
407+
408+ class RelatedModel (models .Model ):
409+ """
410+ A model with a foreign key.
411+ """
412+
413+ related = models.ForeignKey(to = ' self' , on_delete = models.CASCADE )
414+
415+ history = AuditlogHistoryField()
416+
417+
418+ class ManyRelatedModel (models .Model ):
419+ """
420+ A model with a many to many relation.
421+ """
422+
423+ related = models.ManyToManyField(' self' )
424+
425+ history = AuditlogHistoryField()
426+
427+
428+ @auditlog.register (include_fields = [' label' ])
429+ class SimpleIncludeModel (models .Model ):
430+ """
431+ A simple model used for register's include_fields kwarg
432+ """
433+
434+ label = models.CharField(max_length = 100 )
435+ ~~ text = models.TextField(blank = True )
436+
437+ history = AuditlogHistoryField()
438+
439+
440+ class SimpleExcludeModel (models .Model ):
441+ """
442+ A simple model used for register's exclude_fields kwarg
443+ """
444+
445+ label = models.CharField(max_length = 100 )
446+ ~~ text = models.TextField(blank = True )
447+
448+ history = AuditlogHistoryField()
449+
450+
451+ class SimpleMappingModel (models .Model ):
452+ """
453+ A simple model used for register's mapping_fields kwarg
454+ """
455+
456+ sku = models.CharField(max_length = 100 )
457+ vtxt = models.CharField(verbose_name = ' Version' , max_length = 100 )
458+ not_mapped = models.CharField(max_length = 100 )
459+
460+ history = AuditlogHistoryField()
461+
462+
463+ class AdditionalDataIncludedModel (models .Model ):
464+ """
465+ A model where get_additional_data is defined which allows for logging extra
466+ information about the model in JSON
467+ """
468+
469+ label = models.CharField(max_length = 100 )
470+ ~~ text = models.TextField(blank = True )
471+ related = models.ForeignKey(to = SimpleModel, on_delete = models.CASCADE )
472+
473+ history = AuditlogHistoryField()
474+
475+ def get_additional_data (self ):
476+ """
477+ Returns JSON that captures a snapshot of additional details of the
478+ model instance. This method, if defined, is accessed by auditlog
479+ manager and added to each logentry instance on creation.
480+ """
481+ object_details = {
482+ ' related_model_id' : self .related.id,
483+ ' related_model_text' : self .related.text
484+ }
485+ return object_details
486+
487+
488+ class DateTimeFieldModel (models .Model ):
489+ """
490+ A model with a DateTimeField, used to test DateTimeField
491+ changes are detected properly.
492+ """
493+ label = models.CharField(max_length = 100 )
494+ timestamp = models.DateTimeField()
495+ date = models.DateField()
496+ time = models.TimeField()
497+ naive_dt = models.DateTimeField(null = True , blank = True )
498+
499+ history = AuditlogHistoryField()
500+
501+
502+ class ChoicesFieldModel (models .Model ):
503+ """
504+ A model with a CharField restricted to a set of choices.
505+ This model is used to test the changes_display_dict method.
506+ """
507+ RED = ' r'
508+ YELLOW = ' y'
509+ GREEN = ' g'
510+
511+ STATUS_CHOICES = (
512+ (RED , ' Red' ),
513+ (YELLOW , ' Yellow' ),
514+ (GREEN , ' Green' ),
515+ )
516+
517+ status = models.CharField(max_length = 1 , choices = STATUS_CHOICES )
518+ multiselect = MultiSelectField(max_length = 3 , choices = STATUS_CHOICES , max_choices = 3 )
519+ multiplechoice = models.CharField(max_length = 3 , choices = STATUS_CHOICES )
520+
521+ history = AuditlogHistoryField()
522+
523+
524+ class CharfieldTextfieldModel (models .Model ):
525+ """
526+ A model with a max length CharField and a Textfield.
527+ This model is used to test the changes_display_dict
528+ method's ability to truncate long text.
529+ """
530+
531+ longchar = models.CharField(max_length = 255 )
532+ ~~ longtextfield = models.TextField()
533+
534+ history = AuditlogHistoryField()
535+
536+
537+ class PostgresArrayFieldModel (models .Model ):
538+ """
539+ Test auditlog with Postgres's ArrayField
540+ """
541+ RED = ' r'
542+ YELLOW = ' y'
543+ GREEN = ' g'
544+
545+ STATUS_CHOICES = (
546+ (RED , ' Red' ),
547+ (YELLOW , ' Yellow' ),
548+ (GREEN , ' Green' ),
549+ )
550+
551+ arrayfield = ArrayField(models.CharField(max_length = 1 , choices = STATUS_CHOICES ), size = 3 )
552+
553+ history = AuditlogHistoryField()
554+
555+
556+ class NoDeleteHistoryModel (models .Model ):
557+ integer = models.IntegerField(blank = True , null = True )
558+
559+ history = AuditlogHistoryField(delete_related = False )
560+
561+
562+ auditlog.register(AltPrimaryKeyModel)
563+ auditlog.register(UUIDPrimaryKeyModel)
564+ auditlog.register(ProxyModel)
565+ auditlog.register(RelatedModel)
566+ auditlog.register(ManyRelatedModel)
567+ auditlog.register(ManyRelatedModel.related.through)
568+ auditlog.register(SimpleExcludeModel, exclude_fields = [' text' ])
569+ auditlog.register(SimpleMappingModel, mapping_fields = {' sku' : ' Product No.' })
570+ auditlog.register(AdditionalDataIncludedModel)
571+ auditlog.register(DateTimeFieldModel)
572+ auditlog.register(ChoicesFieldModel)
573+ auditlog.register(CharfieldTextfieldModel)
574+ auditlog.register(PostgresArrayFieldModel)
575+ auditlog.register(NoDeleteHistoryModel)
576+ ```
577+
0 commit comments