Skip to content

Commit

Permalink
Merge pull request #24 from caktus/django-1-11
Browse files Browse the repository at this point in the history
Django 1.11 support
  • Loading branch information
vkurup authored Oct 27, 2017
2 parents 3ad54c2 + 1c42e70 commit 2ada252
Show file tree
Hide file tree
Showing 19 changed files with 112 additions and 96 deletions.
10 changes: 5 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ django-file-picker
django-file-picker is a pluggable Django application used for uploading,
browsing, and inserting various forms of media into HTML form fields.

Using jQuery Tools, file_picker integrates seamlessly into pre-existing pages by
Using jQuery Tools, django-file-picker integrates seamlessly into pre-existing pages by
installing an overlay that lists file details and, when applicable, image
thumbnails. New files can also be uploaded from within the overlay (via AJAX
Upload).

``file_picker`` provides a few optional extensions to help get started,
django-file-picker provides a few optional extensions to help get started,
including ``file_picker.uploads``, an app with pre-built Image and File models, and
``file_picker.wymeditor``, an app that integrates with
`WYMeditor <http://www.wymeditor.org/>`_, a web-based
Expand All @@ -24,7 +24,7 @@ Dependencies
Required
````````
* Python 2.7 (**note**: Python 3 is not yet supported)
* `Django 1.8 to 1.10 (inclusive) <http://www.djangoproject.com/>`_
* `Django 1.8 to 1.11 (inclusive) <http://www.djangoproject.com/>`_
* sorl-thumbnail==12.4a1
* `jQuery 1.4.x <http://www.jquery.com/>`_
* `jQuery Tools 1.2.x <http://flowplayer.org/tools/>`_
Expand All @@ -38,7 +38,7 @@ Optional
If you are using ``django.contrib.staticfiles``, then add ``file_picker`` to your INSTALLED_APPS
to include the related css/js.

Otherwise make sure to include the contents of the static folder in your projects
Otherwise make sure to include the contents of the static folder in your project's
media folder.

.. _installation:
Expand Down Expand Up @@ -67,4 +67,4 @@ Basic Installation
# ...
]

Development sponsored by `Caktus Consulting Group, LLC. <http://www.caktusgroup.com/services>`_.
Development sponsored by `Caktus Consulting Group, LLC. <https://www.caktusgroup.com/services/>`_.
4 changes: 2 additions & 2 deletions docs/motivation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ The deep concern while building a file picker has been flexibility. Too many
projects focus on wrapping everything together so that they can make
deep connections.

Our main goal has been to build a application that facilitates connections,
that can be attached across multiple applications and models.
Our main goal has been to build an application that is easy to plug into a
wide variety of applications and models.
74 changes: 41 additions & 33 deletions docs/picker_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,35 @@ Each picker can take a set of attributes for easy customization.::

None of these attributes are required and they all have sane defaults.

* *form*- If left blank is created by building a *ModelForm* from the model defined
in the register function. It is used to build the form on the Upload tab.
* *form*- If not set, a *ModelForm* is created using the model defined
in the register function. This is used to build the form on the Upload tab.

* *link_headers*- Defines the headers for the first set of columns which are used
to insert content into the textbox or WYSIWYG of your choice. By default it
converts _ to ' ' and capitalizes first letter of the fields name.
to insert content into the textbox or WYSIWYG widget of your choice. By default, it
converts _ to ' ' and capitalizes the first letter of the field's name.

* *columns*- Defines the fields you want to be included on the listing page
and their ordering.
* *extra_headers*- The list is used to define the headers for the columns
and needs to be in the same order as columns.
* *ordering*- Defines the order of items on the listing page in
to be used as ``query_set.order_by('-date')``.
* *extra_headers*- This list is used to display the headers for the columns
and needs to be in the same order as *columns*.
* *ordering*- Defines the order of items on the listing page. In this example,
the code would run ``query_set.order_by('-date')``. If no ordering is
provided, we'll order by ``-pk``.


