mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Make a start on operations and state (not sure if final layout)
This commit is contained in:
		
							
								
								
									
										1
									
								
								django/db/migrations/operations/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								django/db/migrations/operations/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| from .models import CreateModel, DeleteModel | ||||
							
								
								
									
										38
									
								
								django/db/migrations/operations/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								django/db/migrations/operations/base.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| class Operation(object): | ||||
|     """ | ||||
|     Base class for migration operations. | ||||
|  | ||||
|     It's responsible for both mutating the in-memory model state | ||||
|     (see db/migrations/state.py) to represent what it performs, as well | ||||
|     as actually performing it against a live database. | ||||
|  | ||||
|     Note that some operations won't modify memory state at all (e.g. data | ||||
|     copying operations), and some will need their modifications to be | ||||
|     optionally specified by the user (e.g. custom Python code snippets) | ||||
|     """ | ||||
|  | ||||
|     # If this migration can be run in reverse. | ||||
|     # Some operations are impossible to reverse, like deleting data. | ||||
|     reversible = True | ||||
|  | ||||
|     def state_forwards(self, app, state): | ||||
|         """ | ||||
|         Takes the state from the previous migration, and mutates it | ||||
|         so that it matches what this migration would perform. | ||||
|         """ | ||||
|         raise NotImplementedError() | ||||
|  | ||||
|     def database_forwards(self, app, schema_editor, from_state, to_state): | ||||
|         """ | ||||
|         Performs the mutation on the database schema in the normal | ||||
|         (forwards) direction. | ||||
|         """ | ||||
|         raise NotImplementedError() | ||||
|  | ||||
|     def database_backwards(self, app, schema_editor, from_state, to_state): | ||||
|         """ | ||||
|         Performs the mutation on the database schema in the reverse | ||||
|         direction - e.g. if this were CreateModel, it would in fact | ||||
|         drop the model's table. | ||||
|         """ | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										26
									
								
								django/db/migrations/operations/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								django/db/migrations/operations/models.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| from .base import Operation | ||||
| from django.db.migrations.state import ModelState | ||||
|  | ||||
|  | ||||
| class CreateModel(Operation): | ||||
|     """ | ||||
|     Create a model's table. | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, name): | ||||
|         self.name = name | ||||
|  | ||||
|     def state_forwards(self, app, state): | ||||
|         state.models[app, self.name.lower()] = ModelState(state, app, self.name) | ||||
|  | ||||
|     def database_forwards(self, app, schema_editor, from_state, to_state): | ||||
|         app_cache = to_state.render() | ||||
|         schema_editor.create_model(app_cache.get_model(app, self.name)) | ||||
|  | ||||
|     def database_backwards(self, app, schema_editor, from_state, to_state): | ||||
|         """ | ||||
|         Performs the mutation on the database schema in the reverse | ||||
|         direction - e.g. if this were CreateModel, it would in fact | ||||
|         drop the model's table. | ||||
|         """ | ||||
|         raise NotImplementedError() | ||||
							
								
								
									
										81
									
								
								django/db/migrations/state.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								django/db/migrations/state.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| from django.db import models | ||||
| from django.db.models.loading import BaseAppCache | ||||
|  | ||||
|  | ||||
| class ProjectState(object): | ||||
|     """ | ||||
|     Represents the entire project's overall state. | ||||
|     This is the item that is passed around - we do it here rather than at the | ||||
|     app level so that cross-app FKs/etc. resolve properly. | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, models=None): | ||||
|         self.models = models or {} | ||||
|         self.app_cache = None | ||||
|  | ||||
|     def clone(self): | ||||
|         "Returns an exact copy of this ProjectState" | ||||
|         ps = ProjectState( | ||||
|             models = dict((k, v.copy()) for k, v in self.models.items()) | ||||
|         ) | ||||
|         for model in ps.models.values(): | ||||
|             model.project_state = ps | ||||
|         return ps | ||||
|  | ||||
|     def render(self): | ||||
|         "Turns the project state into actual models in a new AppCache" | ||||
|         if self.app_cache is None: | ||||
|             self.app_cache = BaseAppCache() | ||||
|             for model in self.model.values: | ||||
|                 model.render(self.app_cache) | ||||
|         return self.app_cache | ||||
|  | ||||
|  | ||||
| class ModelState(object): | ||||
|     """ | ||||
|     Represents a Django Model. We don't use the actual Model class | ||||
|     as it's not designed to have its options changed - instead, we | ||||
|     mutate this one and then render it into a Model as required. | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, project_state, app_label, name, fields=None, options=None, bases=None): | ||||
|         self.project_state = project_state | ||||
|         self.app_label = app_label | ||||
|         self.name = name | ||||
|         self.fields = fields or [] | ||||
|         self.options = options or {} | ||||
|         self.bases = bases or None | ||||
|  | ||||
|     def clone(self): | ||||
|         "Returns an exact copy of this ModelState" | ||||
|         return self.__class__( | ||||
|             project_state = self.project_state, | ||||
|             app_label = self.app_label, | ||||
|             name = self.name, | ||||
|             fields = self.fields, | ||||
|             options = self.options, | ||||
|             bases = self.bases, | ||||
|         ) | ||||
|  | ||||
|     def render(self, app_cache): | ||||
|         "Creates a Model object from our current state into the given app_cache" | ||||
|         # First, make a Meta object | ||||
|         meta_contents = {'app_label': self.app_label, "app_cache": app_cache} | ||||
|         meta_contents.update(self.options) | ||||
|         meta = type("Meta", tuple(), meta_contents) | ||||
|         # Then, work out our bases | ||||
|         # TODO: Use the actual bases | ||||
|         if self.bases: | ||||
|             raise NotImplementedError("Custom bases not quite done yet!") | ||||
|         else: | ||||
|             bases = [models.Model] | ||||
|         # Turn fields into a dict for the body, add other bits | ||||
|         body = dict(self.fields) | ||||
|         body['Meta'] = meta | ||||
|         body['__module__'] = "__fake__" | ||||
|         # Then, make a Model object | ||||
|         return type( | ||||
|             self.name, | ||||
|             tuple(bases), | ||||
|             body, | ||||
|         ) | ||||
		Reference in New Issue
	
	Block a user