4

I am using Flask-Admin for my Flask-based project. In it, I have some models (using peewee) where the primary-key is user-set, such as username for a User. However Flask-Admin is not showing these fields in the model's create/edit pages.

Now, when I try to create a new user, the "Save" button gives a peewee.UserDoesNotExist error, and the "Save & Add" says "Record successfully created" twice but doesn't actually do anything.

I had extended the save() method to auto-generate the username from the name if it's unset, but the problem persisted even when I removed the overriding.

The code...

Here's what my User model looks like:

# import peewee as pw

class User(BaseModel, UserMixin):
    username = pw.CharField(32, primary_key=True)
    password = pw.CharField(512, null=True)
    name = pw.CharField(64)

    # ... other fields not shown ... #

    def save(self, *args, **kwargs):
        # Set the username if field is blank
        if self.username == 'auto' or not self.username:
            self.username = self.name.replace(' ', '').lower()
        # Do the real save
        super(User, self).save(*args, **kwargs)

Here's my admin code:

# from flask_admin.contrib.peewee.view import ModelView

class AdminModelUser(ModelView):
    can_create = True
    column_list = ('username', 'name', 'group', 'active')

admin.add_view(AdminModelUser(User, name='Users', category='Accounts'))

Trying out stuff

I later tried to override the get_form() method, to use wtfpeewee directly and allow the pk, like this:

# from wtfpeewee.orm import model_form
class AdminModelUser(ModelView):
    ...        
    def get_form(self):
        return model_form(User, allow_pk=True)

Now the field is showing, but saving still does not work. When I edit the username of an existing user, the admin says "Record was successfully saved", but it doesn't get saved. And when I try to create a new user, I still get a peewee.UserDoesNotExist error.

My guess is that I've done the overriding in the wrong place, with the fields showing in the form but not in the save methods. I couldn't find any mention of this in the docs: does anyone know how to do it?

Hippo
  • 450
  • 8
  • 22
  • The reason you are getting the `peewee.UserDoesNotExist` is most likely because the SQL generated after changing the username is something like `UPDATE some_table SET (...) WHERE id=new_username` which obviously doesn't exist. I would strongly recommend against using user set primary id's. It's much safer and easier to use an automatically incrementing integer id. – kylieCatt Jul 03 '15 at 13:36
  • 2
    You're creating a lot of unnecessary work for you and your database by editing primary keys. Stick with integers or UUIDs and use unique constraints for meaningful fields that need to be unique, like username. – dirn Jul 03 '15 at 14:27

1 Answers1

2

When you've got a non-integer primary key, you must call save() with force_insert=True to add a new row.

http://docs.peewee-orm.com/en/latest/peewee/models.html#non-integer-primary-keys-composite-keys-and-other-tricks

coleifer
  • 24,887
  • 6
  • 60
  • 75