Methods
-------

The three main methods consist of *append*, *list*, and *upload_file*. List and upload_file
take in the request object and act as views while append takes in an model item and helps
build the JSON output for list. Other methods are available but typically do not
need to be modified.
The three main methods consist of *append*, *list*, and *upload_file*. *List*
and *upload_file* take a request object and act as views, while *append* takes
a model instance and builds the JSON output for list. Other methods are
available but typically do not need to be modified.

append(obj)
^^^^^^^^^^^

This method takes in *obj* which is a item from the model and outputs a dictionary
to be used by list. This dictoinary is of the form.::
This method takes *obj* which is a model instance and returns a dictionary
to be used by *list*. This dictionary is of the form::

{
'name': 'Name for the object.',
Expand All @@ -69,39 +71,45 @@ to be used by list. This dictoinary is of the form.::
'column_name_1': 'value',
'column_name_2': 'value',
},
'insert': ['string/html to insert if first link is clicked', 'for second link',],
'link_content': ['string to show on first insert link', 'for second link',],
'insert': [
'text or html to insert if first link is clicked',
'text or html to insert if second link is clicked',
],
'link_content': [
'string to show on first insert link',
'string to show on second insert link',
],
}

As a note the *link_content* list and insert list must be the same length, as well as
the extra dictionary and the *link_headers* attribute.
The *link_content* list, *insert* list, and *extra* dictionary must all be the
same length, and must match the length of the *link_headers* of your custom FilePicker.

list(request)
^^^^^^^^^^^^^

This takes in a *request* object and outputs.::
This takes a *request* object and returns::

{
'page': Integer of current,
'page': 1-based integer representing current page number,
'pages': List of pages,
'search': The current search term,
'result': List returned from ,
'has_next': Lets the paginator know whether to hide/show the next button.,
'has_previous': Same as above for previous button.,
'link_headers': List of link headers either generated or defined by the attribute.,
'extra_headers': List of the extra headers made in the same we as above.,
'columns': List of column names to be included(same as the columns attribute.),
'result': List returned from *append*,
'has_next': Boolean telling paginator whether to show the next button,
'has_previous': Boolean telling paginator whether to show the previous button.,
'link_headers': List of link headers defined by the Picker attribute (or generated if not defined),
'extra_headers': List of the extra_headers specified by the Picker attribute,
'columns': List of column names specified by the Picker attribute,
}

upload_file(request)
^^^^^^^^^^^^^^^^^^^^

Builds the upload file form and is used to upload files in two steps,
file first then the other form parameters.
This takes a *request* object and builds the upload file form, which is used
to upload files in two steps: first the file, and then the other form parameters.

If called without a POST it returns a JSON dictionary with the key form
with an html block for the form.
If called without POST data it returns a JSON dictionary with the key ``form``
containing the HTML representation of the form.

If called with a file and then with the post, it's a two step process. If the form
passed on the second step it returns the result of append for the object which
was just created.
If called with a file and then with the POST data, it performs a two step
process. If the form validates successfully on the second step it returns the
result of *append* for the object which was just created.
4 changes: 2 additions & 2 deletions docs/sample.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Running the Sample Project

django-file-picker includes a sample project to use as an example. You can run the sample project like so::

~$ mkvirtualenv --distribute filepicker-sample
(filepicker-sample)~$ pip install "django>=1.8,<1.11"
~$ mkvirtualenv filepicker-sample
(filepicker-sample)~$ pip install "django>=1.8,<2.0"
(filepicker-sample)~$ git clone git://github.com/caktus/django-file-picker.git
(filepicker-sample)~$ cd django-file-picker/
(filepicker-sample)~/django-file-picker$ python setup.py develop
Expand Down
8 changes: 3 additions & 5 deletions docs/setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Basic Setup
we will use the models in ``file_picker.uploads``: Image and File.

#. Use or create another model to contain the text field(s) to be inserted
by the picker. Here we will use the Post model from the ``sample_project.article``.
by the picker. Here we will use the Post model from ``sample_project.article``.
It has two text fields, Body and Teaser.

#. To use the pickers on both the teaser and body fields use a *formfield_override*
Expand Down Expand Up @@ -39,7 +39,5 @@ Simple File Picker Widget
.. class:: file_picker.widgets.SimpleFilePickerWidget

To use the simple file picker widget, override the desired form field's widget.
It takes in a dictionary with expected keys `"image"` and/or `"file"` these
define which link to use "Add Image" and/or "Add File".

For an example of usage look at the.
It takes a dictionary with expected keys `"image"` and/or `"file"` which
define which link to use, i.e. "Add Image" and/or "Add File".
6 changes: 3 additions & 3 deletions docs/uploads.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ FilePicker

.. class:: file_picker.uploads.file_pickers.FilePicker

Is a simple class based off of the ``file_picker.FilePickerBase``
This is a subclass of ``file_picker.FilePickerBase``
which is connected to the *File* model and can be found in the Uploads admin
section.

Expand All @@ -23,7 +23,7 @@ ImagePicker

.. class:: file_picker.uploads.file_pickers.ImagePicker

Is a simple class based off of the ``file_picker.ImagePickerBase``
This is a subclass of ``file_picker.ImagePickerBase``
which is connected to the *Image* model and can be found in the Uploads admin
section.

Expand All @@ -39,6 +39,6 @@ on a single text field::
'image': "images",
}))

Where the `"file"` and `"image"` keywords add classes to the inputs, so that the links
The `"file"` and `"image"` keywords add classes to the inputs, so that the links
for the overlay can be added. They can also be added to all fields in a form by
using the *formfield_overrides* as in:ref:`setup`.
7 changes: 3 additions & 4 deletions docs/wymeditor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ WYMeditorWidget
.. class:: file_picker.wymeditor.widgets.WYMeditorWidget

To use the WYMeditorWidget, override the desired form field's widget. It takes in a
dictionary with expected keys `"image"` and/or `"file"` these define which button
dictionary with expected keys `"image"` and/or `"file"` which define which button
is used to call the overlay, either an image or a paper clip icon respectively.

Example TextField Override
**************************
An example using a *formfield_override* in an admin class use WYMeditor and
File Picker for each `TextField` in the form.

::
An example using a *formfield_override* in an admin class using WYMeditor and
a File Picker for each `TextField` in the form::

class PostAdmin(admin.ModelAdmin):
formfield_overrides = {
Expand Down
Empty file removed file_picker/admin.py
Empty file.
7 changes: 2 additions & 5 deletions file_picker/forms.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os

from django import forms
from django.core.files.base import ContentFile
from django.db import models
from django.db.models.base import FieldDoesNotExist

from django.core.files.base import ContentFile


class QueryForm(forms.Form):
page = forms.IntegerField(min_value=0, required=False)
Expand All @@ -15,9 +14,7 @@ class QueryForm(forms.Form):

def clean_page(self):
page = self.cleaned_data.get('page')
if not page:
page = 1
return page
return page or 1


FIELD_EXCLUDES = (models.ImageField, models.FileField)
Expand Down
7 changes: 2 additions & 5 deletions file_picker/sites.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import json

from django.conf.urls import include, url
from django.conf.urls import url
from django.core.urlresolvers import reverse, NoReverseMatch
from django.db import models
from django.db.models.base import ModelBase, FieldDoesNotExist
from django.http import HttpResponse


import file_picker


Expand All @@ -28,8 +27,6 @@ def guess_default(self, model):
return file_picker.FilePickerBase

def register(self, model_or_iterable, class_=None, name=None, **options):
# if not class_:
# class_ = file_picker.FilePickerBase
if isinstance(model_or_iterable, ModelBase):
model_or_iterable = [model_or_iterable]
for model in model_or_iterable:
Expand All @@ -48,7 +45,7 @@ def get_urls(self):
url(r'^$', self.primary, name='index'),
]
for p in self._registry:
urlpatterns += url(r'^%s/' % p['name'], include(p['picker'].urls)),
urlpatterns += url(r'^%s/' % p['name'], p['picker'].urls),
return (urlpatterns, None, "filepicker")
urls = property(get_urls)

Expand Down
5 changes: 3 additions & 2 deletions file_picker/tests.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import os
import file_picker
import datetime
import json
from tempfile import NamedTemporaryFile

from django.db import models
from django.test import TestCase
from django.core.files import File
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.utils.text import capfirst

import file_picker


class Image(models.Model):
"""
Expand Down
1 change: 1 addition & 0 deletions file_picker/uploads/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.contrib import admin

from file_picker.uploads import models as upload_models

admin.site.register(upload_models.Image)
Expand Down
8 changes: 4 additions & 4 deletions file_picker/uploads/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class Migration(migrations.Migration):
('date_created', models.DateTimeField()),
('date_modified', models.DateTimeField()),
('file', models.FileField(upload_to=b'uploads/files/')),
('created_by', models.ForeignKey(related_name=b'uploads_file_created', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name=b'uploads_file_modified', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('created_by', models.ForeignKey(related_name=b'uploads_file_created', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
('modified_by', models.ForeignKey(related_name=b'uploads_file_modified', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
],
options={
'ordering': ('-date_modified',),
Expand All @@ -43,8 +43,8 @@ class Migration(migrations.Migration):
('date_created', models.DateTimeField()),
('date_modified', models.DateTimeField()),
('file', models.ImageField(upload_to=b'uploads/images/')),
('created_by', models.ForeignKey(related_name=b'uploads_image_created', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('modified_by', models.ForeignKey(related_name=b'uploads_image_modified', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('created_by', models.ForeignKey(related_name=b'uploads_image_created', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
('modified_by', models.ForeignKey(related_name=b'uploads_image_modified', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
],
options={
'ordering': ('-date_modified',),
Expand Down
4 changes: 2 additions & 2 deletions file_picker/uploads/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ class BaseFileModel(models.Model):
date_created = models.DateTimeField()
date_modified = models.DateTimeField()
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="%(app_label)s_%(class)s_created",
null=True, blank=True)
null=True, blank=True, on_delete=models.CASCADE)
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="%(app_label)s_%(class)s_modified",
null=True, blank=True)
null=True, blank=True, on_delete=models.CASCADE)

class Meta:
abstract = True
Expand Down
17 changes: 10 additions & 7 deletions file_picker/views.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import os
import logging
import traceback
import tempfile
import datetime
import json
import logging
import os
import tempfile
import traceback

from django.conf.urls import url
from django.core.paginator import Paginator, EmptyPage
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import Q
from django.utils.text import capfirst
from django.http import HttpResponse, HttpResponseServerError
from django.core.paginator import Paginator, EmptyPage
from django.core.urlresolvers import reverse
from django.utils.text import capfirst

from sorl.thumbnail.helpers import ThumbnailError
from sorl.thumbnail import get_thumbnail
Expand Down Expand Up @@ -121,6 +121,9 @@ def get_queryset(self, search):
queryset = self.model.objects.all()
if self.ordering:
queryset = queryset.order_by(self.ordering)
else:
# Need to default to some kind of ordering since we paginate
queryset = queryset.order_by('-pk')
return queryset

def upload_file(self, request):
Expand Down
9 changes: 9 additions & 0 deletions sample_project/sample_project/runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.test.runner import DiscoverRunner


class NoChecksRunner(DiscoverRunner):
# Django 1.11 runs checks before running tests, which causes our urls.py to be loaded before we
# register our file pickers. This turns that functionality off.

def run_checks(self):
pass
Loading

0 comments on commit 2ada252

Please sign in to comment.