Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Выбивает вот такую вот ошибку
- (venv) D:projectprobeprojectflasksite>python app.py
- Traceback (most recent call last):
- File "app.py", line 263, in <module>
- class ImageView(sqla.ModelView):
- File "app.py", line 278, in ImageView
- 'path': form.ImageUploadField('Image',
- AttributeError: module 'wtforms.form' has no attribute 'ImageUploadField'
- import os
- import os.path as op
- from sqlalchemy.event import listens_for
- from jinja2 import Markup
- from flask import Flask, Blueprint, render_template, url_for, redirect, request, session, flash, abort
- from flask_sqlalchemy import SQLAlchemy
- from flask_admin import helpers, expose, form
- from flask_admin import helpers as admin_helpers
- import flask_admin as admin
- import flask_login as login
- from flask_admin.contrib import sqla
- from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin, current_user
- from wtforms import form, StringField, PasswordField, BooleanField, validators, fields
- from werkzeug.security import generate_password_hash, check_password_hash
- # Create application
- app = Flask(__name__, static_folder='files')
- app.config['DATABASE_FILE'] = 'sample_db.sqlite'
- app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
- app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
- app.config['SECRET_KEY'] = 'thisissecret'
- db = SQLAlchemy(app)
- # Create directory for file fields to use
- file_path = op.join(op.dirname(__file__), 'static/images/menu-product')
- try:
- os.mkdir(file_path)
- except OSError:
- pass
- # Define models
- roles_users = db.Table(
- 'roles_users',
- db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
- db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
- )
- class Role(RoleMixin, db.Model):
- id = db.Column(db.Integer(), primary_key=True)
- name = db.Column(db.String(80), unique=True)
- description = db.Column(db.String(255))
- def __str__(self):
- return self.name
- # Create models
- class File(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.Unicode(64))
- path = db.Column(db.Unicode(128))
- def __unicode__(self):
- return self.name
- class Image(db.Model):
- id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.Unicode(64))
- path = db.Column(db.Unicode(128))
- def __unicode__(self):
- return self.name
- class User(UserMixin, db.Model):
- id = db.Column(db.Integer, primary_key=True)
- login = db.Column(db.String(255))
- email = db.Column(db.String(50), unique=True)
- password = db.Column(db.String(100))
- active = db.Column(db.Boolean())
- registered_on = db.Column('registered_on', db.DateTime)
- roles = db.relationship('Role', secondary=roles_users,
- backref=db.backref('users', lazy='dynamic'))
- # Flask-Login integration
- def is_authenticated(self):
- return True
- def is_active(self):
- return True
- def is_anonymous(self):
- return False
- def get_id(self):
- return self.id
- # Required for administrative interface
- def __unicode__(self):
- return self.login
- def __repr__(self):
- return '<User %r>' % self.login
- def __str__(self):
- return self.email
- # Setup Flask-Security
- user_datastore = SQLAlchemyUserDatastore(db, User, Role)
- security = Security(app, user_datastore)
- # Define login and registration forms (for flask-login)
- class LoginForm(form.Form):
- user_message = 'Mailing address should be no more than 60 characters'
- user_required = 'Please enter your login.'
- pass_message = 'Password should be no more than 50 characters'
- pass_required = 'Please enter your password.'
- login = fields.StringField('Username', validators=[validators.Length(message=user_message, max=60),
- validators.required(user_required)])
- password = fields.PasswordField('Password', validators=[validators.Length(message=pass_message, max=50),
- validators.required(pass_required)])
- def get_user(self):
- return db.session.query(User).filter_by(login=self.login.data).first()
- def validate_login(self, field):
- user = self.get_user()
- if user is None:
- raise validators.ValidationError('Invalid user')
- # we're comparing the plaintext pw with the the hash from the db
- if not check_password_hash(user.password, self.password.data):
- # to compare plain text passwords use
- # if user.password != self.password.data:
- raise validators.ValidationError('Invalid password')
- class RegistrationForm(form.Form):
- username_message = 'The name must be at least 4 letters and no more than 25 characters'
- username_required = 'Please enter your login.'
- email_address_message = 'Mailing address should be no more than 60 characters'
- email_address_required = 'Please enter your email address.'
- password_message = 'Passwords must match'
- login = fields.StringField('Username', validators=[validators.Length(message=username_message, min=4, max=25),
- validators.required(username_required)])
- email = fields.StringField('Email', validators=[validators.Length(message=email_address_message, max=60),
- validators.required(email_address_required)])
- password = fields.PasswordField('Password', validators=[validators.required(password_message),
- validators.EqualTo('confirm',
- message='Passwords must match')])
- confirm = fields.PasswordField('Repeat Password')
- def validate_login(self, field):
- if db.session.query(User).filter_by(login=self.login.data).count() > 0:
- raise validators.ValidationError('Duplicate username')
- if db.session.query(User).filter_by(email=self.email.data).count() > 0:
- raise validators.ValidationError('Duplicate email')
- # Initialize flask-login
- def init_login():
- login_manager = login.LoginManager()
- login_manager.init_app(app)
- # Create user loader function
- @login_manager.user_loader
- def load_user(user_id):
- return db.session.query(User).get(user_id)
- # Create customized model view class
- class MyModelView(sqla.ModelView):
- def is_accessible(self):
- if not current_user.is_active or not current_user.is_authenticated:
- return False
- if current_user.has_role('superuser'):
- return True
- return False
- def _handle_view(self, name, **kwargs):
- """
- Override builtin _handle_view in order to redirect users when a view is not accessible.
- """
- if not self.is_accessible():
- if current_user.is_authenticated:
- # permission denied
- abort(403)
- else:
- # login
- return redirect(url_for('admin.login_view', next=request.url))
- class MyMasterIndexView(sqla.ModelView):
- def is_accessible(self):
- if not current_user.is_active or not current_user.is_authenticated:
- return False
- if current_user.has_role('user'):
- return True
- return False
- def _handle_view(self, name, **kwargs):
- """
- Override builtin _handle_view in order to redirect users when a view is not accessible.
- """
- if not self.is_accessible():
- if current_user.is_authenticated:
- # permission denied
- abort(403)
- else:
- # login
- return redirect(url_for('admin.login_view', next=request.url))
- # Delete hooks for models, delete files if models are getting deleted
- @listens_for(File, 'after_delete')
- def del_file(mapper, connection, target):
- if target.path:
- try:
- os.remove(op.join(file_path, target.path))
- except OSError:
- # Don't care if was not deleted because it does not exist
- pass
- @listens_for(Image, 'after_delete')
- def del_image(mapper, connection, target):
- if target.path:
- # Delete image
- try:
- os.remove(op.join(file_path, target.path))
- except OSError:
- pass
- # Delete thumbnail
- try:
- os.remove(op.join(file_path,
- form.thumbgen_filename(target.path)))
- except OSError:
- pass
- # Administrative views
- '''
- class FileView(sqla.ModelView):
- # Override form field to use Flask-Admin FileUploadField
- form_overrides = {
- 'path': form.FileUploadField
- }
- # Pass additional parameters to 'path' to FileUploadField constructor
- form_args = {
- 'path': {
- 'label': 'File',
- 'base_path': file_path,
- 'allow_overwrite': False
- }
- }
- '''
- class ImageView(sqla.ModelView):
- def _list_thumbnail(view, context, model, name):
- if not model.path:
- return ''
- return Markup('<img src="%s">' % url_for('static',
- filename=form.thumbgen_filename(model.path)))
- column_formatters = {
- 'path': _list_thumbnail
- }
- # Alternative way to contribute field is to override it completely.
- # In this case, Flask-Admin won't attempt to merge various parameters for the field.
- form_extra_fields = {
- 'path': form.ImageUploadField('Image',
- base_path=file_path,
- thumbnail_size=(100, 100, True))
- }
- # Create customized index view class that handles login & registration
- class MyAdminIndexView(admin.AdminIndexView):
- @expose('/')
- def index(self):
- if not login.current_user.is_authenticated:
- return redirect(url_for('.login_view'))
- return super(MyAdminIndexView, self).index()
- @expose('/login/', methods=['GET', 'POST'])
- def login_view(self):
- # handle user login
- form = LoginForm(request.form)
- if helpers.validate_form_on_submit(form):
- user = form.get_user()
- login.login_user(user)
- if login.current_user.is_authenticated:
- return redirect(url_for('.index'))
- link = '<p>Don't have an account? <a href="' + url_for('.register_view') + '">Click here to register.</a></p>'
- self._template_args['form'] = form
- self._template_args['link'] = link
- return super(MyAdminIndexView, self).index()
- @expose('/register/', methods=['GET', 'POST'])
- def register_view(self):
- form = RegistrationForm(request.form)
- if helpers.validate_form_on_submit(form):
- user = User()
- form.populate_obj(user)
- # we hash the users password to avoid saving it as plaintext in the db,
- # remove to use plain text:
- user.password = generate_password_hash(form.password.data)
- db.session.add(user)
- db.session.commit()
- login.login_user(user)
- return redirect(url_for('.index'))
- link = '<p>Already have an account? <a href="' + url_for('.login_view') + '">Click here to log in.</a></p>'
- self._template_args['form'] = form
- self._template_args['link'] = link
- return super(MyAdminIndexView, self).index()
- @expose('/logout/')
- def logout_view(self):
- login.logout_user()
- return redirect(url_for('.index'))
- # Flask views
- @app.route('/')
- def index():
- return render_template('index.html')
- # Initialize flask-login
- init_login()
- # Create admin
- admin = admin.Admin(app, index_view=MyAdminIndexView(), base_template='my_master.html')
- # Add view
- admin.add_view(MyModelView(User, db.session))
- admin.add_view(MyModelView(Role, db.session))
- #admin.add_view(FileView(File, db.session))
- admin.add_view(ImageView(Image, db.session, name='Order'))
- # define a context processor for merging flask-admin's template context into the
- # flask-security views.
- @security.context_processor
- def security_context_processor():
- return dict(
- admin_base_template=admin.base_template,
- admin_view=admin.index_view,
- h=admin_helpers,
- get_url=url_for
- )
- def build_sample_db():
- """
- Populate a small db with some example entries.
- """
- db.create_all()
- with app.app_context():
- user_role = Role(name='user')
- super_user_role = Role(name='superuser')
- db.session.add(user_role)
- db.session.add(super_user_role)
- db.session.commit()
- test_user = user_datastore.create_user(
- login='Admin',
- email='admin',
- password=generate_password_hash('admin'),
- roles=[super_user_role]
- )
- db.session.add(test_user)
- db.session.commit()
- return
- if __name__ == '__main__':
- # Build a sample db on the fly, if one does not exist yet.
- app_dir = os.path.realpath(os.path.dirname(__file__))
- database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
- if not os.path.exists(database_path):
- build_sample_db()
- # Start app
- app.run(debug=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement