2016-10-23 2 views
0

Эй, может кто-нибудь скажет мне, что я делаю неправильно в своем коде? Я хочу проверить, нет ли имени пользователя в базе данных или нет.FLASK SQlite Python - Проверка, что имя пользователя уже есть в базе данных

Целый маршрут. Это не даст мне никаких ошибок, но также не заполнит мою базу данных.

@app.route('/regist', methods=['GET', 'POST']) 
def regist(): 
    if request.method == "POST": 
     with sql.connect("database.db") as con: 
      cur = con.cursor() 
     try: 
      # flash("register attempted") 

      username = request.form['username'] 
      password = request.form['password'] 
      passwordencr = request.form['password'] 
      email = request.form['email'] 

      x = cur.execute("SELECT * FROM users WHERE name = ?", (username)) 

      if int(len(x)) > 0: 
       flash("That username is already taken, please choose another") 
       return render_template('register.html') 
      else: 
       cur.execute("INSERT INTO users (name,password,email) VALUES (?,?,?)",(username,passwordencr,email)) 

       con.commit() 
       flash ("Successfully registrated") 
     except: 
      con.rollback() 
      msg = "error in insert operation" 

     finally: 
      session['logged_in'] = True 
      session['username'] = username 
      gc.collect() 
      msg = Message('Hello', sender='[email protected]', recipients=[email]) 
      msg.body = "your username for ak047 is: %s and your password is %s" %(username,password) 
      mail.send(msg) 
      return render_template("home.html", msg=msg) 
      con.close() 
      gc.collect() 
+0

Я думаю, что ваш код, безусловно, ошибки, вы никогда не должны использовать одеяло, кроме как у вас, если вы не видели бы вы свою ошибку –

+0

Вам не нужно называть 'Int (Len (х)) '. 'len' возвращает целое число. Вам также не нужно сравнивать длину чего-то с 0. 'if len (x)> 0' совпадает с' if x'. – dirn

ответ

3

Во-первых, я думаю, что у меня есть образец рабочего кода для исходной задачи. Тем не менее, я думаю, что вы можете решить эту проблему с дублирующимся пользователем лучше, используя ограничения в базе данных. См. Нижнюю часть моего ответа.

Сначала давайте проверим текущий код. Есть несколько вопросов, которые я могу увидеть здесь:

  1. Неправильная отступы try/finally означает, что нет никакой связи активны в течение try/finally.
  2. То, как вы проверяете, есть ли запись с именем пользователя, неверна.

Отступ

В текущем коде try/finally блока на линии 6 потребностей с отступом один дополнительно для того, чтобы иметь возможность использовать соединение, установленное соединение, сделанное в with заявления по линии 4.

Поскольку код в настоящее время стоит, соединение будет закрыто к моменту его использования, поэтому доступ к базе данных завершится с ошибкой.

Проверка пользователя

код, используемый для проверки пользователь не сможет, выбрасывая исключение, которое приведет к тому, чтобы окончательно поразить и rollback быть выполнены. Возвращаемое значение от execute выдает исключение, когда вы вызываете len, есть ли какие-либо записи.

Вот что я получаю от питона оболочки, чтобы показать, что я имею в виду:

>>> int(len(cur.execute("select * from people where name_last=:who", {"who": "mike"}))) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: object of type 'sqlite3.Cursor' has no len() 

Вместо того, чтобы проверить, возвращает ли select заявление значение, используйте fetchone и посмотреть, если он возвращает None:

# No users named `fred`: 
>>> cur.execute("select * from people where name_last=:who", {"who": "fred"}) 
<sqlite3.Cursor object at 0x10bbd0180> 
>>> cur.fetchone() is None 
True 

# At least one user named `mike`: 
>>> cur.execute("select * from people where name_last=:who", {"who": "mike"}) 
<sqlite3.Cursor object at 0x10bbd0180> 
>>> cur.fetchone() is None 
False 

поэтому я думаю, что-то подобное может работать:

