internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: flask-admin/flask-admin

Issue:
InlineModelFormList CAN NOT deal with model with  two primary keys
When pk is tuple, the following code does not work.        

```
    pk_map = dict((str(getattr(v, self._pk)), v) for v in values)

    # Handle request data
    for field in self.entries:
        field_id = field.get_pk()

        if field_id in pk_map:
            model = pk_map[field_id]

            if self.should_delete(field):
                self.session.delete(model)
                continue
        else:
            model = self.model()
            values.append(model)
```

Beside, type of `str(getattr(v, self._pk))` may be different from that of `field_id = field.get_pk()`.



Discussion:

Resolving patch:
diff --git a/flask_admin/contrib/sqla/fields.py b/flask_admin/contrib/sqla/fields.py
--- a/flask_admin/contrib/sqla/fields.py
+++ b/flask_admin/contrib/sqla/fields.py
@@ -272,11 +272,11 @@ def populate_obj(self, obj, name):
             return
 
         # Create primary key map
-        pk_map = dict((str(getattr(v, self._pk)), v) for v in values)
+        pk_map = dict((get_obj_pk(v, self._pk), v) for v in values)
 
         # Handle request data
         for field in self.entries:
-            field_id = field.get_pk()
+            field_id = get_field_id(field)
 
             is_created = field_id not in pk_map
             if not is_created:
@@ -298,3 +298,27 @@ def get_pk_from_identity(obj):
     # TODO: Remove me
     cls, key = identity_key(instance=obj)
     return u':'.join(text_type(x) for x in key)
+
+
+def get_obj_pk(obj, pk):
+    """
+    get and format pk from obj
+    :rtype: text_type
+    """
+
+    if isinstance(pk, tuple):
+        return tuple(text_type(getattr(obj, k)) for k in pk)
+
+    return text_type(getattr(obj, pk))
+
+
+def get_field_id(field):
+    """
+    get and format id from field
+    :rtype: text_type
+    """
+    field_id = field.get_pk()
+    if isinstance(field_id, tuple):
+        return tuple(text_type(_) for _ in field_id)
+
+    return text_type(field_id)
diff --git a/flask_admin/model/fields.py b/flask_admin/model/fields.py
--- a/flask_admin/model/fields.py
+++ b/flask_admin/model/fields.py
@@ -118,6 +118,10 @@ def __init__(self, form_class, pk, form_opts=None, **kwargs):
         self.form_opts = form_opts
 
     def get_pk(self):
+
+        if isinstance(self._pk, (tuple, list)):
+            return tuple(getattr(self.form, pk).data for pk in self._pk)
+
         return getattr(self.form, self._pk).data
 
     def populate_obj(self, obj, name):


Test patch:
Repository: flask-admin/flask-admin

Issue:
base_path should accept callables
I'm using [ImageUploadField](http://flask-admin.readthedocs.org/en/latest/api/mod_form_upload/?highlight=namegen#flask.ext.admin.form.upload.ImageUploadField) and I'm having trouble with the base_path: I'm setting the path in flask's configuration so I need base_path to accept callable which is not possible.

I've looked at open issues and did override _create_form_ and _edit_form_ as suggested but then deleting the image does not remove it from filesystem. Would be much cleaner with a callable base_path so that's a feature request and not a bug report for the workaround.

Thanks



Discussion:

Resolving patch:
diff --git a/flask_admin/form/upload.py b/flask_admin/form/upload.py
--- a/flask_admin/form/upload.py
+++ b/flask_admin/form/upload.py
@@ -226,6 +226,8 @@ def _get_path(self, filename):
         if not self.base_path:
             raise ValueError('FileUploadField field requires base_path to be set.')
 
+        if callable(self.base_path):
+            return op.join(self.base_path(), filename)
         return op.join(self.base_path, filename)
 
     def _delete_file(self, filename):


Test patch:
Repository: flask-admin/flask-admin

Issue:
Raising on multiple-column properties
Some of our SQLA models have composite properties, which make Flask-Admin raise when scaffold_list_columns or scaffold_form runs. We were able to work around it by subclassing ModelView, but would it make sense to just `continue` on these properties instead of raising? Due to the nature of composite properties, I don't think anyone would expect to see them in the admin interface anyway.



Discussion:
You can ignore them explicitly through `column_exclude_list` and `form_excluded_columns`. 

Maybe it is good idea to skip them, but I'm thinking that it should at least show a warning.

I see you have a TODO to skip and add a warning. Would you accept a PR replacing the TypeError with a warning?

Sure!


