# HG changeset patch # User neko259 # Date 2017-09-29 08:36:17 # Node ID f370237893b4d0cebe8a125e31b6bb76ab892e09 # Parent 75d347ed0ea16ca111e7ef94c76e39bc09ffb8fc Use update-time of a post instead of version diff --git a/boards/admin.py b/boards/admin.py --- a/boards/admin.py +++ b/boards/admin.py @@ -16,7 +16,7 @@ class PostAdmin(admin.ModelAdmin): exclude = ('referenced_posts', 'refmap', 'images', 'global_id') readonly_fields = ('poster_ip', 'thread', 'linked_images', 'attachments', 'uid', 'url', 'pub_time', 'opening', 'linked_global_id', - 'version', 'foreign', 'tags') + 'foreign', 'tags') def ban_poster(self, request, queryset): bans = 0 @@ -63,7 +63,6 @@ class PostAdmin(admin.ModelAdmin): return ', '.join([tag.get_name() for tag in obj.get_tags()]) def save_model(self, request, obj, form, change): - obj.increment_version() obj.save() obj.clear_cache() @@ -127,8 +126,6 @@ class ThreadAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): op = obj.get_opening_post() - op.increment_version() - op.save(update_fields=['version']) obj.save() op.clear_cache() diff --git a/boards/management/commands/sync_with_server.py b/boards/management/commands/sync_with_server.py --- a/boards/management/commands/sync_with_server.py +++ b/boards/management/commands/sync_with_server.py @@ -4,9 +4,10 @@ import xml.etree.ElementTree as ET import httplib2 from django.core.management import BaseCommand +from django.utils.dateparse import parse_datetime from boards.models import GlobalId -from boards.models.post.sync import SyncManager, TAG_ID, TAG_VERSION +from boards.models.post.sync import SyncManager, TAG_ID, TAG_UPDATE_TIME __author__ = 'neko259' @@ -85,12 +86,12 @@ class Command(BaseCommand): for model in models: tag_id = model.find(TAG_ID) global_id, exists = GlobalId.from_xml_element(tag_id) - tag_version = model.find(TAG_VERSION) - if tag_version is not None: - version = int(tag_version.text) or 1 + tag_update_time = model.find(TAG_UPDATE_TIME) + if tag_update_time: + update_time = tag_update_time.text else: - version = 1 - if not exists or global_id.post.version < version: + update_time = None + if not exists or update_time is None or global_id.post.last_edit_time < parse_datetime(update_time): logger.debug('Processed (+) post {}'.format(global_id)) ids_to_sync.append(global_id) else: diff --git a/boards/migrations/0064_remove_post_version.py b/boards/migrations/0064_remove_post_version.py new file mode 100644 --- /dev/null +++ b/boards/migrations/0064_remove_post_version.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-09-27 12:38 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('boards', '0063_auto_20170301_1058'), + ] + + operations = [ + migrations.RemoveField( + model_name='post', + name='version', + ), + ] diff --git a/boards/models/post/__init__.py b/boards/models/post/__init__.py --- a/boards/models/post/__init__.py +++ b/boards/models/post/__init__.py @@ -100,7 +100,6 @@ class Post(models.Model, Viewable): tripcode = models.CharField(max_length=50, blank=True, default='') opening = models.BooleanField(db_index=True) hidden = models.BooleanField(default=False) - version = models.IntegerField(default=1) def __str__(self): return 'P#{}/{}'.format(self.id, self.get_title()) @@ -341,9 +340,6 @@ class Post(models.Model, Viewable): def set_hidden(self, hidden): self.hidden = hidden - def increment_version(self): - self.version = F('version') + 1 - def clear_cache(self): """ Clears sync data (content cache, signatures etc). diff --git a/boards/models/post/manager.py b/boards/models/post/manager.py --- a/boards/models/post/manager.py +++ b/boards/models/post/manager.py @@ -138,7 +138,7 @@ class PostManager(models.Manager): @transaction.atomic def import_post(self, title: str, text: str, pub_time: str, global_id, opening_post=None, tags=list(), files=list(), - file_urls=list(), tripcode=None, version=1): + file_urls=list(), tripcode=None, last_edit_time=None): is_opening = opening_post is None if is_opening: thread = boards.models.thread.Thread.objects.create( @@ -151,12 +151,11 @@ class PostManager(models.Manager): text=text, pub_time=pub_time, poster_ip=NO_IP, - last_edit_time=pub_time, + last_edit_time=last_edit_time or pub_time, global_id=global_id, opening=is_opening, thread=thread, - tripcode=tripcode, - version=version) + tripcode=tripcode) for file in files: self._add_file_to_post(file, post) @@ -170,12 +169,11 @@ class PostManager(models.Manager): @transaction.atomic def update_post(self, post, title: str, text: str, pub_time: str, - tags=list(), files=list(), file_urls=list(), tripcode=None, version=1): + tags=list(), files=list(), file_urls=list(), tripcode=None): post.title = title post.text = text post.pub_time = pub_time post.tripcode = tripcode - post.version = version post.save() post.clear_cache() diff --git a/boards/models/post/sync.py b/boards/models/post/sync.py --- a/boards/models/post/sync.py +++ b/boards/models/post/sync.py @@ -1,16 +1,17 @@ +import logging import xml.etree.ElementTree as et -import logging -from xml.etree import ElementTree + +from django.db import transaction +from django.utils.dateparse import parse_datetime from boards.abstracts.exceptions import SyncException -from boards.abstracts.sync_filters import ThreadFilter, TagsFilter,\ - TimestampFromFilter +from boards.abstracts.sync_filters import ThreadFilter, TagsFilter, \ + TimestampFromFilter from boards.models import KeyPair, GlobalId, Signature, Post, Tag from boards.models.attachment.downloaders import download from boards.models.signature import TAG_REQUEST, ATTR_TYPE, TYPE_GET, \ ATTR_VERSION, TAG_MODEL, ATTR_NAME, TAG_ID, TYPE_LIST from boards.utils import get_file_mimetype, get_file_hash -from django.db import transaction EXCEPTION_NODE = 'Sync node returned an error: {}.' EXCEPTION_DOWNLOAD = 'File was not downloaded.' @@ -30,6 +31,7 @@ TAG_TITLE = 'title' TAG_TEXT = 'text' TAG_THREAD = 'thread' TAG_PUB_TIME = 'pub-time' +TAG_UPDATE_TIME = 'update-time' TAG_SIGNATURES = 'signatures' TAG_SIGNATURE = 'signature' TAG_CONTENT = 'content' @@ -59,6 +61,8 @@ ID_TYPE_URL = 'url' STATUS_SUCCESS = 'success' +CURRENT_MODEL_VERSION = '1.1' + logger = logging.getLogger('boards.sync') @@ -120,6 +124,9 @@ class SyncManager: pub_time = et.SubElement(content_tag, TAG_PUB_TIME) pub_time.text = str(post.get_pub_time_str()) + update_time = et.SubElement(content_tag, TAG_UPDATE_TIME) + update_time.text = str(post.last_edit_time) + if post.tripcode: tripcode = et.SubElement(content_tag, TAG_TRIPCODE) tripcode.text = post.tripcode @@ -141,8 +148,6 @@ class SyncManager: for file in attachments: SyncManager._attachment_to_xml( attachments_tag, attachment_refs, file) - version_tag = et.SubElement(content_tag, TAG_VERSION) - version_tag.text = str(post.version) global_id.content = et.tostring(content_tag, ENCODING_UNICODE) global_id.save() @@ -191,8 +196,8 @@ class SyncManager: global_id, exists = GlobalId.from_xml_element(tag_id) signatures = SyncManager._verify_model(global_id, content_str, tag_model) - version = int(tag_content.find(TAG_VERSION).text) - is_old = exists and global_id.post.version < version + update_time = tag_content.find(TAG_UPDATE_TIME).text + is_old = exists and global_id.post.last_edit_time < parse_datetime(update_time) if exists and not is_old: logger.debug('Post {} exists and is up to date.'.format(global_id)) else: @@ -204,13 +209,13 @@ class SyncManager: title = tag_content.find(TAG_TITLE).text or '' text = tag_content.find(TAG_TEXT).text or '' - pub_time = tag_content.find(TAG_PUB_TIME).text tripcode_tag = tag_content.find(TAG_TRIPCODE) if tripcode_tag is not None: tripcode = tripcode_tag.text or '' else: tripcode = '' + pub_time = tag_content.find(TAG_PUB_TIME).text thread = tag_content.find(TAG_THREAD) tags = [] if thread: @@ -257,15 +262,14 @@ class SyncManager: Post.objects.update_post( post, title=title, text=text, pub_time=pub_time, tags=tags, files=files, file_urls=urls, - tripcode=tripcode, version=version) + tripcode=tripcode, version=version, last_edit_time=update_time) logger.debug('Parsed updated post {}'.format(global_id)) else: Post.objects.import_post( title=title, text=text, pub_time=pub_time, opening_post=opening_post, tags=tags, global_id=global_id, files=files, - file_urls=urls, tripcode=tripcode, - version=version) + file_urls=urls, tripcode=tripcode, last_edit_time=update_time) logger.debug('Parsed new post {}'.format(global_id)) @staticmethod @@ -285,8 +289,8 @@ class SyncManager: tag_model = et.SubElement(models, TAG_MODEL) tag_id = et.SubElement(tag_model, TAG_ID) post.global_id.to_xml_element(tag_id) - tag_version = et.SubElement(tag_model, TAG_VERSION) - tag_version.text = str(post.version) + update_time = et.SubElement(tag_model, TAG_UPDATE_TIME) + update_time.text = str(post.last_edit_time) return et.tostring(response, ENCODING_UNICODE) @@ -372,7 +376,7 @@ class SyncManager: request.set(ATTR_VERSION, '1.0') model = et.SubElement(request, TAG_MODEL) - model.set(ATTR_VERSION, '1.0') + model.set(ATTR_VERSION, CURRENT_MODEL_VERSION) model.set(ATTR_NAME, 'post') if opening_post: diff --git a/boards/models/thread.py b/boards/models/thread.py --- a/boards/models/thread.py +++ b/boards/models/thread.py @@ -186,7 +186,7 @@ class Thread(models.Model): """ Gets replies with only fields that are used for viewing. """ - return self.get_replies().defer('text', 'last_edit_time', 'version') + return self.get_replies().defer('text', 'last_edit_time') def get_top_level_replies(self) -> QuerySet: return self.get_replies().exclude(refposts__threads__in=[self]) diff --git a/boards/templates/boards/all_threads.html b/boards/templates/boards/all_threads.html --- a/boards/templates/boards/all_threads.html +++ b/boards/templates/boards/all_threads.html @@ -64,6 +64,7 @@ {% endif %} + •
{% if is_hidden %} @@ -71,6 +72,7 @@ {% endif %}
+ • {% trans 'Gallery' %}