def regist(): 
    if request.method == "POST": 
     with sql.connect("database.db") as con: 
      cur = con.cursor() 
      try: 
       # ... Collecting form info ... 

       cur.execute("SELECT * FROM users WHERE name = ?", (username)) 

       if cur.fetchone() is not None: 
        flash("That username is already taken...") 
        return render_template('register.html') 
       else: 
        cur.execute("INSERT INTO users (name,password,email) VALUES (?,?,?)",(username,passwordencr,email)) 
        con.commit() 
        flash (...) 
      except: 
       con.rollback() 

      finally: 
       session['logged_in'] = True 
       session['username'] = username 
       # ... mailing code ... 

Альтернативный подход

Более надежный подход заключается в том, чтобы позволить базе данных взять на себя ответственность за предотвращение дублирования пользователей.

Составьте столбец nameunique при создании таблицы. Тогда вставка записи с тем же именем пользователя вызовет исключение.Принимая пример из sqlite3 docs:

import sqlite3 

con = sqlite3.connect(":memory:") 
con.execute("create table person (id integer primary key, firstname varchar unique)") 

# Successful, con.commit() is called automatically afterwards 
with con: 
    con.execute("insert into person(firstname) values (?)", ("Joe",)) 

# con.rollback() is called after the with block finishes with an exception, the 
# exception is still raised and must be caught 
try: 
    with con: 
     con.execute("insert into person(firstname) values (?)", ("Joe",)) 
except sqlite3.IntegrityError: 
    print "couldn't add Joe twice" 
+0

http://prntscr.com/cxyunv вот так? Я смущен. – Julian

+0

Обновленный код, чтобы надеяться, ясно, что я говорю :) –

+0

Он по-прежнему не заполнит мою базу данных. Что я пытался сказать: когда я удаляю кусок, где он проверяет имя пользователя в БД (если его уже там), мой код работает отлично, и он заполняет мой db .. – Julian

0

этот код подключается к database.db дважды в строках 1 и 9. Возможно, это не то, что первоначально было предназначено

+0

Это не дает мне никаких ошибок, но информация по-прежнему не передается в базе данных. – Julian

+0

Я поставил свой код сверху. Было бы хорошо, если бы вы могли заглянуть в него. – Julian

+0

Я думаю, что @Mike Rhodes прав, попробуйте/за исключением того, что блок должен быть отступом еще на одном уровне – Marat

2

сделать одну функцию, которая проверить имя пользователя и адрес электронной почты уже в базе данных или нет.

#Models 
class User(UserMixin, db.Model): 
    id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
    username = db.Column(db.String(15), unique=True, nullable=False) 
    email = db.Column(db.String(50), unique=True, nullable=False) 
    password = db.Column(db.String(120), unique=True, nullable=False) 
    created_on = db.Column(db.DateTime, server_default=db.func.now()) 
    updated_on = db.Column(db.DateTime, server_default=db.func.now(), server_onupdate=db.func.now()) 
    tasks = db.relationship('Task', backref='author', lazy='dynamic') 

    @classmethod 
    def is_user_name_taken(cls, username): 
     return db.session.query(db.exists().where(User.username==username)).scalar() 

    @classmethod 
    def is_email_taken(cls, email): 
     return db.session.query(db.exists().where(User.email==email)).scalar() 

    def __repr__(self): 
     return '<User %r>' % (self.username) 

#User Signup Api 
@app.route('/todo/api/v1.0/signup', methods=['POST']) 
def signup(): 

    if 'username' not in request.json: 
     return jsonify({'username': 'must include username'}) 
    if 'email' not in request.json: 
     return jsonify({'email': 'must include email'}) 
    if 'password' not in request.json: 
     return jsonify({'password' : 'must include password' }) 

    if User.is_user_name_taken(request.json['username']): 
     return jsonify({'username': 'This username is already taken!'}), 409 
    if User.is_email_taken(request.json['email']): 
     return jsonify({'email': 'This email is already taken!'}), 409 

    if request.json : 
     hashed_password = generate_password_hash(request.json['password'], method='sha256') 
     new_user = User(username=request.json['username'], email=request.json['email'], password=hashed_password) 
     db.session.add(new_user) 
     db.session.commit() 
     return jsonify({'user': 'user created successfully'}), 201 
    return jsonify({'username': 'must include username', 
      'password': 'must include password', 
      'email' : 'must include email' }) 
Смежные вопросы