0

I am working on a small reading tracking app in Flask. I cannot seem to write data from one of my routes, below:

@app.route('/add_book', methods=['GET', 'POST'])
@login_required
def add_book():
    form=BookForm()
    if request.method=='POST':
        if form.validate_on_submit():
            book=Book(
                title=form.title.data,
                author=form.author.data,
                # category=form.category.data,
                # added_on=form.added_on.data,
                # done=form.done.data,
                user_id=current_user
                )

            db.session.add(book)
            db.session.commit()
            flash('Book added')
            return redirect(url_for('books'))
        else:
            flash('ERROR. The book not added.')

    return render_template('add_book.html', form=form)

This is the corresponding HTML:

{% extends "layout.html" %}

{% block content %}

{% if form %}

    <form action="{{ url_for('add_book') }}" method="post">
      {{ form.hidden_tag() }}

        {{ form.title.label }}<br>
        {{ form.title() }}<br>

        {{ form.author.label }}<br>
        {{ form.author(cols=32, rows=4) }}<br>

       <!-- {{ form.category.label }}<br>
        {{ form.category() }}<br> -->

        {{ form.submit() }}

    </form>

    {% endif %}

{% endblock %}

When the page renders, the label and forms for the book and author appear, however on clicking Submit, the data does not get saved.

The code section is similar to that for registering a user and I am stuck on what to do because I cannot see any errors. I am using SQLite as a database.

Here is the book model:

class Book(db.Model):

    __tablename__='books'

    id=db.Column(db.Integer, primary_key=True)
    title=db.Column(db.String(100))
    author=db.Column(db.String(50))
    # category=db.Column(db.String(50))
    added_on=db.Column(db.DateTime, index=True, default=datetime.utcnow)
    done=db.Column(db.Boolean, default=False)
    user_id=db.Column(db.Integer, db.ForeignKey('users.id'))

    def __init__(self, title, author, added_on, done, user_id):
        self.title=title
        self.author=author
        self.added_on=added_on
        self.done=done
        self.user_id=user_id

    def __repr__(self):
        # return '<Book: Title - {0}, Author - {1}, Category - {2}>'.format(self.title, self.author, self.category)
        return '<Book: Title - {0}, Author - {1}>'.format(self.title, self.author)

1 Answers1

1

The current_user is a user proxy giving access to all user attributes or use something like this How to track the current user in flask-login?

a quick solution would be to change this line

user_id = current_user

into this

user_id = current_user.id

Update: ok, I got it working. You need the following fixes, each of them leads to trouble with form validation and or committing to database: - use current_user.id in your book object as I said earlier. - removed the init method in books model. I'm not sure what the added value is at the moment, I'm getting error messages about fields added on and done which are not on the form. I haven't taken the time to look into it further. - just go for if request.method=='POST' as you don't need both. The form will be checked for validation anyways.

tip: don't forget to create a requirements file (pip freeze --> requirements.txt), that makes it a lot easier to reinstall in a new virtual environment.

gittert
  • 1,238
  • 2
  • 7
  • 15
  • let me test myself with your code, I'll come back on it – gittert Feb 21 '19 at 12:44
  • thanks, i'll try and test this evening. in the meantime, try add a print before and between this, to see if the form validation is going as expected. db.session.add(book) db.session.commit() – gittert Feb 26 '19 at 09:21
  • IT'S WORKING! THANK YOU! –  Feb 27 '19 at 11:34
  • No worries mate. Just run in a venv in debug mode and keep a close look at its output. It also helps if you add some prints here and there to check input and output during troubleshooting. – gittert Feb 27 '19 at 12:04