Giter Site home page Giter Site logo

django-fm / django-fm Goto Github PK

View Code? Open in Web Editor NEW
76.0 5.0 13.0 410 KB

Modal AJAX form to create, update and delete Django objects with ease. Not maintained these days, feel free to fork.

License: MIT License

Python 30.56% CSS 6.75% JavaScript 53.90% HTML 8.78%

django-fm's Introduction

Live example - see the source code of demonstration in demo repository folder.

Django FM

Requires jQuery and Bootstrap 3 on client side. Depends on django-crispy-forms on server side.

This app allows to make responsive AJAX modal forms for creating, editing, deleting objects in Django. This is a very personalized approach to quickly build admin-like interfaces. It reduces an amount of time and code when making tedious Django work.

Install:

pip install django-fm

Add crispy_forms and fm to INSTALLED_APPS:

INSTALLED_APPS = (
    ...
    'crispy_forms',
    'fm',
)

Also in settings.py set crispy template pack to bootstrap3:

CRISPY_TEMPLATE_PACK = 'bootstrap3'

Include modal template into your project template and initialize jQuery plugin:

<!DOCTYPE html>
<html lang="en">
    <head>
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
        <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    </head>
    <body>
        {% block content %}{% endblock %}
        {% include "fm/modal.html" %}
        <script type="text/javascript">
            $(function() {
                $.fm({debug: true});
            });
        </script>
    </body>
</html>

There are 3 class-based views in django-fm to inherit from when you want AJAX forms:

  • AjaxCreateView
  • AjaxUpdateView
  • AjaxDeleteView

You create urls for them as usual, in templates you just create links to create, update, delete resources with special class (fm-create, fm-update, fm-delete).

Get started

So let's create a view to create new instance of some model. In views.py:

from fm.views import AjaxCreateView
from feedback.forms import FeedbackForm

class FeedbackCreateView(AjaxCreateView):
    form_class = FeedbackForm

You are just inherit from AjaxCreateView and provide form_class argument - you do this every day in Django when inherit from django.views.generic.CreateView, right?

Also you should create url for this resource in urls.py:

from django.conf.urls import patterns, url
from feedback.views import FeedbackCreateView

urlpatterns = patterns(
    'feedback.views',
    ...
    url(r'^create/$', FeedbackCreateView.as_view(), name="feedback_create"),
    ...
)

Again - nothing new here.

The most interesting part in template - you don't have to define template for your form - just write a link to create new object with special attributes which tell django-fm how to behave.

So in your template write:

<a href="{% url 'feedback_create' %}" class="fm-create" data-fm-head="Create" data-fm-callback="reload">Create new</a>

Look at fm-create special class - it's necessary. And that's all - now when user clicks on this link - modal AJAX window with form will be shown.

Every link can have some attributes which define modal window behaviour and callback after successfull object creation, update or deletion:

  • data-fm-head - header of modal
  • data-fm-callback - what to do after successfull modal submission - at moment the following values allowed: reload, redirect, replace, remove, prepend, append, redirect_from_response
  • data-fm-target - value of action specific for each action type - for example this must be an URL when data-fm-callback is redirect

Let's take a closer look at all these available actions:

  • when data-fm-callback omitted - nothing happens - modal window just closes after successfull submission
  • reload - page will be reloaded
  • redirect - page will be redirected to URL from data-fm-target
  • replace - content from element defined via jQuery selector in data-fm-target will be replaced with message from incoming JSON from server
  • remove - element defined via jQuery selector in data-fm-targer will be removed from DOM
  • prepend - message from JSON coming from server will be prepended to element defined in data-fm-target
  • append - message from JSON coming from server will be appended to element defined in data-fm-target
  • redirect_from_response - the current window will be redirected to the message from JSON coming from server. Your view must override the get_response_message method to return the URL to redirect to.
  • also there is a possibility to set custom callback how to react on successfull submission.

See demo project to see this concept in action.

Custom callbacks

Since version 0.2.4 it's possible to register custom callback functions to do non-standard or more complicated logic after success form submission. Here is how you can register new callback (should be used with data-fm-callback="appendWithAlert" parameter):

$(function() {
    $.fm({
        debug: true,
        custom_callbacks: {
            "appendWithAlert": function(data, options) {
                $(options.modal_target).append(data.message);
                alert("model instance created!");
            }
        }
    });
});

Some other things to be aware of

  • note that file upload via AJAX will work in modern browsers only - see this table.
  • when modal with form ready - an event fm.ready will be triggered on body element (by default). This can help to add some javascript widgets into form.
  • you can extend AjaxCreateView, AjaxUpdateView and AjaxDeleteView using standard Django techniques. For example, you can add permission checking using PermissionMixin from django-braces project

django-fm's People

Contributors

avendael avatar fzambia avatar martync avatar petrdlouhy avatar sheymans avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

django-fm's Issues

Error occurred while loading

I remember having this problem a while back but can't remember how I fixed it then.

I always get the error "Error occurred while loading" when submitting the modals, even though the database updates properly.

Form wont load when using widgets with own script media

It seems that if you use a widget such as a datetimepicker, select2 etc that loads its own scripts with the field then the form wont load at all. I know this is a common problem with modal content but this seems to destroy the form completely. Any ideas/workaround?

Adding a redirection to an URL received from the response

Hi,

Thanks for this beautiful project, it's really pleasant to use, good job !
Since I'm using it, I had 2 use cases where I need to redirect the user to an URL generated on the server side.

For example, after creating a new instance through the modal, I want to redirect my user to an advanced settings of that instance. I can't provide data-fm-target because it doesn't exist yet.

Let me know if you're interested by adding this feature, I can work on it, and I'll do it with pleasure.

Cheers

[Errno 32] Broken pipe when saving AjaxUpdateView on page with ModelForm

I'm getting a broken pipe error when saving an AjaxUpdateView that resides on the same page as a ModelForm. The Ajax POST request to save the updated form seems to be firing twice, and the second one hits a 500 error.

This is also causing the ModelForm on the page to be POSTed (POST /results/review/255/) rather than GETed, so the ModelForm is being submitted unexpectedly without an instance, so could result in losing all data in that ModelForm.

Traceback (starting from submitting AjaxUpdateView form):

[22/Oct/2014 14:26:37] "POST /results/test-result/2085/edit/ajax/ HTTP/1.1" 200 31
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 86, in run
    self.finish_response()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 128, in finish_response
    self.write(data)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 212, in write
    self.send_headers()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 270, in send_headers
    self.send_preamble()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 194, in send_preamble
    'Date: %s\r\n' % format_date_time(time.time())
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 324, in write
    self.flush()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
[22/Oct/2014 14:26:37] "POST /results/test-result/2085/edit/ajax/ HTTP/1.1" 500 59
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 53466)
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 593, in process_request_thread
[22/Oct/2014 14:26:37] "POST /results/review/255/ HTTP/1.1" 200 20458
    self.finish_request(request, client_address)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/Users/johnfraney/Projects/acculab/env/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 129, in __init__
    super(WSGIRequestHandler, self).__init__(*args, **kwargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 651, in __init__
    self.finish()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 710, in finish
    self.wfile.close()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 279, in close
    self.flush()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------
[22/Oct/2014 14:26:37] "GET /static/fm/js/fm.js?v=0.1.6 HTTP/1.1" 304 0

Patch 0.2.2 breaks for forms that don't specify a helper

#13 fixes forms that pass a crispy form helper, but breaks for forms like this one

class NameForm(forms.ModelForm):
    class Meta:
        model = Name
        fields = (
            'first_name',
            'middle_name',
            'last_name'
        )
VariableDoesNotExist: Failed lookup for key [helper] in u'<tr><th><label for="id_first_name">First name:</label></th><td><input id="id_first_name" maxlength="128" name="first_name" type="text" /></td></tr>\n<tr><th><label for="id_middle_name">Middle name:</label></th><td><input id="id_middle_name" maxlength="128" name="middle_name" type="text" /></td></tr>\n<tr><th><label for="id_last_name">Last name:</label></th><td><input id="id_last_name" maxlength="128" name="last_name" type="text" /></td></tr>'

render_to_string in 1.10

Hi!

The dictionary and context_instance parameters for the following functions are removed:
django.shortcuts.render()
django.shortcuts.render_to_response()
django.template.loader.render_to_string()

Can you fix it?
Thanks!

AjaxDeleteView doesn't do anything

my normal delete views are working, but when I add to the link
class="fm-delete" data-fm-head="Delete" data-fm-callback="reload"
and set my view to AjaxDeleteView , nothing happens.
I click the delete link, I see an empty modal window, but there isn't an ajax call to load the delete_confirm template. no error messages.

Other views are working fine (like AjaxUpdateView)

Custom error messages

Hi, is there a way to send in my own error messages in stead of getting "Error occurred while loading"?

I am using fm-modal for creating and updating multiple models and there can be a number of issues causing errors. For example if the user tries to create a category but the company doesn't exist. I would like to then give a message such as "Error creating category. Please create company first".

I have tried to use def get_error_result(self,ApplicationRateCategoryForm) in my view but it is never called.
Any suggestions would be greatly appreciated!

Submitting of invalid form

hi,

first, thanks a lot for this little library; comes in very handy!

There is a minor bug when you try to repeatedly submit a failed form. The "submit" button does not get properly binded anymore (instead it starts posting to the originating page of the modal, not to the modal URL itself).

To reproduce:

  1. Submit a form with some mandatory field empty.
  2. Get a invalid form message back.
  3. Submit the same form (still invalid); this POST now goes to the underlying URL (not the modal URL).

I'll do a pull request that fixes it, but you should probably check that it is inline with what you have in mind.

Stijn

support for custom template modal

How i can add my own custom template for modal form?

And adding for Django 1.10, because error inside file fm.views.py:
the problem is:
- old:
return render_to_string(
self.message_template,
self.get_message_template_context(),
context_instance=RequestContext(self.request)
)

- new
return render_to_string(
self.message_template,
self.get_message_template_context(),
context=RequestContext(self.request)
)

And i want to get permission if i want to create project in github based on your work.

django.core.urlresolvers.NoReverseMatch:

Hi.
I have been testing django-fm in my project. Creation and deletion of objects work fine, but I am having a problem with update. When I click on 'OK' to submit the modal form after editing the update form, the changes are saved to the database. But there is a problem with the callback:

Request URL: http://127.0.0.1:8000/establishment/subspecialities/update/15/

Error:
django.core.urlresolvers.NoReverseMatch: Reverse for 'subspeciality_update' with arguments '()' and keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['establishment/subspecialities/update/(?P<pk>\\d+)/$']

Edit and delete buttons :
<a href="{% url 'establishment:subspeciality_update' pk=subspeciality.pk %}" class="fm-update btn blue-madison btn-circle btn-xs" data-fm-head="Edit Sub-speciality" data-fm-callback="replace" data-fm-target="#row-{{ subspeciality.pk }}">Edit<i class="fa fa-pencil"></i></a>

`<a href="{% url 'establishment:subspeciality_delete' pk=subspeciality.pk  %}" class="fm-delete btn red-sunglo btn-circle btn-xs  btn" data-fm-head="Delete Sub-speciality?" data-fm-callback="remove" data-fm-target="#row-{{ subspeciality.pk }}">Delete<i class="fa fa-times"></i></a>`

As you can see, in the case of update, reverse is not finding the url because the pk kwargs is empty. If I go up the call stack, I can see kwargs = {pk:'15'}, but I can't work out where of why it is being 'lost'

The only substantial differences between this and you demo example is that the subspeciality model has a foreign key, and the CRUD urls are not defined in the root urls, but included.

Can you suggest any areas that I should check for mistakes?

Rgds

Unable to pass crispy helper layout to django-fm modal

I am able to render the form below w/ 2 fields in the same row using {% crispy MyCrispyForm %} tags in my template, but when using django-fm, it renders the two fields in its own separate rows. From inspecting the rendered elements, it appears that it is not passing the crispy form's helper.layout to the modal.

class MyCrispyForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = [
            "firstname",
            "lastname",
            ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)     
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Div(
                Div('firstname', css_class="col-sm-6"),
                Div('lastname', css_class="col-sm-6"),
                css_class = 'row'
            ),
        )

Documentation says data-fm-action but it should be data-fm-callback

Where it reads:

data-fm-action - what to do after successfull modal submission - at moment the following values allowed: reload, redirect, replace, remove, prepend, append

it turns out that data-fm-action does not exist, and it is data-fm-callback instead.

Fixing the docs might save some people's time.

Thanks for the great work!

Two or more callbacks

Hello, i want to know if its possible to define more than 1 value to data-fm-callback, for example if i want to edit an entry and leave a message.

Thanks

Static files / template files not being found

This could be due to an error on my part, but after installing django-fm, following the directions, and running manage.py collectstatic, my Django app isn't able to find django-fm's templates and static files.

{% include "fm/modal.html" %} gives me a TemplateDoesNotExist error. django-fm is not listed in the directories searched by django.template.loaders.app_directories.Loader.

This is my TEMPLATE_LOADERS from settings.py:

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
)

I know that django-fm is installed properly because the {% load fm_tags %} and {% fm_version %} template tags work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.