| author | ymh <ymh.work@gmail.com> |
| Wed, 20 Jan 2010 12:37:40 +0100 | |
| changeset 3 | 526ebd3988b0 |
| permissions | -rw-r--r-- |
|
3
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
1 |
#!/usr/bin/env python |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
2 |
# -*- coding: UTF-8 -*- |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
3 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
4 |
Title: Dumpscript management command |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
5 |
Project: Hardytools (queryset-refactor version) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
6 |
Author: Will Hardy (http://willhardy.com.au) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
7 |
Date: June 2008 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
8 |
Usage: python manage.py dumpscript appname > scripts/scriptname.py |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
9 |
$Revision: 217 $ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
10 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
11 |
Description: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
12 |
Generates a Python script that will repopulate the database using objects. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
13 |
The advantage of this approach is that it is easy to understand, and more |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
14 |
flexible than directly populating the database, or using XML. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
15 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
16 |
* It also allows for new defaults to take effect and only transfers what is |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
17 |
needed. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
18 |
* If a new database schema has a NEW ATTRIBUTE, it is simply not |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
19 |
populated (using a default value will make the transition smooth :) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
20 |
* If a new database schema REMOVES AN ATTRIBUTE, it is simply ignored |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
21 |
and the data moves across safely (I'm assuming we don't want this |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
22 |
attribute anymore. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
23 |
* Problems may only occur if there is a new model and is now a required |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
24 |
ForeignKey for an existing model. But this is easy to fix by editing the |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
25 |
populate script :) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
26 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
27 |
Improvements: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
28 |
See TODOs and FIXMEs scattered throughout :-) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
29 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
30 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
31 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
32 |
import sys |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
33 |
from django.db import models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
34 |
from django.core.exceptions import ObjectDoesNotExist |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
35 |
from django.core.management.base import BaseCommand |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
36 |
from django.utils.encoding import smart_unicode, force_unicode |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
37 |
from django.contrib.contenttypes.models import ContentType |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
38 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
39 |
class Command(BaseCommand): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
40 |
help = 'Dumps the data as a customised python script.' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
41 |
args = '[appname ...]' |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
42 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
43 |
def handle(self, *app_labels, **options): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
44 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
45 |
# Get the models we want to export |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
46 |
models = get_models(app_labels) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
47 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
48 |
# A dictionary is created to keep track of all the processed objects, |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
49 |
# so that foreign key references can be made using python variable names. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
50 |
# This variable "context" will be passed around like the town bicycle. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
51 |
context = {} |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
52 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
53 |
# Create a dumpscript object and let it format itself as a string |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
54 |
print Script(models=models, context=context) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
55 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
56 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
57 |
def get_models(app_labels): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
58 |
""" Gets a list of models for the given app labels, with some exceptions. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
59 |
TODO: If a required model is referenced, it should also be included. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
60 |
Or at least discovered with a get_or_create() call. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
61 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
62 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
63 |
from django.db.models import get_app, get_apps, get_model |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
64 |
from django.db.models import get_models as get_all_models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
65 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
66 |
# These models are not to be output, e.g. because they can be generated automatically |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
67 |
# TODO: This should be "appname.modelname" string |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
68 |
from django.contrib.contenttypes.models import ContentType |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
69 |
EXCLUDED_MODELS = (ContentType, ) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
70 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
71 |
models = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
72 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
73 |
# If no app labels are given, return all |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
74 |
if not app_labels: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
75 |
for app in get_apps(): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
76 |
models += [ m for m in get_all_models(app) if m not in EXCLUDED_MODELS ] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
77 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
78 |
# Get all relevant apps |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
79 |
for app_label in app_labels: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
80 |
# If a specific model is mentioned, get only that model |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
81 |
if "." in app_label: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
82 |
app_label, model_name = app_label.split(".", 1) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
83 |
models.append(get_model(app_label, model_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
84 |
# Get all models for a given app |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
85 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
86 |
models += [ m for m in get_all_models(get_app(app_label)) if m not in EXCLUDED_MODELS ] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
87 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
88 |
return models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
89 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
90 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
91 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
92 |
class Code(object): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
93 |
""" A snippet of python script. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
94 |
This keeps track of import statements and can be output to a string. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
95 |
In the future, other features such as custom indentation might be included |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
96 |
in this class. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
97 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
98 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
99 |
def __init__(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
100 |
self.imports = {} |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
101 |
self.indent = -1 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
102 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
103 |
def __str__(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
104 |
""" Returns a string representation of this script. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
105 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
106 |
if self.imports: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
107 |
sys.stderr.write(repr(self.import_lines)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
108 |
return flatten_blocks([""] + self.import_lines + [""] + self.lines, num_indents=self.indent) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
109 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
110 |
return flatten_blocks(self.lines, num_indents=self.indent) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
111 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
112 |
def get_import_lines(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
113 |
""" Takes the stored imports and converts them to lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
114 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
115 |
if self.imports: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
116 |
return [ "from %s import %s" % (value, key) for key, value in self.imports.items() ] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
117 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
118 |
return [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
119 |
import_lines = property(get_import_lines) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
120 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
121 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
122 |
class ModelCode(Code): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
123 |
" Produces a python script that can recreate data for a given model class. " |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
124 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
125 |
def __init__(self, model, context={}): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
126 |
self.model = model |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
127 |
self.context = context |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
128 |
self.instances = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
129 |
self.indent = 0 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
130 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
131 |
def get_imports(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
132 |
""" Returns a dictionary of import statements, with the variable being |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
133 |
defined as the key. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
134 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
135 |
return { self.model.__name__: smart_unicode(self.model.__module__) } |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
136 |
imports = property(get_imports) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
137 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
138 |
def get_lines(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
139 |
""" Returns a list of lists or strings, representing the code body. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
140 |
Each list is a block, each string is a statement. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
141 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
142 |
code = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
143 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
144 |
for counter, item in enumerate(self.model.objects.all()): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
145 |
instance = InstanceCode(instance=item, id=counter+1, context=self.context) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
146 |
self.instances.append(instance) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
147 |
if instance.waiting_list: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
148 |
code += instance.lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
149 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
150 |
# After each instance has been processed, try again. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
151 |
# This allows self referencing fields to work. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
152 |
for instance in self.instances: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
153 |
if instance.waiting_list: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
154 |
code += instance.lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
155 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
156 |
return code |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
157 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
158 |
lines = property(get_lines) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
159 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
160 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
161 |
class InstanceCode(Code): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
162 |
" Produces a python script that can recreate data for a given model instance. " |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
163 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
164 |
def __init__(self, instance, id, context={}): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
165 |
""" We need the instance in question and an id """ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
166 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
167 |
self.instance = instance |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
168 |
self.model = self.instance.__class__ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
169 |
self.context = context |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
170 |
self.variable_name = "%s_%s" % (self.instance._meta.db_table, id) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
171 |
self.skip_me = None |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
172 |
self.instantiated = False |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
173 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
174 |
self.indent = 0 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
175 |
self.imports = {} |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
176 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
177 |
self.waiting_list = list(self.model._meta.fields) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
178 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
179 |
self.many_to_many_waiting_list = {} |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
180 |
for field in self.model._meta.many_to_many: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
181 |
self.many_to_many_waiting_list[field] = list(getattr(self.instance, field.name).all()) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
182 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
183 |
def get_lines(self, force=False): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
184 |
""" Returns a list of lists or strings, representing the code body. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
185 |
Each list is a block, each string is a statement. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
186 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
187 |
force (True or False): if an attribute object cannot be included, |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
188 |
it is usually skipped to be processed later. With 'force' set, there |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
189 |
will be no waiting: a get_or_create() call is written instead. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
190 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
191 |
code_lines = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
192 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
193 |
# Don't return anything if this is an instance that should be skipped |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
194 |
if self.skip(): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
195 |
return [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
196 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
197 |
# Initialise our new object |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
198 |
# e.g. model_name_35 = Model() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
199 |
code_lines += self.instantiate() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
200 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
201 |
# Add each field |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
202 |
# e.g. model_name_35.field_one = 1034.91 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
203 |
# model_name_35.field_two = "text" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
204 |
code_lines += self.get_waiting_list() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
205 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
206 |
if force: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
207 |
# TODO: Check that M2M are not affected |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
208 |
code_lines += self.get_waiting_list(force=force) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
209 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
210 |
# Print the save command for our new object |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
211 |
# e.g. model_name_35.save() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
212 |
if code_lines: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
213 |
code_lines.append("%s.save()\n" % (self.variable_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
214 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
215 |
code_lines += self.get_many_to_many_lines(force=force) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
216 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
217 |
return code_lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
218 |
lines = property(get_lines) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
219 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
220 |
def skip(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
221 |
""" Determine whether or not this object should be skipped. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
222 |
If this model is a parent of a single subclassed instance, skip it. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
223 |
The subclassed instance will create this parent instance for us. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
224 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
225 |
TODO: Allow the user to force its creation? |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
226 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
227 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
228 |
if self.skip_me is not None: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
229 |
return self.skip_me |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
230 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
231 |
try: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
232 |
# Django trunk since r7722 uses CollectedObjects instead of dict |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
233 |
from django.db.models.query import CollectedObjects |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
234 |
sub_objects = CollectedObjects() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
235 |
except ImportError: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
236 |
# previous versions don't have CollectedObjects |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
237 |
sub_objects = {} |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
238 |
self.instance._collect_sub_objects(sub_objects) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
239 |
if reduce(lambda x, y: x+y, [self.model in so._meta.parents for so in sub_objects.keys()]) == 1: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
240 |
pk_name = self.instance._meta.pk.name |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
241 |
key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
242 |
self.context[key] = None |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
243 |
self.skip_me = True |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
244 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
245 |
self.skip_me = False |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
246 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
247 |
return self.skip_me |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
248 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
249 |
def instantiate(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
250 |
" Write lines for instantiation " |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
251 |
# e.g. model_name_35 = Model() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
252 |
code_lines = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
253 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
254 |
if not self.instantiated: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
255 |
code_lines.append("%s = %s()" % (self.variable_name, self.model.__name__)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
256 |
self.instantiated = True |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
257 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
258 |
# Store our variable name for future foreign key references |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
259 |
pk_name = self.instance._meta.pk.name |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
260 |
key = '%s_%s' % (self.model.__name__, getattr(self.instance, pk_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
261 |
self.context[key] = self.variable_name |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
262 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
263 |
return code_lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
264 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
265 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
266 |
def get_waiting_list(self, force=False): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
267 |
" Add lines for any waiting fields that can be completed now. " |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
268 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
269 |
code_lines = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
270 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
271 |
# Process normal fields |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
272 |
for field in list(self.waiting_list): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
273 |
try: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
274 |
# Find the value, add the line, remove from waiting list and move on |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
275 |
value = get_attribute_value(self.instance, field, self.context, force=force) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
276 |
code_lines.append('%s.%s = %s' % (self.variable_name, field.name, value)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
277 |
self.waiting_list.remove(field) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
278 |
except SkipValue, e: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
279 |
# Remove from the waiting list and move on |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
280 |
self.waiting_list.remove(field) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
281 |
continue |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
282 |
except DoLater, e: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
283 |
# Move on, maybe next time |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
284 |
continue |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
285 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
286 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
287 |
return code_lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
288 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
289 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
290 |
def get_many_to_many_lines(self, force=False): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
291 |
""" Generates lines that define many to many relations for this instance. """ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
292 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
293 |
lines = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
294 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
295 |
for field, rel_items in self.many_to_many_waiting_list.items(): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
296 |
for rel_item in list(rel_items): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
297 |
try: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
298 |
pk_name = rel_item._meta.pk.name |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
299 |
key = '%s_%s' % (rel_item.__class__.__name__, getattr(rel_item, pk_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
300 |
value = "%s" % self.context[key] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
301 |
lines.append('%s.%s.add(%s)' % (self.variable_name, field.name, value)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
302 |
self.many_to_many_waiting_list[field].remove(rel_item) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
303 |
except KeyError: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
304 |
if force: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
305 |
value = "%s.objects.get(%s=%s)" % (rel_item._meta.object_name, pk_name, getattr(rel_item, pk_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
306 |
lines.append('%s.%s.add(%s)' % (self.variable_name, field.name, value)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
307 |
self.many_to_many_waiting_list[field].remove(rel_item) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
308 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
309 |
if lines: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
310 |
lines.append("") |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
311 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
312 |
return lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
313 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
314 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
315 |
class Script(Code): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
316 |
" Produces a complete python script that can recreate data for the given apps. " |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
317 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
318 |
def __init__(self, models, context={}): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
319 |
self.models = models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
320 |
self.context = context |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
321 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
322 |
self.indent = -1 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
323 |
self.imports = {} |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
324 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
325 |
def get_lines(self): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
326 |
""" Returns a list of lists or strings, representing the code body. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
327 |
Each list is a block, each string is a statement. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
328 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
329 |
code = [ self.FILE_HEADER.strip() ] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
330 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
331 |
# Queue and process the required models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
332 |
for model_class in queue_models(self.models, context=self.context): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
333 |
sys.stderr.write('Processing model: %s\n' % model_class.model.__name__) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
334 |
code.append(model_class.import_lines) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
335 |
code.append("") |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
336 |
code.append(model_class.lines) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
337 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
338 |
# Process left over foreign keys from cyclic models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
339 |
for model in self.models: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
340 |
sys.stderr.write('Re-processing model: %s\n' % model.model.__name__) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
341 |
for instance in model.instances: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
342 |
if instance.waiting_list or instance.many_to_many_waiting_list: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
343 |
code.append(instance.get_lines(force=True)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
344 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
345 |
return code |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
346 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
347 |
lines = property(get_lines) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
348 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
349 |
# A user-friendly file header |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
350 |
FILE_HEADER = """ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
351 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
352 |
#!/usr/bin/env python |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
353 |
# -*- coding: utf-8 -*- |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
354 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
355 |
# This file has been automatically generated, changes may be lost if you |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
356 |
# go and generate it again. It was generated with the following command: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
357 |
# %s |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
358 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
359 |
import datetime |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
360 |
from decimal import Decimal |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
361 |
from django.contrib.contenttypes.models import ContentType |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
362 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
363 |
def run(): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
364 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
365 |
""" % " ".join(sys.argv) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
366 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
367 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
368 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
369 |
# HELPER FUNCTIONS |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
370 |
#------------------------------------------------------------------------------- |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
371 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
372 |
def flatten_blocks(lines, num_indents=-1): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
373 |
""" Takes a list (block) or string (statement) and flattens it into a string |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
374 |
with indentation. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
375 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
376 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
377 |
# The standard indent is four spaces |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
378 |
INDENTATION = " " * 4 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
379 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
380 |
if not lines: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
381 |
return "" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
382 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
383 |
# If this is a string, add the indentation and finish here |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
384 |
if isinstance(lines, basestring): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
385 |
return INDENTATION * num_indents + lines |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
386 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
387 |
# If this is not a string, join the lines and recurse |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
388 |
return "\n".join([ flatten_blocks(line, num_indents+1) for line in lines ]) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
389 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
390 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
391 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
392 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
393 |
def get_attribute_value(item, field, context, force=False): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
394 |
""" Gets a string version of the given attribute's value, like repr() might. """ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
395 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
396 |
# Find the value of the field, catching any database issues |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
397 |
try: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
398 |
value = getattr(item, field.name) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
399 |
except ObjectDoesNotExist: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
400 |
raise SkipValue('Could not find object for %s.%s, ignoring.\n' % (item.__class__.__name__, field.name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
401 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
402 |
# AutoField: We don't include the auto fields, they'll be automatically recreated |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
403 |
if isinstance(field, models.AutoField): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
404 |
raise SkipValue() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
405 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
406 |
# Some databases (eg MySQL) might store boolean values as 0/1, this needs to be cast as a bool |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
407 |
elif isinstance(field, models.BooleanField) and value is not None: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
408 |
return repr(bool(value)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
409 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
410 |
# Post file-storage-refactor, repr() on File/ImageFields no longer returns the path |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
411 |
elif isinstance(field, models.FileField): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
412 |
return repr(force_unicode(value)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
413 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
414 |
# ForeignKey fields, link directly using our stored python variable name |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
415 |
elif isinstance(field, models.ForeignKey) and value is not None: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
416 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
417 |
# Special case for contenttype foreign keys: no need to output any |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
418 |
# content types in this script, as they can be generated again |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
419 |
# automatically. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
420 |
# NB: Not sure if "is" will always work |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
421 |
if field.rel.to is ContentType: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
422 |
return 'ContentType.objects.get(app_label="%s", model="%s")' % (value.app_label, value.model) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
423 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
424 |
# Generate an identifier (key) for this foreign object |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
425 |
pk_name = value._meta.pk.name |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
426 |
key = '%s_%s' % (value.__class__.__name__, getattr(value, pk_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
427 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
428 |
if key in context: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
429 |
variable_name = context[key] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
430 |
# If the context value is set to None, this should be skipped. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
431 |
# This identifies models that have been skipped (inheritance) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
432 |
if variable_name is None: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
433 |
raise SkipValue() |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
434 |
# Return the variable name listed in the context |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
435 |
return "%s" % variable_name |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
436 |
elif force: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
437 |
return "%s.objects.get(%s=%s)" % (value._meta.object_name, pk_name, getattr(value, pk_name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
438 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
439 |
raise DoLater('(FK) %s.%s\n' % (item.__class__.__name__, field.name)) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
440 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
441 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
442 |
# A normal field (e.g. a python built-in) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
443 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
444 |
return repr(value) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
445 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
446 |
def queue_models(models, context): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
447 |
""" Works an an appropriate ordering for the models. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
448 |
This isn't essential, but makes the script look nicer because |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
449 |
more instances can be defined on their first try. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
450 |
""" |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
451 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
452 |
# Max number of cycles allowed before we call it an infinite loop. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
453 |
MAX_CYCLES = 5 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
454 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
455 |
model_queue = [] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
456 |
number_remaining_models = len(models) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
457 |
allowed_cycles = MAX_CYCLES |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
458 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
459 |
while number_remaining_models > 0: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
460 |
previous_number_remaining_models = number_remaining_models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
461 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
462 |
model = models.pop(0) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
463 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
464 |
# If the model is ready to be processed, add it to the list |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
465 |
if check_dependencies(model, model_queue): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
466 |
model_class = ModelCode(model=model, context=context) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
467 |
model_queue.append(model_class) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
468 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
469 |
# Otherwise put the model back at the end of the list |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
470 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
471 |
models.append(model) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
472 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
473 |
# Check for infinite loops. |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
474 |
# This means there is a cyclic foreign key structure |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
475 |
# That cannot be resolved by re-ordering |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
476 |
number_remaining_models = len(models) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
477 |
if number_remaining_models == previous_number_remaining_models: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
478 |
allowed_cycles -= 1 |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
479 |
if allowed_cycles <= 0: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
480 |
# Add the remaining models, but do not remove them from the model list |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
481 |
missing_models = [ ModelCode(model=m, context=context) for m in models ] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
482 |
model_queue += missing_models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
483 |
# Replace the models with the model class objects |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
484 |
# (sure, this is a little bit of hackery) |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
485 |
models[:] = missing_models |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
486 |
break |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
487 |
else: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
488 |
allowed_cycles = MAX_CYCLES |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
489 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
490 |
return model_queue |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
491 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
492 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
493 |
def check_dependencies(model, model_queue): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
494 |
" Check that all the depenedencies for this model are already in the queue. " |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
495 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
496 |
# A list of allowed links: existing fields, itself and the special case ContentType |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
497 |
allowed_links = [ m.model.__name__ for m in model_queue ] + [model.__name__, 'ContentType'] |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
498 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
499 |
# For each ForeignKey or ManyToMany field, check that a link is possible |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
500 |
for field in model._meta.fields + model._meta.many_to_many: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
501 |
if field.rel and field.rel.to.__name__ not in allowed_links: |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
502 |
return False |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
503 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
504 |
return True |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
505 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
506 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
507 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
508 |
# EXCEPTIONS |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
509 |
#------------------------------------------------------------------------------- |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
510 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
511 |
class SkipValue(Exception): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
512 |
""" Value could not be parsed or should simply be skipped. """ |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
513 |
|
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
514 |
class DoLater(Exception): |
|
526ebd3988b0
replace pocketfilms occurence by blinkster
ymh <ymh.work@gmail.com>
parents:
diff
changeset
|
515 |
""" Value could not be parsed or should simply be skipped. """ |