Beispiel #1
0
    def get_app_module(self, module_name):
        import_path = '{0}.{1}'.format(self.app_name, module_name)
        import_filepath = '{0}/{1}.py'.format(self.app_name, module_name)

        try:
            module = import_child(import_path)
        except ImportError:
            raise GeneratorError(
                'Could not import {0}. Make sure {1} exists and does not '
                'contain any syntax '
                'errors.'.format(import_path, import_filepath))

        return module
    def get_app_module(self, module_name):
        import_path = '{0}.{1}'.format(self.app_name, module_name)
        import_filepath = '{0}/{1}.py'.format(self.app_name, module_name)

        try:
            module = import_child(import_path)
        except ImportError:
            raise GeneratorError(
                'Could not import {0}. Make sure {1} exists and does not '
                'contain any syntax '
                'errors.'.format(import_path, import_filepath)
            )

        return module
    def generate_scaffold(self, *args, **options):
        self.verbose = int(options.get('verbosity')) > 1
        self.dry_run = options.get('dry_run', False)
        self.is_timestamped = options.get('is_timestamped', True)
        self.existing_model = options.get('existing_model', None)
        self.timestamp_fieldname = options.get('timestamp_fieldname', None)

        if self.timestamp_fieldname and not self.existing_model:
            raise CommandError(smart_str(_(
                'The --timestamp-field option can only be used if --model '
                'is specified.')))

        try:
            app_name = args[0]
        except IndexError:
            raise CommandError('You must provide an app_name.')

        if app_name not in settings.INSTALLED_APPS:
            raise CommandError(smart_str(_(
                'You must add {0} to your INSTALLED_APPS '
                'in order for {1} to generate templates.'.format(
                    app_name, self.command_name))))

        try:
            app_module = __import__(app_name)
        except ImportError:
            raise CommandError(smart_str(_(
                'Could not import app with name: {0}'.format(app_name))))

        app_dirpath = app_module.__path__[0]

        if not self.existing_model:
            try:
                model_name = args[1]
            except IndexError:
                raise CommandError(
                    smart_str(_('You must provide a model_name.')))
        else:
            model_name = self.existing_model

        app_views_dirpath = os.path.join(app_dirpath, 'views')
        model_views_filename = '{0}_views.py'.format(slugify(model_name))
        model_views_filepath = os.path.join(
            app_views_dirpath, model_views_filename)

        # TODO - Append to views file if already exists
        if os.path.isfile(model_views_filepath):
            raise CommandError(smart_str(_(
                '{0} already exists.'.format(model_views_filepath))))

        pos_args = [a.split(':') for a in args[2:]]
        model_field_args = []
        for a in pos_args:
            # Split for other_model relationship
            split = [item for sublist in a for item in sublist.split('=')]
            model_field_args.append(split)

        if not model_field_args and not self.existing_model:
            # TODO - Allow models with only a primary key?
            raise CommandError(smart_str(_(
                'Cannot generate model with no fields.')))

        for arg in [a for a in model_field_args if len(a) < 2]:
            raise CommandError(smart_str(_(
                'No field type specified for model field: {0}'.format(arg))))

        if not self.existing_model:
            models_generator = ModelsGenerator(app_name)
            try:
                rendered_model, rendered_model_name = \
                    models_generator.render_model(
                        model_name, model_field_args, self.is_timestamped)
            except GeneratorError as err:
                raise CommandError(smart_str(_(
                    'Could not generate model.\n{0}'.format(err))))

        app_urls_filepath = os.path.join(app_dirpath, 'urls.py')
        if not os.path.isfile(app_urls_filepath) and self.dry_run:
            raise CommandError(smart_str(_(
                'It appears you don\'t have a valid URLconf in your '
                '{app_name} app. Please create a valid urls.py file '
                'and try again.\nAlternatively, you can try again without '
                'appending --dry-run to this command, in which case '
                '{cmd_name} will make a valid URLconf for you.'.format(
                    app_name=app_name, cmd_name=self.command_name))))


        with FilesystemTransaction(self.dry_run, self) as transaction:
            ### Generate model ###
            app_models_filepath = os.path.join(app_dirpath, 'models.py')

            if not self.existing_model:
                with transaction.open(app_models_filepath, 'a+') as f:
                    f.write(rendered_model)
                    f.seek(0)
                    self.log(f.read())

                # FIXME - Reload models, use namespace
                reload_django_appcache()
                exec('from {0}.models import *'.format(app_name))

            # The rest of the generators use model introspection to
            # generate views, urlpatterns, etc.
            if not self.existing_model and self.dry_run:
                # Since the model is not actually created on dry run,
                # execute the model code. This is probably a Very Bad
                # Idea.
                with open(app_models_filepath, 'r') as f:
                    code = compile(
                        f.read() + rendered_model, '<string>', 'exec')

                # Ensure django.db.models is available in namespace
                import_child('django.db.models')

                # FIXME - Use namespace dictionary
                exec code in globals()

                # Get reference to generated_model
                code_str = 'generated_model = {0}().__class__'.format(
                        rendered_model_name)
                code = compile(code_str, '<string>', 'exec')
                exec code in globals()
                generated_model = globals()['generated_model']
            else:
                generated_model = get_model(app_name, model_name)

            if not generated_model:
                raise CommandError(smart_str(_(
                    'Something when wrong when generating model '
                    '{0}'.format(model_name))))


            ### Generate views ###
            transaction.mkdir(app_views_dirpath)
            app_views_init_filepath = \
                os.path.join(app_views_dirpath, '__init__.py')

            if os.path.isdir(app_views_init_filepath):
                raise CommandError(smart_str(_(
                    'Could not create file: {0}\n'
                    'Please remove the directory at that location '
                    'and try again.'.format(app_views_init_filepath))))
            elif not os.path.exists(app_views_init_filepath):
                with transaction.open(app_views_init_filepath, 'a+') as f:
                    f.write('')
            else:
                self.msg('exists', app_views_init_filepath)

            views_generator = ViewsGenerator(app_name)
            rendered_views = views_generator.render_views(
                generated_model, self.timestamp_fieldname)

            with transaction.open(model_views_filepath, 'a+') as f:
                f.write(rendered_views)
                f.seek(0)
                self.log(f.read())


            ### Generate URLs ###
            if not os.path.isfile(app_urls_filepath):
                with transaction.open(app_urls_filepath, 'a+') as f:
                    s = 'from django.conf.urls import patterns, url\n\n'
                    f.write(s)
                    f.seek(0)
                    self.log(f.read())
            else:
                self.msg('exists', app_urls_filepath)

            urls_generator = UrlsGenerator(app_name)
            rendered_urls = urls_generator.render_urls(
                generated_model, self.timestamp_fieldname)

            with transaction.open(app_urls_filepath, 'a+') as f:
                f.write(rendered_urls)
                f.seek(0)
                self.log(f.read())


            ### Generate templates ###
            app_templates_root_dirpath = \
                os.path.join(app_dirpath, 'templates')
            transaction.mkdir(app_templates_root_dirpath)

            app_templates_app_dirpath = os.path.join(
                app_templates_root_dirpath, app_name)
            transaction.mkdir(app_templates_app_dirpath)

            model_templates_dirpath = os.path.join(
                app_templates_app_dirpath, slugify(model_name))
            transaction.mkdir(model_templates_dirpath)

            templates_generator = TemplatesGenerator(app_name)

            rendered_templates = templates_generator.render_templates(
                generated_model,
                model_templates_dirpath,
                self.timestamp_fieldname
            )

            for dst_abspath, rendered_template in rendered_templates:
                if os.path.isfile(dst_abspath):
                    self.msg('exists', dst_abspath)
                else:
                    with transaction.open(dst_abspath, 'a+') as f:
                        f.write(rendered_template)
                        f.seek(0)
                        self.log(f.read())


        # Compiled files cause problems when run
        # immediately after generation
        clean_pyc_in_dir(app_dirpath)