Resolving patch:
diff --git a/flask_admin/contrib/sqla/view.py b/flask_admin/contrib/sqla/view.py
--- a/flask_admin/contrib/sqla/view.py
+++ b/flask_admin/contrib/sqla/view.py
@@ -1,4 +1,5 @@
 import logging
+import warnings
 
 from sqlalchemy.orm.attributes import InstrumentedAttribute
 from sqlalchemy.orm import joinedload
@@ -391,8 +392,7 @@ def scaffold_list_columns(self):
                     filtered = tools.filter_foreign_columns(self.model.__table__, p.columns)
 
                     if len(filtered) > 1:
-                        # TODO: Skip column and issue a warning
-                        raise TypeError('Can not convert multiple-column properties (%s.%s)' % (self.model, p.key))
+                        warnings.warn('Can not convert multiple-column properties (%s.%s)' % (self.model, p.key))
 
                     column = filtered[0]
                 else:


Test patch:
Repository: flask-admin/flask-admin

Issue:
Raising on multiple-column properties
Some of our SQLA models have composite properties, which make Flask-Admin raise when scaffold_list_columns or scaffold_form runs. We were able to work around it by subclassing ModelView, but would it make sense to just `continue` on these properties instead of raising? Due to the nature of composite properties, I don't think anyone would expect to see them in the admin interface anyway.



Discussion:
You can ignore them explicitly through `column_exclude_list` and `form_excluded_columns`. 

Maybe it is good idea to skip them, but I'm thinking that it should at least show a warning.

I see you have a TODO to skip and add a warning. Would you accept a PR replacing the TypeError with a warning?

Sure!


Resolving patch:
diff --git a/flask_admin/contrib/sqla/form.py b/flask_admin/contrib/sqla/form.py
--- a/flask_admin/contrib/sqla/form.py
+++ b/flask_admin/contrib/sqla/form.py
@@ -1,3 +1,5 @@
+import warnings
+
 from wtforms import fields, validators
 from sqlalchemy import Boolean, Column
 
@@ -158,7 +160,8 @@ def convert(self, model, mapper, prop, field_args, hidden_pk):
                     columns = filter_foreign_columns(model.__table__, prop.columns)
 
                     if len(columns) > 1:
-                        raise TypeError('Can not convert multiple-column properties (%s.%s)' % (model, prop.key))
+                        warnings.warn('Can not convert multiple-column properties (%s.%s)' % (model, prop.key))
+                        return None
 
                     column = columns[0]
                 else:
diff --git a/flask_admin/contrib/sqla/view.py b/flask_admin/contrib/sqla/view.py
--- a/flask_admin/contrib/sqla/view.py
+++ b/flask_admin/contrib/sqla/view.py
@@ -393,6 +393,7 @@ def scaffold_list_columns(self):
 
                     if len(filtered) > 1:
                         warnings.warn('Can not convert multiple-column properties (%s.%s)' % (self.model, p.key))
+                        continue
 
                     column = filtered[0]
                 else:


Test patch:
Repository: flask-admin/flask-admin

Issue:
Docs refactor
The documentation is great, but for a completely new user, there's a lot to read through before they have a good overview of what's possible. To make it more obvious for a user to see how to do all of the common things, I want to refactor the docs into the following sections:
## Getting started
- Initialization
- Adding model views
- Overriding the index page
## Auth & permissions
- Basic auth
- Flask-Security
## Customizing the builtin model views
- Image fields
- HTML fields
- List view options
- Form view options
## Adding your own views
- Standalone views
- Overriding specific model views
## Advanced
- Enabling localization
- Handling foreign key relations inline
- Many-to-many relations
- Managing files & folders
- Managing geographical models
- Customizing builtin forms via form rendering rules
- Using different model backends
- Rolling your own authentication
- Usage tips
- Adding a Redis console
## API 
- (auto generated from code)



Discussion:
Just created branch `docs_refactor` for these changes. Any comments/help is welcome!


Resolving patch:
diff --git a/doc/_themes/flask_theme_support.py b/doc/_themes/flask_theme_support.py
old mode 100644
new mode 100755
diff --git a/doc/conf.py b/doc/conf.py
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -43,7 +43,7 @@
 
 # General information about the project.
 project = u'flask-admin'
-copyright = u'2012-2013, Serge S. Koval'
+copyright = u'2012-2015, Serge S. Koval'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -137,9 +137,8 @@
 
 # Custom sidebar templates, maps document names to template names.
 html_sidebars = {
-    'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html'],
-    '**': ['localtoc.html', 'relations.html',
-           'sourcelink.html', 'searchbox.html']
+    'index': ['sidebarintro.html', 'searchbox.html'],
+    '**': ['toc.html', 'relations.html', 'searchbox.html']
 }
 # Additional templates that should be rendered to pages, maps page names to
 # template names.


Test patch:
Repository: flask-admin/flask-admin

Issue:
Adding a icon to a category in a menu
If you have a category with some views (which are added with `admin.add_view`), you can use the parameters `menu_icon_type` and `menu_icon_value` to set a icon (finally displayed with `{{ menu_icon(item) }}` in the menu).

Is there a possiblity to add a icon for the category too? Because in this case the category isn't a view.



Discussion:
Right now there's no way to, as icons are not displayed for category items. But you can add this functionality through custom mixin and custom template.

All right, thanks.

Is it possible to add this feature and if yes, how and where in the code would be the best solution?


Resolving patch:
diff --git a/flask_admin/base.py b/flask_admin/base.py
--- a/flask_admin/base.py
+++ b/flask_admin/base.py
@@ -454,7 +454,8 @@ def __init__(self, app=None, name=None,
                  endpoint=None,
                  static_url_path=None,
                  base_template=None,
-                 template_mode=None):
+                 template_mode=None,
+                 category_icon_classes=None):
         """
             Constructor.
 
@@ -482,6 +483,9 @@ def __init__(self, app=None, name=None,
             :param template_mode:
                 Base template path. Defaults to `bootstrap2`. If you want to use
                 Bootstrap 3 integration, change it to `bootstrap3`.
+            :param category_icon_classes:
+                A dict of category names as keys and html classes as values to be added to menu category icons.
+                Example: {'Favorites': 'glyphicon glyphicon-star'}
         """
         self.app = app
 