{% if tag.get_description %} diff --git a/boards/tests/test_keys.py b/boards/tests/test_keys.py --- a/boards/tests/test_keys.py +++ b/boards/tests/test_keys.py @@ -65,22 +65,22 @@ class KeyTest(TestCase): '' '' '' - '' + '' 'test_title' - '[post]%s[/post]' - '' - '%s' - '%s' - '' % ( + '[post]{}[/post]' + '' + '{}' + '{}' + ''.format( key.public_key, reply_post.id, key.key_type, - str(post.global_id), + post.global_id, key.public_key, post.id, key.key_type, - str(reply_post.get_pub_time_str()), - post.version, + reply_post.get_pub_time_str(), + reply_post.last_edit_time, ) in response, 'Wrong XML generated for the GET response.') diff --git a/boards/tests/test_sync.py b/boards/tests/test_sync.py --- a/boards/tests/test_sync.py +++ b/boards/tests/test_sync.py @@ -37,13 +37,13 @@ class SyncTest(TestCase): '' '' '' - '' - '%s' - '%s' - '%s' - '%s' - '%s' - '' % ( + '' + '{}' + '{}' + '{}' + '{}' + '{}' + ''.format( post.global_id.key, post.global_id.local_id, post.global_id.key_type, @@ -51,7 +51,7 @@ class SyncTest(TestCase): post.get_sync_text(), post.get_thread().get_tags().first().get_name(), post.get_pub_time_str(), - post.version, + post.last_edit_time, ) in response, 'Wrong response generated for the GET request.') @@ -86,13 +86,13 @@ class SyncTest(TestCase): '' '' '' - '' - '%s' - '%s' - '%s' - '%s' - '%s' - '' % ( + '' + '{}' + '{}' + '{}' + '{}' + '{}' + ''.format( post.global_id.key, post.global_id.local_id, post.global_id.key_type, @@ -100,7 +100,6 @@ class SyncTest(TestCase): post.get_sync_text(), post.get_thread().get_tags().first().get_name(), post.get_pub_time_str(), - post.version, ) in response, 'Wrong response generated for the GET request.') @@ -128,21 +127,21 @@ class SyncTest(TestCase): '' '' '' - '{}' + '{}' '' '' '' - '{}' + '{}' '' ''.format( post.global_id.key, post.global_id.local_id, post.global_id.key_type, - post.version, + post.last_edit_time, post2.global_id.key, post2.global_id.local_id, post2.global_id.key_type, - post2.version, + post2.last_edit_time, ) in response_all, 'Wrong response generated for the LIST request for all posts.') @@ -173,13 +172,13 @@ class SyncTest(TestCase): '' '' '' - '{}' + '{}' '' ''.format( post.global_id.key, post.global_id.local_id, post.global_id.key_type, - post.version, + post.last_edit_time, ) in response_thread, 'Wrong response generated for the LIST request for posts of ' 'existing thread.') @@ -240,13 +239,13 @@ class SyncTest(TestCase): '' '' '' - '{}' + '{}' '' ''.format( post2.global_id.key, post2.global_id.local_id, post2.global_id.key_type, - post2.version, + post2.last_edit_time, ) in response_thread, 'Wrong response generated for the LIST request for posts of ' 'existing thread.') diff --git a/docs/dip-1.markdown b/docs/dip-1.markdown --- a/docs/dip-1.markdown +++ b/docs/dip-1.markdown @@ -97,7 +97,7 @@ Sample response: - 1 + 2017-01-01 00:00:00 diff --git a/docs/dip-2.markdown b/docs/dip-2.markdown --- a/docs/dip-2.markdown +++ b/docs/dip-2.markdown @@ -1,6 +1,6 @@ # 0 Title # -"post" model reference +"post" model reference of version 1.1 # 1 Description # @@ -13,7 +13,7 @@ * title -- text field. * text -- text field. * pub-time -- timestamp (TBD: Define format). -* version -- when post content changes, version should be incremented. +* update -- when post content changes, the update time should be incremented. # 2.2 Optional fields #