{ "info": { "author": "Albert O'Connor", "author_email": "info@albertoconnor.ca", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 2.7" ], "description": "# Drift\n\nDrift 0.0.5 supports Django 1.7 migrations.\n\nMake pages and models easily editable directly by users.\n\nUsing an approach similar to the Django admin and using some new style content editable approach to make a better user experience.\n\nMore docs, source and examples coming soon.\n\n## History\n\n### 0.0.6\n\n* Modifying `contrib.versionedpages` to prevent deletion on content when\n users are deleted using `on_delete=models.SET_NULL`.\n\n### 0.0.5\n\n* Breaking change, `content.get_form` now requires request be passed in\n as the first argument. Where you have `content.get_form(request.POST)`\n make it `content.get_form(request, request.POST)`. This make translation\n using django-hvad possible.\n\n# Tutorial: Creating a Custom Content Type\n\nGenerally a content type will live in its own app which contains the models which back the content type, the content class which is used in the views to control how the type is managed.\n\n## Model\n\nStart with a pretty simple model.\n\n```\n#python\n class Foo(models.Model):\n name = models.CharField(max_length=256)\n slug = models.SlugField()\n description = models.TextField()\n\n published = models.BooleanField(default=True)\n\n created = models.DateTimeField(auto_now_add=True)\n updated = models.DateTimeField(auto_now=True)\n\n @models.permalink\n def get_absolute_url(self):\n return ('foo', [self.slug])\n\n def __unicode__(self):\n return self.name\n```\n\nThis simple Foo model has a title and description. Generally in the CMS you will want to link to the instances of Foo so having both a `slug` and a `get_absolute_url` is highly recommended.\n\n## Urls and Admin\n\nNext update urls.py to allow our `get_absolute_url` function to kind of work. We will need views before they can.\n\n```\n#!python\n\nfrom django.conf.urls import patterns, url\n\nfrom . import views\n\nurlpatterns = patterns('',\n url(r'^$', views.foos, name=\"foo_list\"),\n url(r'^\\+new/$', edit_foo, name=\"edit_foo\"),\n url(r'^(.+)/edit/$', edit_foo, name=\"edit_foo\"),\n url(r'^(.*)/$', foo, name=\"foo\"),\n)\n```\n\nWe also need register the model in the admin, by default drift provides an admin link to edit the item in the admin if that is what is preferred.\n\n```\n#python\nfrom django.contrib import admin\n\nfrom .models import Foo\n\nadmin.site.register(Foo)\n```\n\n## Content\n\nBefore we write the critical views.py and template, let's take a moment to implement the special content.py and object which makes editing the content type through the interface possible. This should feel pretty similar to the admin.\n\n```\n#!python\nfrom django.core.urlresolvers import reverse_lazy\n\nfrom drift import content\n\nfrom .models import Foo\n\nclass FooContent(content.ModelContent):\n name = \"Foo\"\n contenteditable = ('name', 'description')\n exclude = ('published',)\n prepopulated_fields = {'slug': 'name'}\n\n def get_new_url(self):\n return reverse_lazy('new_foo')\n\n def get_edit_url(self):\n if self.instance is not None:\n return reverse_lazy('edit_foo', args=[self.instance.slug])\n return None\n\ncontent.system.register(Foo, FooContent)\n```\n\n`contenteditable` means the field can be edited inline using some special widgets provided by drift. If it isn't listed as `contenteditable` than it appear in the \"Content Settings\" section of the editing page.\n\n## Views\n\nFinally views and templates need to be created. We need 3 views, viewing a foo, editing a foo and publishing a foo.\n\n```\n#python\nfrom django.shortcuts import render, get_object_or_404, redirect\nfrom django.views.decorators.http import require_POST\nfrom django.contrib.auth.decorators import login_required\n\nfrom drift.content import make_content\n\nfrom .models import Foo\n\n\ndef foos(request, template=\"foo_list.html\"):\n foos = Foo.objects.filter(published=True)\n return render(\n request,\n template,\n dict(\n content=make_content(Foo),\n foos=foos,\n ),\n )\n\n\ndef foo(request, slug, template=\"foo.html\"):\n foo = get_object_or_404(Foo, slug=slug)\n\n return render(\n request,\n template,\n dict(\n content=make_content(foo),\n ),\n )\n\n\n@login_required\ndef edit_foo(request, slug=None, template=\"edit_foo.html\"):\n if slug is None:\n foo = Foo()\n create = True\n else:\n foo = get_object_or_404(Foo, slug=slug)\n create = False\n\n content = make_content(foo, request, 'create' if create else 'edit')\n\n if request.method == \"POST\":\n form = content.get_form(request, request.POST)\n if form.is_valid():\n foo = form.save()\n return redirect('foo', foo.slug)\n\n return render(\n request,\n template,\n dict(\n edit=True,\n content=content,\n ),\n )\n\n```\n\n## Templates\n\nDefine your foo_list.html, foo.html and edit_foo.html templates and you should be ready to test.\n\n```\n#html\n{% extends 'base.html' %}\n\n{% block head_css %}\n {{ block.super }}\n {% if user.is_staff %}\n \n {% endif %}\n{% endblock head_css %}\n\n{% block head_js %}\n {{ block.super }}\n\n {% if user.is_staff %}\n \n \n {% endif %}\n{% endblock head_js %}\n\n{% block contents %}\n{% include 'content/control_panel.html' %}\n

Foos

\n {% for foo in foos %}\n

\n {{ foo.name }}\n

\n {% endfor %}\n{% endblock contents %}\n```\n\n```\n#html\n{% extends 'base.html' %}\n\n{% block head_css %}\n {{ block.super }}\n {% if user.is_staff %}\n \n {% endif %}\n{% endblock head_css %}\n\n{% block head_js %}\n {{ block.super }}\n\n {% if user.is_staff %}\n \n \n {% endif %}\n{% endblock head_js %}\n\n{% block contents %}\n{% include 'content/control_panel.html' %}\n

{{ content.instance.name }}

\n
\n {{ version.description|safe }}\n
\n{% endblock contents %}\n```\n\n```\n#html\n{% extends 'base.html' %}\n\n{% block head_css %}\n {{ block.super }}\n {% if user.is_staff %}\n \n {% endif %}\n{% endblock head_css %}\n\n{% block head_js %}\n {{ block.super }}\n {% if user.is_staff %}\n \n {% include 'content/editor_header.html' %}\n {# TODO: refactor in to a shared template which still exposed a hook or customize from the editor #}\n \n \n {% endif %}\n{% endblock head_js %}\n\n{% block contents %}\n
\n {% csrf_token %}\n {% include 'content/control_panel.html' %}\n\n

{{ content.form.name }}

\n\n
\n

Content Settings

\n {% for field in content.form.non_contenteditable_fields %}\n {% with field.field as field %}\n {% include \"_field.html\" %}\n {% endwith %}\n {% endfor %}\n
\n\n \n
\n{% endblock %}\n```\n\n# Url hookup\n\nYou need to include your foo/urls.py in your site urls.py.\n\nOnce this is done you should be able to sign in, go to the url you hooked up, and use the header to create a new Foo object. You can see you list of Foo objects and edit them. The pre-populate for the slug should also work.", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/amjoconn/drift", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "drift", "package_url": "https://pypi.org/project/drift/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/drift/", "project_urls": { "Homepage": "https://bitbucket.org/amjoconn/drift" }, "release_url": "https://pypi.org/project/drift/0.0.7/", "requires_dist": null, "requires_python": "", "summary": "Make editing content directly easier for CMS authors and users.", "version": "0.0.7" }, "last_serial": 2978055, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "5d7bebc1c8736f262a798c1cb7147517", "sha256": "30974d6b99bef04a1ce1dd1229d2a44853d35f061d138a4752e3a4b6ab21e4a8" }, "downloads": -1, "filename": "drift-0.0.1.tar.gz", "has_sig": false, "md5_digest": "5d7bebc1c8736f262a798c1cb7147517", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3345, "upload_time": "2014-06-11T19:36:30", "url": "https://files.pythonhosted.org/packages/97/3e/dbe033e849a44e685801fa93ff9820f06ea0d3c5cc467ba2ee03bea775ed/drift-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "10c01e395ed7e6641d51ffba6eaa3ee6", "sha256": "04bc492b72dcb9510eab60221bd0463e27b3fa6b0e29eeac8e1cef564f6960b3" }, "downloads": -1, "filename": "drift-0.0.2.tar.gz", "has_sig": false, "md5_digest": "10c01e395ed7e6641d51ffba6eaa3ee6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 63940, "upload_time": "2014-06-11T19:48:57", "url": "https://files.pythonhosted.org/packages/e3/15/abe31e9619fc3104760726ebc7f45b4ef01bda5478bf7896e01937ace3a8/drift-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "09b765056340839106f8873643ea4e33", "sha256": "9295801e7b8468030fd8429c4546e1d9e624b06c184b7e065d6a2d6bda4ed934" }, "downloads": -1, "filename": "drift-0.0.3.tar.gz", "has_sig": false, "md5_digest": "09b765056340839106f8873643ea4e33", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 63916, "upload_time": "2014-06-12T11:10:18", "url": "https://files.pythonhosted.org/packages/83/70/abf7892efa4abb117abed094168ee9694bac3eb5c3beb52f93ca54e115ae/drift-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "4334a80d269a8264a094a92dd59a0a20", "sha256": "06e4c90a309efdc1a4562c5529b9051417fe4769cb7d6ef5bd921a3b7226c59d" }, "downloads": -1, "filename": "drift-0.0.4.tar.gz", "has_sig": false, "md5_digest": "4334a80d269a8264a094a92dd59a0a20", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 63961, "upload_time": "2014-07-08T18:37:18", "url": "https://files.pythonhosted.org/packages/fe/88/0e4348af56f29af4c9423716e8119d86850aca3f8d80f0f3cbaed2c01f38/drift-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "0432bee1e82f1a67af78d42985b521d9", "sha256": "5f828b6ca8a703c988885ff5c7b6113a560bad0542f82f7e1a58c6adb91aea90" }, "downloads": -1, "filename": "drift-0.0.5-py2-none-any.whl", "has_sig": false, "md5_digest": "0432bee1e82f1a67af78d42985b521d9", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 100884, "upload_time": "2015-04-27T19:31:01", "url": "https://files.pythonhosted.org/packages/6e/a1/e6a348738309bbc7b2a3b015bee0a917c5fad9ddabfd910f0e62026e74c4/drift-0.0.5-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "afd622b76e9a8b89d26b8b483259f3c1", "sha256": "0b5416641d862bd7486ff4351b5a6742624891849f0cdfc89e5667e2411c6bbd" }, "downloads": -1, "filename": "drift-0.0.5.tar.gz", "has_sig": false, "md5_digest": "afd622b76e9a8b89d26b8b483259f3c1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 66300, "upload_time": "2015-04-27T19:31:05", "url": "https://files.pythonhosted.org/packages/39/42/62af07eaa8e20cb929ca7a3cb068a3089505df8d1da7a7cadb92bbe27ede/drift-0.0.5.tar.gz" } ], "0.0.6": [], "0.0.7": [ { "comment_text": "", "digests": { "md5": "6977d0624000bf37b9e1cac037164799", "sha256": "b12f4a26453808d5274cc58d7ef7304ccb59e76eb636a2dd8ce66c13f55a1bc6" }, "downloads": -1, "filename": "drift-0.0.7.tar.gz", "has_sig": false, "md5_digest": "6977d0624000bf37b9e1cac037164799", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 67119, "upload_time": "2017-06-25T21:28:37", "url": "https://files.pythonhosted.org/packages/8f/2b/bd4141a10054145139ed534e7a6da1df42f387c73265b9e9bac3d1efa010/drift-0.0.7.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6977d0624000bf37b9e1cac037164799", "sha256": "b12f4a26453808d5274cc58d7ef7304ccb59e76eb636a2dd8ce66c13f55a1bc6" }, "downloads": -1, "filename": "drift-0.0.7.tar.gz", "has_sig": false, "md5_digest": "6977d0624000bf37b9e1cac037164799", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 67119, "upload_time": "2017-06-25T21:28:37", "url": "https://files.pythonhosted.org/packages/8f/2b/bd4141a10054145139ed534e7a6da1df42f387c73265b9e9bac3d1efa010/drift-0.0.7.tar.gz" } ] }