Commit a45cdf15a03943b70ca7fc9675a00811ef4f707a
- Diff rendering mode:
- inline
- side by side
admin.py
(5 / 0)
|   | |||
| 20 | 20 | import comment | |
| 21 | 21 | ||
| 22 | 22 | sys.path.append('node') | |
| 23 | sys.path.append('admin') | ||
| 23 | 24 | import recipe | |
| 25 | import load | ||
| 24 | 26 | ||
| 25 | 27 | import migrate | |
| 26 | 28 | ||
| … | … | ||
| 78 | 78 | # comments | |
| 79 | 79 | ('/admin/comment/', comment.Index), | |
| 80 | 80 | ('/admin/comment/del.html', comment.Del), | |
| 81 | |||
| 82 | # load | ||
| 83 | ('/admin/load/', load.Import), | ||
| 81 | 84 | ||
| 82 | 85 | # migrations | |
| 83 | 86 | ('/admin/migrate/', migrate.Migrate), |
admin/load.py
(127 / 0)
|   | |||
| 1 | ## ---------------------------------------------------------------------------- | ||
| 2 | # import standard modules | ||
| 3 | import re | ||
| 4 | import logging | ||
| 5 | import sys | ||
| 6 | import yaml | ||
| 7 | import datetime | ||
| 8 | |||
| 9 | # Google specific modules | ||
| 10 | from google.appengine.ext import db | ||
| 11 | from google.appengine.api.labs.taskqueue import Task | ||
| 12 | from google.appengine.api.datastore_errors import BadKeyError | ||
| 13 | from django.utils import simplejson | ||
| 14 | |||
| 15 | # local modules | ||
| 16 | sys.path.append("..") | ||
| 17 | from models import Section, Page, Recipe, Comment | ||
| 18 | import models | ||
| 19 | import webbase | ||
| 20 | import formbase | ||
| 21 | import util | ||
| 22 | |||
| 23 | ## ---------------------------------------------------------------------------- | ||
| 24 | |||
| 25 | class Import(webbase.WebBase): | ||
| 26 | def get(self): | ||
| 27 | vals = { | ||
| 28 | 'sections' : Section.all(), | ||
| 29 | 'node_types' : models.node_choices, | ||
| 30 | 'title' : 'Import a node', | ||
| 31 | 'data_types' : [ | ||
| 32 | { 'value' : 'json', 'text' : 'JSON' }, | ||
| 33 | { 'value' : 'yaml', 'text' : 'YAML' }, | ||
| 34 | ], | ||
| 35 | } | ||
| 36 | self.template( 'load-form.html', vals, 'admin' ); | ||
| 37 | |||
| 38 | def post(self): | ||
| 39 | msgs = [] | ||
| 40 | section = None | ||
| 41 | try: | ||
| 42 | section = Section.get( self.request.get('section') ) | ||
| 43 | except BadKeyError: | ||
| 44 | # invalid key, try again | ||
| 45 | self.redirect('.') | ||
| 46 | |||
| 47 | node_type = self.request.get('node_type') | ||
| 48 | data_input = self.request.get('data_input') | ||
| 49 | data_type = self.request.get('data_type') | ||
| 50 | data = None | ||
| 51 | if data_type == 'json': | ||
| 52 | logging.info(data_input) | ||
| 53 | data = simplejson.loads( data_input ) | ||
| 54 | elif data_type == 'yaml': | ||
| 55 | data = yaml.load( data_input ) | ||
| 56 | else: | ||
| 57 | # someone is messing with the input params | ||
| 58 | self.redirect('.') | ||
| 59 | |||
| 60 | logging.info(data) | ||
| 61 | |||
| 62 | # figure out what this node_type is | ||
| 63 | item = None | ||
| 64 | if node_type == 'page': | ||
| 65 | item = Page( | ||
| 66 | section = Section.get( self.request.get('section') ), | ||
| 67 | name = data['name'], | ||
| 68 | title = data['title'], | ||
| 69 | content = data['content'], | ||
| 70 | type = data['type'], | ||
| 71 | label_raw = ' '.join( data['label'] ), | ||
| 72 | attribute_raw = ' '.join( data['attribute'] ), | ||
| 73 | inserted = util.str_to_datetime( data['inserted'] ), | ||
| 74 | updated = util.str_to_datetime( data['updated'] ), | ||
| 75 | ) | ||
| 76 | logging.info('here1') | ||
| 77 | |||
| 78 | elif node_type == 'recipe': | ||
| 79 | item = Recipe( | ||
| 80 | section = Section.get( self.request.get('section') ), | ||
| 81 | name = data['name'], | ||
| 82 | title = data['title'], | ||
| 83 | intro = data['intro'], | ||
| 84 | serves = data['serves'], | ||
| 85 | ingredients = data['ingredients'], | ||
| 86 | method = data['method'], | ||
| 87 | type = data['type'], | ||
| 88 | label_raw = ' '.join( data['label'] ), | ||
| 89 | attribute_raw = ' '.join( data['attribute'] ), | ||
| 90 | inserted = util.str_to_datetime( data['inserted'] ), | ||
| 91 | updated = util.str_to_datetime( data['updated'] ), | ||
| 92 | ) | ||
| 93 | logging.info('here2') | ||
| 94 | |||
| 95 | else: | ||
| 96 | # again, someone is messing with the input params | ||
| 97 | self.redirect('.') | ||
| 98 | |||
| 99 | # regenerate this item | ||
| 100 | item.set_derivatives() | ||
| 101 | item.put() | ||
| 102 | item.section.regenerate() | ||
| 103 | |||
| 104 | msgs.append( 'Added node [%s, %s]' % (item.name, item.title) ) | ||
| 105 | |||
| 106 | if 'comments' in data: | ||
| 107 | for comment in data['comments']: | ||
| 108 | # load each comment in against this node | ||
| 109 | comment = Comment( | ||
| 110 | node = item, | ||
| 111 | name = comment['name'], | ||
| 112 | email = comment['email'], | ||
| 113 | website = comment['website'], | ||
| 114 | comment = comment['comment'], | ||
| 115 | comment_html = util.render(comment['comment'], 'text'), | ||
| 116 | inserted = util.str_to_datetime( comment['inserted'] ), | ||
| 117 | updated = util.str_to_datetime( comment['updated'] ), | ||
| 118 | ) | ||
| 119 | comment.put() | ||
| 120 | msgs.append( 'Added comment [%s, %s]' % (comment.name, comment.email) ) | ||
| 121 | |||
| 122 | # now that we've added some comments, make the node regenerate | ||
| 123 | item.regenerate() | ||
| 124 | |||
| 125 | self.template( 'load-import.html', { 'msgs' : msgs }, 'admin' ); | ||
| 126 | |||
| 127 | ## ---------------------------------------------------------------------------- |
issues/c_6cb461af.cil
(6 / 0)
|   | |||
| 1 | Issue: b17f8ceb | ||
| 2 | CreatedBy: Andrew Chilton <andychilton@gmail.com> | ||
| 3 | Inserted: 2009-12-23T05:48:48 | ||
| 4 | Updated: 2009-12-23T07:05:42 | ||
| 5 | |||
| 6 | Also going to add the ability to load in JSON (as well as YAML). |
issues/i_b17f8ceb.cil
(3 / 2)
|   | |||
| 1 | 1 | Summary: Add an import page so we can manually do old entries | |
| 2 | Status: InProgress | ||
| 2 | Status: Finished | ||
| 3 | 3 | CreatedBy: Andrew Chilton <andychilton@gmail.com> | |
| 4 | 4 | AssignedTo: Andrew Chilton <andychilton@gmail.com> | |
| 5 | 5 | Label: Milestone-v0.04 | |
| 6 | Comment: 6cb461af | ||
| 6 | 7 | Inserted: 2009-12-22T10:07:57 | |
| 7 | Updated: 2009-12-22T10:13:51 | ||
| 8 | Updated: 2009-12-23T08:43:11 | ||
| 8 | 9 | ||
| 9 | 10 | After playing with the remote_api and it being just terrible, and also looking | |
| 10 | 11 | at the bulk loader and it being overly complicated, I've decided to just have a |
models.py
(1 / 0)
|   | |||
| 21 | 21 | # * updated = db.DateTimeProperty( auto_now = True ) | |
| 22 | 22 | ||
| 23 | 23 | type_choices = ["text", "code", "phliky", "textile", "html", "markdown"] | |
| 24 | node_choices = ['page', 'recipe'] | ||
| 24 | 25 | layout_choices = ['content', 'blog', 'faq'] | |
| 25 | 26 | ||
| 26 | 27 | ## ---------------------------------------------------------------------------- |
theme/admin/load-form.html
(58 / 0)
|   | |||
| 1 | {% extends "wrapper.html" %} | ||
| 2 | |||
| 3 | {% block content %} | ||
| 4 | |||
| 5 | <h2>Import a Node (with Comments)</h2> | ||
| 6 | |||
| 7 | <form method="post" action=""> | ||
| 8 | |||
| 9 | <table class="edit"> | ||
| 10 | <tbody> | ||
| 11 | |||
| 12 | <tr> | ||
| 13 | <th><label for="id_section">Section:</label></th> | ||
| 14 | <td> | ||
| 15 | <select id="id_section" name="section"> | ||
| 16 | <option value="">Select...</option> | ||
| 17 | {% for section in sections %} | ||
| 18 | <option value="{{ section.key|urlencode }}"{% ifequal section.key item.section.key %} selected="selected"{% endifequal %}>{{ section.path|escape }}</option> | ||
| 19 | {% endfor %} | ||
| 20 | </select> | ||
| 21 | </td> | ||
| 22 | </tr> | ||
| 23 | |||
| 24 | <tr> | ||
| 25 | <th><label for="id_node_type">Node Type:</label></th> | ||
| 26 | <td> | ||
| 27 | <select id="id_node_type" name="node_type"> | ||
| 28 | <option value="">Select...</option> | ||
| 29 | {% for node_type in node_types %} | ||
| 30 | <option value="{{ node_type|escape }}">{{ node_type|escape }}</option> | ||
| 31 | {% endfor %} | ||
| 32 | </select> | ||
| 33 | </td> | ||
| 34 | </tr> | ||
| 35 | |||
| 36 | <tr> | ||
| 37 | <th><label for="id_data">Data:</label></th> | ||
| 38 | <td><textarea id="id_data" name="data_input" class="large"></textarea></td> | ||
| 39 | </tr> | ||
| 40 | |||
| 41 | <tr> | ||
| 42 | <th><label for="id_data_type">Data Type:</label></th> | ||
| 43 | <td> | ||
| 44 | {% for data_type in data_types %} | ||
| 45 | <input type="radio" id="id_data_type" name="data_type" value="{{ data_type.value|escape }}"{% if forloop.first %} checked="checked"{% endif %} /> {{ data_type.text|escape }} | ||
| 46 | {% if not forloop.last %}<br />{% endif %} | ||
| 47 | {% endfor %} | ||
| 48 | </td> | ||
| 49 | </tr> | ||
| 50 | |||
| 51 | </tbody> | ||
| 52 | </table> | ||
| 53 | |||
| 54 | <input type="submit"/> | ||
| 55 | |||
| 56 | </form> | ||
| 57 | |||
| 58 | {% endblock %} |
theme/admin/load-import.html
(15 / 0)
|   | |||
| 1 | {% extends "wrapper.html" %} | ||
| 2 | |||
| 3 | {% block content %} | ||
| 4 | |||
| 5 | <h2>Node Imported</h2> | ||
| 6 | |||
| 7 | <ul> | ||
| 8 | {% for msg in msgs %} | ||
| 9 | <li>{{ msg|escape }}</li> | ||
| 10 | {% endfor %} | ||
| 11 | </ul> | ||
| 12 | |||
| 13 | <p><a href=".">Import Another</a></p> | ||
| 14 | |||
| 15 | {% endblock %} |
theme/admin/page-form.html
(2 / 2)
|   | |||
| 26 | 26 | <select id="id_section" name="section"> | |
| 27 | 27 | <option value="">Select...</option> | |
| 28 | 28 | {% for section in sections %} | |
| 29 | <option value="{{ section.key|urlencode }}"{% ifequal section.key item.section.key %} selected="selected"{% endifequal %}>{{ section.path|escape }}</option> | ||
| 29 | <option value="{{ section.key|escape }}"{% ifequal section.key item.section.key %} selected="selected"{% endifequal %}>{{ section.path|escape }}</option> | ||
| 30 | 30 | {% endfor %} | |
| 31 | 31 | </select> | |
| 32 | 32 | </td> | |
| … | … | ||
| 44 | 44 | ||
| 45 | 45 | <tr> | |
| 46 | 46 | <th><label for="id_content">Content:</label></th> | |
| 47 | <td><textarea id="id_content" name="content" class="content">{{ item.content|escape }}</textarea></td> | ||
| 47 | <td><textarea id="id_content" name="content" class="medium">{{ item.content|escape }}</textarea></td> | ||
| 48 | 48 | </tr> | |
| 49 | 49 | ||
| 50 | 50 | <tr> |
theme/admin/wrapper.html
(3 / 0)
|   | |||
| 50 | 50 | <li> | |
| 51 | 51 | <a href="/admin/recipe/">Recipe</a> (<a href="/admin/recipe/new.html">New</a>) | |
| 52 | 52 | </li> | |
| 53 | <li> | ||
| 54 | <a href="/admin/load/">Import</a> | ||
| 55 | </li> | ||
| 53 | 56 | </ul> | |
| 54 | 57 | </li> | |
| 55 | 58 | <li> |
util.py
(8 / 0)
|   | |||
| 7 | 7 | import sys | |
| 8 | 8 | import cgi | |
| 9 | 9 | import re | |
| 10 | import datetime | ||
| 11 | import re | ||
| 10 | 12 | ||
| 11 | 13 | ## ---------------------------------------------------------------------------- | |
| 12 | 14 | # local modules | |
| … | … | ||
| 78 | 78 | name = re.sub(r'-$', '', name ) | |
| 79 | 79 | ||
| 80 | 80 | return name | |
| 81 | |||
| 82 | def str_to_datetime(str): | ||
| 83 | """ takes strings of the form yyyy-mm-dd hh:mm:ss and returns a datetime """ | ||
| 84 | a = [ int(x) for x in re.split(r'[ \-:]', str) ] | ||
| 85 | dt = datetime.datetime(a[0], a[1], a[2], a[3], a[4], a[5]) | ||
| 86 | return dt | ||
| 81 | 87 | ||
| 82 | 88 | ## ---------------------------------------------------------------------------- |