@@ -503,6 +507,7 @@ def __init__(self, app=None, name=None,
         self.subdomain = subdomain
         self.base_template = base_template or 'admin/base.html'
         self.template_mode = template_mode or 'bootstrap2'
+        self.category_icon_classes = category_icon_classes or dict()
 
         # Add predefined index view
         self.add_view(self.index_view)
@@ -545,8 +550,10 @@ def _add_menu_item(self, menu_item, target_category):
 
             category = self._menu_categories.get(cat_text)
 
+            # create a new menu category if one does not exist already
             if category is None:
                 category = MenuCategory(target_category)
+                category.class_name = self.category_icon_classes.get(cat_text)
                 self._menu_categories[cat_text] = category
 
                 self._menu.append(category)


Test patch:
Repository: flask-admin/flask-admin

Issue:
Issue with empty List of ReferenceField since 1.2.0
Hello,

There is an issue (or is it a feature ?) with MongoEngine's ListField of ReferenceField. I cannot save my object in Flask-Admin (be it a new or edited object) when an attribute of ListField(ReferenceField()) type is empty. The save returns to the same page saying that the value is not correct.

Here is the sample attribute:

roles = db.ListField(db.ReferenceField(Role), default=[])

I reverted to v1.1.0 which is working fine. The problem appeared when I updated to v1.2.0



Discussion:
Apparently there were some changes in flask_mongoengine form generation logic, but adding `Optional` validator automatically helped the case.


Resolving patch:
diff --git a/flask_admin/contrib/mongoengine/form.py b/flask_admin/contrib/mongoengine/form.py
--- a/flask_admin/contrib/mongoengine/form.py
+++ b/flask_admin/contrib/mongoengine/form.py
@@ -114,7 +114,7 @@ def conv_List(self, model, field, kwargs):
                 return AjaxSelectMultipleField(loader, **kwargs)
 
             kwargs['widget'] = form.Select2Widget(multiple=True)
-            kwargs.setdefault('validators', [validators.Optional()])
+            kwargs.setdefault('validators', []).append(validators.Optional())
 
             # TODO: Support AJAX multi-select
             doc_type = field.field.document_type


Test patch:
Repository: flask-admin/flask-admin

Issue:
Mass Delete (and other actions) should persist view args (query string)
If I filter a list view and then do a mass delete/action, I would expect to be brought back to the same filtered view, but instead I'm redirected to the naked index view.



Discussion:

Resolving patch:
diff --git a/flask_admin/actions.py b/flask_admin/actions.py
--- a/flask_admin/actions.py
+++ b/flask_admin/actions.py
@@ -3,6 +3,7 @@
 
 from flask_admin import tools
 from flask_admin._compat import text_type
+from flask_admin.helpers import get_redirect_target
 
 
 def action(name, text, confirmation=None):
@@ -100,7 +101,8 @@ def handle_action(self, return_view=None):
 
             :param return_view:
                 Name of the view to return to after the request.
-                If not provided, will return user to the index view.
+                If not provided, will return user to the return url in the form
+                or the list view.
         """
         action = request.form.get('action')
         ids = request.form.getlist('rowid')
@@ -113,9 +115,9 @@ def handle_action(self, return_view=None):
             if response is not None:
                 return response
 
-        if not return_view:
-            url = self.get_url('.' + self._default_view)
-        else:
+        if return_view:
             url = self.get_url('.' + return_view)
+        else:
+            url = get_redirect_target() or self.get_url('.index_view')
 
         return redirect(url)


Test patch:
Repository: flask-admin/flask-admin

Issue:
form_extra_fields not considered in an inline form 
[flask_admin.form.upload](http://flask-admin.readthedocs.org/en/latest/api/mod_form_upload/#module-flask_admin.form.upload) related fields are not rendered correctly in an inline form. 

Looks like the _extra_fields_ kwarg is not set when invoking _get_form_ from the [InlineModelConverter.contribute](https://github.com/flask-admin/flask-admin/blob/f774a37620f9efa9606a7f85b8a60c51e2918f2a/flask_admin/contrib/sqla/form.py#L610) method.  

Can you please point me to the contribution guidelines ?  I can maybe submit a PR for this.

(Note: I posted this on [StackOverflow](http://stackoverflow.com/questions/32300837/using-imageuploadfield-in-an-inlineformadmin-form) after which I looked into the source)



Discussion:

Resolving patch:
diff --git a/flask_admin/contrib/sqla/form.py b/flask_admin/contrib/sqla/form.py
--- a/flask_admin/contrib/sqla/form.py
+++ b/flask_admin/contrib/sqla/form.py
@@ -612,7 +612,8 @@ def contribute(self, model, form_class, inline_model):
                                   only=info.form_columns,
                                   exclude=exclude,
                                   field_args=info.form_args,
-                                  hidden_pk=True)
+                                  hidden_pk=True,
+                                  extra_fields=info.form_extra_fields)
 
         # Post-process form
         child_form = info.postprocess_form(child_form)


Test patch:
Repository: flask-admin/flask-admin

Issue:
Tests failing due to new Pillow 3.0.0
Tests are currently failing when a tiff file (https://github.com/flask-admin/flask-admin/blob/master/flask_admin/tests/data/copyleft.jpg) is uploaded:

```
======================================================================
FAIL: flask_admin.tests.test_form_upload.test_image_upload_field
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/virtualenv/python2.6.9/lib/python2.6/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/home/travis/build/flask-admin/flask-admin/flask_admin/tests/test_form_upload.py", line 225, in test_image_upload_field
    ok_(my_form.validate())
AssertionError: None
>>  raise AssertionError(None)
```

The issue has to do with the new 3.0.0 version of Pillow. I started an issue for it here: https://github.com/python-pillow/Pillow/issues/1466

A temporary solution might be to lock Pillow to 2.9.0. I can submit a pull request if that's what we decide to do: https://github.com/flask-admin/flask-admin/compare/master...pawl:fix_pillow_build



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -49,7 +49,7 @@ def grep(attrname):
     ],
     tests_require=[
         'nose>=1.0',
-        'pillow',
+        'pillow==2.9.0',
         'mongoengine',
         'pymongo',
         'wtf-peewee',


Test patch:
Repository: flask-admin/flask-admin

Issue:
Broken compatibility with flask-admin 1.1.0
Hi,

I had to make this change in my source code :

-from flask.ext.admin.form import rules
+from flask_admin.form import rules

Because in module flask_admin.form.rules line 403, we have this test : 

if isinstance(r, BaseRule):

And it returns false if rule object was created from flask.ext.admin.form instead of flask_admin.form . I spent some times to find it, maybe it can help someone else.



Discussion:

Resolving patch:
diff --git a/flask_admin/form/rules.py b/flask_admin/form/rules.py
--- a/flask_admin/form/rules.py
+++ b/flask_admin/form/rules.py
@@ -400,12 +400,13 @@ def configure_rules(self, rules, parent=None):
         result = []
 
         for r in rules:
-            if isinstance(r, BaseRule):
-                result.append(r.configure(self, parent))
-            elif isinstance(r, string_types):
+            if isinstance(r, string_types):
                 result.append(self.convert_string(r).configure(self, parent))
             else:
-                raise ValueError('Dont know how to convert %s' % repr(r))
+                try:
+                    result.append(r.configure(self, parent))
+                except AttributeError:
+                    raise TypeError('Could not convert "%s" to rule' % repr(r))
 
         return result
 


Test patch:
Repository: flask-admin/flask-admin

Issue:
sqla.Unique validator is inserted twice
when a table column is set to be unique when defining the model:

`
class Example(Base):
     email = Column(String(50), unique=True)
`

and when adding any validators in form_args for the Example model view,
e.g.
`
form_args = dict(email=dict(validators=[required()]))
`

the form's validators list for the email field contains the sqla.Unique **twice** and the  "Already exists" message appears twice when having a unique violation



Discussion:

Resolving patch:
diff --git a/flask_admin/contrib/mongoengine/form.py b/flask_admin/contrib/mongoengine/form.py
--- a/flask_admin/contrib/mongoengine/form.py
+++ b/flask_admin/contrib/mongoengine/form.py
@@ -1,3 +1,5 @@
+from copy import deepcopy
+
 from mongoengine import ReferenceField, ListField
 from mongoengine.base import BaseDocument, DocumentMetaclass, get_document
 
@@ -68,7 +70,8 @@ def convert(self, model, field, field_args):
         }
 
         if field_args:
-            kwargs.update(field_args)
+            # prevent modification of self.form_args
+            kwargs.update(deepcopy(field_args))
 
         if field.required:
             kwargs['validators'].append(validators.InputRequired())
diff --git a/flask_admin/contrib/sqla/form.py b/flask_admin/contrib/sqla/form.py
--- a/flask_admin/contrib/sqla/form.py
+++ b/flask_admin/contrib/sqla/form.py
@@ -1,5 +1,7 @@
 import warnings
 
+from copy import deepcopy
+
 from wtforms import fields, validators
 from sqlalchemy import Boolean, Column
 
@@ -147,7 +149,8 @@ def convert(self, model, mapper, prop, field_args, hidden_pk):
         }
 
         if field_args:
-            kwargs.update(field_args)
+            # prevent modification of self.form_args
+            kwargs.update(deepcopy(field_args))
 
         # Check if it is relation or property
         if hasattr(prop, 'direction'):


Test patch:
Repository: flask-admin/flask-admin

Issue:
form_ajax_refs to model with primary key attribute not matching the column in the DB
When I have the following models:

```
class Country(db.Model):

    name = db.Column(db.Text)
    alpha2 = db.Column('iso3166alpha2', db.Text)
    alpha3 = db.Column('iso3166alpha3', db.Text)
    numeric = db.Column('iso3166numeric', db.Integer, primary_key=True, autoincrement=False)


class Customer(db.Model):
    id = db.Column('customer_id', db.Integer, primary_key=True, nullable=False)
    name = db.Column(db.Text)
    country_number = db.Column('country', db.Integer, db.ForeignKey('country.iso3166numeric'), nullable=False)
    country = db.relationship('Country', foreign_keys=country_number)
```

And I try to register Customer model in administration like that

```
class CustomerModelView(StaffModelView):
    form_ajax_refs = {
        'country': {
            'fields': ['alpha3', 'name'],
            'page_size': 10
        }
    }
```

I receive an error:

```
AttributeError: 'Country' object has no attribute 'iso3166numeric'
```

The problem is obviously that attribute name of the primary key of the Country model does not match the name of the column. But it is supported by the SQLAlchemy.

The problem occurs in QueryAjaxModelLoader.format method https://github.com/flask-admin/flask-admin/blob/v1.3.0/flask_admin/contrib/sqla/ajax.py#L50-L54

I found that in SQLAlchemy there is a way to get the value of primary key by using `primary_key_from_instance` method of the `Mapper`

I will try to provide a pull request to show what I mean.



Discussion:
My PR #1073 has changes for fixing this issue.


Resolving patch:
diff --git a/flask_admin/contrib/sqla/ajax.py b/flask_admin/contrib/sqla/ajax.py
--- a/flask_admin/contrib/sqla/ajax.py
+++ b/flask_admin/contrib/sqla/ajax.py
@@ -3,6 +3,8 @@
 from flask_admin._compat import as_unicode, string_types
 from flask_admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
 
+from .tools import get_primary_key, has_multiple_pks
+
 
 class QueryAjaxModelLoader(AjaxModelLoader):
     def __init__(self, name, session, model, **options):
@@ -24,11 +26,10 @@ def __init__(self, name, session, model, **options):
 
         self._cached_fields = self._process_fields()
 
-        primary_keys = model._sa_class_manager.mapper.primary_key
-        if len(primary_keys) > 1:
+        if has_multiple_pks(model):
             raise NotImplementedError('Flask-Admin does not support multi-pk AJAX model loading.')
 
-        self.pk = primary_keys[0].name
+        self.pk = get_primary_key(model)
 
     def _process_fields(self):
         remote_fields = []


Test patch: