PK!%django_markdown_messaging/__init__.pyPK![["django_markdown_messaging/admin.pyfrom django.contrib import admin from .models import Message admin.site.register(Message)PK!!7H]]!django_markdown_messaging/apps.pyfrom django.apps import AppConfig class MessagingConfig(AppConfig): name = 'messaging' PK!V]4django_markdown_messaging/migrations/0001_initial.py# Generated by Django 2.0.6 on 2018-08-20 10:24 from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='Message', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('slug', models.SlugField(max_length=32, unique=True)), ('message', models.TextField()), ('is_editable', models.BooleanField(default=False, verbose_name="Autoriser l'édition")), ('is_deletable', models.BooleanField(default=False, verbose_name='Autoriser la suppression')), ], ), ] PK!0django_markdown_messaging/migrations/__init__.pyPK!B`z  #django_markdown_messaging/models.pyfrom django.db import models from django.db.utils import IntegrityError from django.utils.crypto import get_random_string import markdown def generate_slug(length: int) -> str: """Generate a random slug""" chars = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789' return get_random_string(length, chars) class Message(models.Model): """Model for a message""" slug = models.SlugField(unique=True, max_length=32) message = models.TextField() is_editable = models.BooleanField(default=False, verbose_name="Autoriser l'édition") is_deletable = models.BooleanField(default=False, verbose_name="Autoriser la suppression") @property def markdown(self): return markdown.markdown(self.message, output_format='html5') def save(self, *args, **kwargs): """Custom message saving to add a random slug""" # Three tries to generate unique slug for i in range(0, 3): if not self.slug: self.slug = generate_slug(5) try: super().save(*args, **kwargs) break except IntegrityError: self.slug = generate_slug(5) def __str__(self): return self.slug PK!E 7django_markdown_messaging/templates/messaging/base.html Private messaging
{% block content %}{% endblock %}
PK!=FF?django_markdown_messaging/templates/messaging/edit-message.html{% extends 'messaging/base.html' %} {% block content %}

{% if message %} Message - {{ message.slug }} {% else %} New message {% endif %}

Back
{% csrf_token %} {% if not message %}
{% endif %}
{% endblock %}PK!G??8django_markdown_messaging/templates/messaging/index.html{% extends 'messaging/base.html' %} {% block content %}

Private messaging service

{% if added_slug %}

Message correctly saved: {{ request.META.HTTP_HOST }}{% url 'messaging:message' added_slug %}

Don't forget to save this link in order to share it! :-)

{% endif %} {% if unknown_slug %}

Message {{ unknown_slug }} does not exist.

{% endif %}
{% csrf_token %}

You can also create a new message.

{% endblock %}PK!p:django_markdown_messaging/templates/messaging/message.html{% extends 'messaging/base.html' %} {% load static %} {% block content %}

Message - {{ message.slug }}

Back
{{ message.markdown|safe }}
{% if message.is_editable %} Edit {% endif %} {% if message.is_deletable %} Delete {% endif %} {% endblock %}PK!'<<"django_markdown_messaging/tests.pyfrom django.test import TestCase # Create your tests here. PK!4{!django_markdown_messaging/urls.pyfrom django.urls import path, include from .views import * urlpatterns = [ path('', IndexView.as_view(), name='index'), path('new', NewMessageView.as_view(), name='new-message'), path('/', include([ path('', MessageView.as_view(), name='message'), path('edit/', EditMessageView.as_view(), name='edit-message'), path('delete/', DeleteMessageView.as_view(), name='delete-message'), ])), ]PK!}4+$$"django_markdown_messaging/views.pyfrom django.urls import reverse from django.http import HttpResponseRedirect from django.views.generic import TemplateView from .models import Message import logging class AbstractMessageView(TemplateView): def __init__(self): super(AbstractMessageView, self).__init__() self.logger = logging.getLogger('messaging') def get(self, request, *args, **kwargs): """ Django method to handle a message view. Take a slug as parameter and handle a message """ if not 'slug' in kwargs: return super().get(request, *args, **kwargs) slug = str(kwargs.get('slug', '')) message = self.get_message(slug) if not message: request.session['unknown-slug'] = slug return HttpResponseRedirect(reverse('messaging:index')) return self.handle(request, message) def get_message(self, slug): """Get a message or return none""" try: message = Message.objects.get(slug=slug) except Message.DoesNotExist: self.logger.error("Try to get an unknown message: {}".format(slug)) return None self.logger.info("Get message: {}".format(message.slug)) return message def save_message(self, message): """Save a message""" message.save() self.logger.info("Save message: {}".format(message.slug)) def delete_message(self, message): """Delete a message""" slug = message.slug message.delete() self.logger.info("Delete message: {}".format(slug)) class IndexView(TemplateView): """Index view""" template_name = 'messaging/index.html' def get(self, request): """Handle get request""" context = {} # If we just add a new message if 'added-slug' in request.session: context['added_slug'] = request.session['added-slug'] del request.session['added-slug'] # If we just ask for an unknown message if 'unknown-slug' in request.session: context['unknown_slug'] = request.session['unknown-slug'] del request.session['unknown-slug'] return self.render_to_response(context) def post(self, request): """Handle post request""" value = request.POST.get('slug') if not value: return self.render_to_response({}) return HttpResponseRedirect(reverse('messaging:message', args=[value])) class NewMessageView(AbstractMessageView): """New message view""" template_name = 'messaging/edit-message.html' def post(self, request): """Handle post request""" value = request.POST.get('txtMessage', '') if not value: return self.render_to_response({}) message = Message(message=value, is_editable = request.POST.get('chkIsEditable', '') == 'on', is_deletable = request.POST.get('chkIsDeletable', '') == 'on') self.save_message(message) request.session['added-slug'] = message.slug return HttpResponseRedirect(reverse('messaging:index')) class MessageView(AbstractMessageView): """Message view""" template_name = 'messaging/message.html' def handle(self, request, message): context = { 'message': message } return self.render_to_response(context) class EditMessageView(AbstractMessageView): """Edit message view""" template_name = 'messaging/edit-message.html' def handle(self, request, message): if not message.is_editable: return HttpResponseRedirect(reverse('messaging:message', args=[message.slug])) context = { 'message': message } return self.render_to_response(context) def post(self, request, slug): message = self.get_message(slug) if not message: request.session['unknown-slug'] = slug return HttpResponseRedirect(reverse('messaging:index')) value = request.POST.get('txtMessage', '') if not value: return self.render_to_response({'message': message}) message.message = value self.save_message(message) request.session['added-slug'] = message.slug return HttpResponseRedirect(reverse('messaging:index')) class DeleteMessageView(AbstractMessageView): """Delete message view""" def handle(self, request, message): if not message.is_deletable: return HttpResponseRedirect(reverse('messaging:message', args=[message.slug])) self.delete_message(message) return HttpResponseRedirect(reverse('messaging:index'))PK!1django_markdown_messaging-0.0.1.dist-info/LICENSECopyright 2018 Aloha68 Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. PK!HMWX/django_markdown_messaging-0.0.1.dist-info/WHEEL A н#Z@Z|Jl~6蓅 Λ MU4[PYBpYD*Mͯ#ڪ/̚?ݭ'%nPK!Hy3y* 2django_markdown_messaging-0.0.1.dist-info/METADATAU]o6}篸kb$]Z0#0^ن(bZ؈JRvwIKނ{y=~Wt"NDR 3I(L *ʹ0O^Bk\syZhMQUL#8 A03ˍkVUbNsMx.]!<*eA#biz8f$0h*! ?\*v]kL"? itt$'NZП %h͓6A׽:l_ݎ0*0$emUaas9+o0"ޚrMV28iqq,;-.h+kT]۲{VK6m:WWTm~=4/t~$e7hS#+1֥F᳋sni7M{C.mraN$9 =ҜϤ#׺8!'[-'NA7Jn ]pY'G6L >0|tҨx%;9%ȗsj3}~?Ju9]4N_1uPju(.(;ɻlۄmJgH{asiMa,*W I ;V{6pI ɑ&g@ )-ribEMY5j-{0EFz6ip K3QnG}! B(SԢp_`ߚ[1bzϞN_:_"zJDk/V9-sKB}B^9@)RKZϯ}GćFRL(_3¤FuA7iͤ%Z1.zUP @mDު.,F.47 h) XT$QPK!H~0django_markdown_messaging-0.0.1.dist-info/RECORDI8{H/> !l!@8}sBOkZNfa}lqQeNMTqޢ(orEnF[LOSWp։=>J"]ִitޓ7{GFi7/t("\G܃fW;ѷQmׂn|}Sr{XuDM0{uKe}JngC 0 ~<^W;-cdR*s/Yǣ ߬qubTZ]FOj34 flDpW!*`|wGZP;" %1a4M9D/?&plt6J:7`o٧ 3M v;0V+=Qx͔#s62O40kXbI.e(vJȵ=r0&3AFO7LtHUmsC;Z!B"6ߤѼoAMGcDW˙R.+E}!,||E&Wp޽ІtOL"\*)y@ V]NR/!${kDZm7bWoCXP0" eі_PK!%django_markdown_messaging/__init__.pyPK![["Cdjango_markdown_messaging/admin.pyPK!!7H]]!django_markdown_messaging/apps.pyPK!V]4zdjango_markdown_messaging/migrations/0001_initial.pyPK!0django_markdown_messaging/migrations/__init__.pyPK!B`z  #django_markdown_messaging/models.pyPK!E 7a django_markdown_messaging/templates/messaging/base.htmlPK!=FF?django_markdown_messaging/templates/messaging/edit-message.htmlPK!G??8udjango_markdown_messaging/templates/messaging/index.htmlPK!p: django_markdown_messaging/templates/messaging/message.htmlPK!'<<"\django_markdown_messaging/tests.pyPK!4{!django_markdown_messaging/urls.pyPK!}4+$$"django_markdown_messaging/views.pyPK!12/django_markdown_messaging-0.0.1.dist-info/LICENSEPK!HMWX/^2django_markdown_messaging-0.0.1.dist-info/WHEELPK!Hy3y* 23django_markdown_messaging-0.0.1.dist-info/METADATAPK!H~06django_markdown_messaging-0.0.1.dist-info/RECORDPK H: