mirror of
https://github.com/DarrenOfficial/dpaste.git
synced 2024-11-15 08:02:54 +11:00
Added option to keep snippets forever.
This commit is contained in:
parent
25a83cf0f8
commit
964e1b64c7
10 changed files with 110 additions and 12 deletions
|
@ -1,6 +1,11 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
2.4 (dev)
|
||||
----------------
|
||||
|
||||
* Added an option to keep snippets forever
|
||||
|
||||
2.3 (2014-01-07)
|
||||
----------------
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ possible to be installed into an existing Django project like a regular app.
|
|||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
testing
|
||||
integration
|
||||
|
|
|
@ -35,6 +35,9 @@ Finally just ``syncdb`` or if you use South, migrate::
|
|||
|
||||
manage.py migrate dpaste
|
||||
|
||||
Purge expired snippets
|
||||
======================
|
||||
|
||||
Do not forget to setup a cron job to purge expired snippets. You need to
|
||||
run the management command ``cleanup_snippets``. A cron job I use looks like::
|
||||
|
||||
|
|
|
@ -55,6 +55,15 @@ behavior without touching the code:
|
|||
(3600 * 24 * 30 * 12 * 100, ugettext(u'100 Years')),
|
||||
)
|
||||
|
||||
You can keep snippets forever when you set the choice key to ``never``.
|
||||
The management command will ignore these snippets::
|
||||
|
||||
ugettext = lambda s: s
|
||||
DPASTE_EXPIRE_CHOICES = (
|
||||
(3600, ugettext(u'In one hour')),
|
||||
(u'never', ugettext(u'Never')),
|
||||
)
|
||||
|
||||
``DPASTE_EXPIRE_DEFAULT``
|
||||
The key of the default value of ``DPASTE_EXPIRE_CHOICES``. Default:
|
||||
``3600 * 24 * 30 * 12 * 100`` or simpler: ``DPASTE_EXPIRE_CHOICES[2][0]``.
|
||||
|
|
|
@ -61,7 +61,6 @@ class SnippetForm(forms.ModelForm):
|
|||
if 'l' in request.GET and request.GET['l'] in LEXER_KEYS:
|
||||
self.fields['lexer'].initial = request.GET['l']
|
||||
|
||||
|
||||
def clean_content(self):
|
||||
content = self.cleaned_data.get('content', '')
|
||||
if content.strip() == '':
|
||||
|
@ -75,6 +74,12 @@ class SnippetForm(forms.ModelForm):
|
|||
raise forms.ValidationError('This snippet was identified as Spam.')
|
||||
return self.cleaned_data
|
||||
|
||||
def clean_expire_options(self):
|
||||
expires = self.cleaned_data['expire_options']
|
||||
if expires == u'never':
|
||||
return None
|
||||
return expires
|
||||
|
||||
def save(self, parent=None, *args, **kwargs):
|
||||
MAX_SNIPPETS_PER_USER = getattr(settings, 'DPASTE_MAX_SNIPPETS_PER_USER', 15)
|
||||
|
||||
|
@ -82,9 +87,12 @@ class SnippetForm(forms.ModelForm):
|
|||
if parent:
|
||||
self.instance.parent = parent
|
||||
|
||||
# Add expire datestamp
|
||||
# Add expire datestamp. None indicates 'keep forever', use the default
|
||||
# null state of the db column for that.
|
||||
expires = self.cleaned_data['expire_options']
|
||||
if expires:
|
||||
self.instance.expires = datetime.datetime.now() + \
|
||||
datetime.timedelta(seconds=int(self.cleaned_data['expire_options']))
|
||||
datetime.timedelta(seconds=int(expires))
|
||||
|
||||
# Save snippet in the db
|
||||
super(SnippetForm, self).save(*args, **kwargs)
|
||||
|
|
|
@ -12,7 +12,10 @@ class Command(LabelCommand):
|
|||
help = "Purges snippets that are expired"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
deleteable_snippets = Snippet.objects.filter(expires__lte=datetime.datetime.now())
|
||||
deleteable_snippets = Snippet.objects.filter(
|
||||
expires__isnull=False,
|
||||
expires__lte=datetime.datetime.now()
|
||||
)
|
||||
sys.stdout.write(u"%s snippets gets deleted:\n" % deleteable_snippets.count())
|
||||
for d in deleteable_snippets:
|
||||
sys.stdout.write(u"- %s (%s)\n" % (d.secret_id, d.expires))
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Changing field 'Snippet.expires'
|
||||
db.alter_column('dpaste_snippet', 'expires', self.gf('django.db.models.fields.DateTimeField')(null=True))
|
||||
|
||||
# Changing field 'Snippet.secret_id'
|
||||
db.alter_column('dpaste_snippet', 'secret_id', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
|
||||
|
||||
# Changing field 'Snippet.published'
|
||||
db.alter_column('dpaste_snippet', 'published', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True))
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Changing field 'Snippet.expires'
|
||||
db.alter_column('dpaste_snippet', 'expires', self.gf('django.db.models.fields.DateTimeField')(default=None))
|
||||
|
||||
# Changing field 'Snippet.secret_id'
|
||||
db.alter_column('dpaste_snippet', 'secret_id', self.gf('django.db.models.fields.CharField')(default='', max_length=255))
|
||||
|
||||
# Changing field 'Snippet.published'
|
||||
db.alter_column('dpaste_snippet', 'published', self.gf('django.db.models.fields.DateTimeField')())
|
||||
|
||||
models = {
|
||||
u'dpaste.snippet': {
|
||||
'Meta': {'ordering': "('-published',)", 'object_name': 'Snippet'},
|
||||
'content': ('django.db.models.fields.TextField', [], {}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
u'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
|
||||
'lexer': ('django.db.models.fields.CharField', [], {'default': "'python'", 'max_length': '30'}),
|
||||
u'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
|
||||
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['dpaste.Snippet']"}),
|
||||
'published': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
u'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
|
||||
'secret_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
u'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['dpaste']
|
|
@ -18,11 +18,11 @@ def generate_secret_id(length=L, alphabet=T):
|
|||
return ''.join([R.choice(alphabet) for i in range(length)])
|
||||
|
||||
class Snippet(models.Model):
|
||||
secret_id = models.CharField(_(u'Secret ID'), max_length=255, blank=True)
|
||||
content = models.TextField(_(u'Content'), )
|
||||
secret_id = models.CharField(_(u'Secret ID'), max_length=255, blank=True, null=True)
|
||||
content = models.TextField(_(u'Content'))
|
||||
lexer = models.CharField(_(u'Lexer'), max_length=30, default=LEXER_DEFAULT)
|
||||
published = models.DateTimeField(_(u'Published'), blank=True)
|
||||
expires = models.DateTimeField(_(u'Expires'), blank=True)
|
||||
published = models.DateTimeField(_(u'Published'), auto_now_add=True)
|
||||
expires = models.DateTimeField(_(u'Expires'), blank=True, null=True)
|
||||
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
|
||||
|
||||
class Meta:
|
||||
|
@ -37,8 +37,7 @@ class Snippet(models.Model):
|
|||
return self.is_root_node() and not self.get_children()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.pk:
|
||||
self.published = datetime.now()
|
||||
if not self.secret_id:
|
||||
self.secret_id = generate_secret_id()
|
||||
super(Snippet, self).save(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -310,6 +310,22 @@ class SnippetTestCase(TestCase):
|
|||
management.call_command('cleanup_snippets')
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
||||
def test_delete_management_snippet_that_never_expires_will_not_get_deleted(self):
|
||||
"""
|
||||
Snippets without an expiration date wont get deleted automatically.
|
||||
"""
|
||||
data = self.valid_form_data()
|
||||
self.client.post(self.new_url, data, follow=True)
|
||||
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
||||
s = Snippet.objects.all()[0]
|
||||
s.expires = None
|
||||
s.save()
|
||||
|
||||
management.call_command('cleanup_snippets')
|
||||
self.assertEqual(Snippet.objects.count(), 1)
|
||||
|
||||
def test_highlighting(self):
|
||||
# You can pass any lexer to the pygmentize function and it will
|
||||
# never fail loudly.
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# These requirements are only required for local testing or development.
|
||||
# To use dpaste it's enough to install the package, all, and only the
|
||||
# necessary dependencies are installed automatically.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# Project dependencies
|
||||
django==1.6.1
|
||||
django-mptt==0.6.0
|
||||
|
|
Loading…
Reference in a new issue