Giter Site home page Giter Site logo

djk2 / django-popup-view-field Goto Github PK

View Code? Open in Web Editor NEW
22.0 5.0 6.0 400 KB

Field and widget can render bootstrap dialog window with content from django view.

License: MIT License

Python 65.76% HTML 15.13% JavaScript 19.09% Shell 0.02%
django crispy popup dialog bootstrap3 field

django-popup-view-field's Introduction

django-popup-view-field

Latest PyPI version Travis CI Requirements Status

Field and widget can render bootstrap dialog with content from django view. You can create normal django View and load this view in dialog for form field.

  • Support:

    • Python: 2.7, 3.6
    • Django: 1.9, 1.10, 1.11, 2.0, 2.1, 2.2, 3.0
    • django-crispy-forms
    • django-bootstrap3
    • django-bootstrap4 (!Only for Django >= 2.1)
  • Require:

    • Django
    • bootstrap3 or bootstrap4
    • JQuery
  • Recommended:

    • django-bootstrap3 or django-bootstrap4
    • django-crispy-forms
  • Locale:

    • EN - (english)
    • PL - (polish)
  • Tested on browsers:

    • OK - Chromium 79.0.3945.79 - Ubuntu 18.04
    • OK - Firefox 72.0.1 (64 bity) - Ubuntu 18.04
    • OK - Google Chrome 70.0 - Fedora 28
    • OK - Firefox 62.0.3 - Fedora 28
    • OK - Firefox 50.1.0 - Ubuntu 14.04
    • OK - Firefox 31.1 - CentOS 6.4
    • OK - Chromium 53.0 - Ubuntu 14.04
    • OK - Microsoft Edge 38 - Windows 10
    • OK - Internet Explorer 11.0 - Windows 10
    • OK - Internet Explorer 10.0 - Windows 7
    • OK - Internet Explorer 9.0 - Windows 7
    • ER - Internet Explorer <= 8 (no support "html()" for data-popup-view-value)

Screenshots

  • Example: Form with several popup-view-fields

Form with django-popup-view-fields

  • Example: Dialog for select sex

Dialog for select sex

  • Example: Dialog for select color

Dialog for select color

  • Example: Dialog with form

Dialog with form

Run demo

  1. Clone or download repository:

    git clone https://github.com/djk2/django-popup-view-field.git
    
  2. Create virtualenv or not (red more: http://docs.python-guide.org/en/latest/dev/virtualenvs/)

  3. Install requirements for demo:

    cd django-popup-view-field/demo
    
    pip install -r requirements.txt
    
  4. Run developing web server:

    python manage.py runserver
    
  5. Run your browser and call url: 127.0.0.1:8000

    firefox 127.0.0.1:8000
    

Install

Install package - There are several solutions, choose your own

  1. Install using pypi repository:

    pip install django-popup-view-field
    
  2. Install using pip + github repository url:

    pip install git+https://github.com/djk2/django-popup-view-field.git
    
  3. Install using pip + zip archive:

    wget https://github.com/djk2/django-popup-view-field/archive/master.zip
    pip install master.zip
    
  4. Clone or download application to your django project directory:

    wget https://github.com/djk2/django-popup-view-field/archive/master.zip -O /tmp/master.zip
    unzip /tmp/master.zip -d /tmp/
    cd my_project_dir
    cp -r /tmp/django-popup-view-field-master/django_popup_view_field/ ./
    

Add django_popup_view_field to your INSTALLED_APPS setting

settings.py

INSTALLED_APPS = [
    ...
    'bootstrap3',    # If you use django-bootstrap3
    'crispy_forms',  # If you user django-crispy-forms

    'django_popup_view_field',
    ...
]

# If you want use bootstrap4 then uncomment
# DJANGO_POPUP_VIEW_FIELD_TEMPLATE_PACK = 'bootstrap4'
Warning:
Is recommended use django-bootstrap3/django-bootstrap4 or django-crispy-forms to render forms and fields, but this is not necessary. You can still write django templates using pure CSS from bootstrap3/4. More information about bootstrap forms in here: http://getbootstrap.com/css/#forms

Add the django_popup_view_field urls to your root url patterns

urls.py

urlpatterns = [
    ...
    url(
        r'^django_popup_view_field/',
        include('django_popup_view_field.urls', namespace="django_popup_view_field")
    ),
]
Note:
The URL path can be whatever you want, but you must include 'django_popup_view_field.urls' with the 'django_popup_view_field' namespace. You may leave out the namespace in Django >= 1.9

In your base template, add django_popup_view_field_javascript tag

django_popup_view_field_javascript template tag load all required javascripts and template-scripts for application. Tag should be append before body close </body> tag and after jQuery and Bootstrap scripts.

base.html

<!DOCTYPE html>
{% load django_popup_view_field_tags %}

<html>
    <head>
        ...
        <!-- Bootstrap CSS should be here -->
        ...
    </head>

    <body>
        ...
        ...
        <!-- jQuery script should be here -->
        <!-- Bootstrap javascripts should be here -->
        ...
        ...
        {% django_popup_view_field_javascript %}
    </body>
</html>

Settings

DJANGO_POPUP_VIEW_FIELD_TEMPLATE_PACK

Since version 0.6.0, django-popup-view-fields has built-in support for bootstrap4 also. To enable support for bootstrap4 you have to set DJANGO_POPUP_VIEW_FIELD_TEMPLATE_PACK to "bootstrap4" value.

  • bootstrap3 - this setting will be load javascript and html templates for bootstrap3.
    This is a default value
  • bootstrap4 - this setting will be load javascript and html templates for bootstrap4.

Value of DJANGO_POPUP_VIEW_FIELD_TEMPLATE_PACK is changing behavior of '{% django_popup_view_field_javascript %}' tag and PopupViewWidget class. Template scripts_include.html is using this flag to decide which template and javascript will be load. PopupViewWidget class is using this flag to decide which template for field should be load.

Simple Example

Simple Example - screenshot

Create PopupView

Html content rendered by this view will be loaded into bootstrap dialog. Create your popup view same as normal django view.

Your popup view must be subclass of django.views.generic.View

templates/myapp/popups/colors.html

<ul>
    <li data-popup-view-value="red" style="background:red;"> red hat </li>
    <li data-popup-view-value="blue" style="background:blue;"> blue sky </li>
    <li data-popup-view-value="green" style="background:green;"> green planet </li>
    <li data-popup-view-value="pink" style="background:pink;"> pink car </li>
</ul>

If user click on the element with the attribute data-popup-view-value, the value of this attribute will be set in form field and dialog will close.


If you want set content of element as value in form field, use html() for attribute:

<li data-popup-view-value="html()"> This text will be use :) </li>

popups.py

from django.views.generic import TemplateView
from django_popup_view_field.registry import registry_popup_view

class ColorsPopupView(TemplateView):
    template_name = 'myapp/popups/colors.html'

# REGISTER IS IMPORTANT
registry_popup_view.register(ColorsPopupView)

Remember that you must register your popup view. After register you can run your popup view by call url:

..../django_popup_view_field/ColorsPopupView

In template you can get url to popup view using url tag:

{% url "django_popup_view_field:get_popup_view" 'ColorsPopupView' %}

After register you can unregister your popup view:

registry_popup_view.unregister(ColorsPopupView)

# or unregister by view name

registry_popup_view.unregister_by_name('ColorsPopupView')

You can also get popup view class by name:

view_class = registry_popup_view.get('ColorsPopupView')
view_class.as_view()

Create Form with PopupViewField

forms.py

from django import forms
from django_popup_view_field.fields import PopupViewField
from myapp.popups import ColorsPopupView

class ColorForm(forms.Form):

    color = PopupViewField(
        view_class=ColorsPopupView,
        popup_dialog_title='What is your favorite color',
        attrs={'readonly': True},
        required=True,
        help_text='be honest'
    )

class PopupViewField(view_class, popup_dialog_title, *args, **kwargs)

  • view_class - required - popup view class, view to render dialog content, must be subclass of django.views.generic.View
  • popup_dialog_title - not required - Title for dialog, default Popup Dialog: Select value
  • attrs - not required - provides attributes for Widget
  • args and kwargs are default for CharField

Create typical FormView

views.py

from django.views.generic import FormView
from myapp.forms import ColorForm
from django.http import HttpResponse

class ColorFormView(FormView):
    template_name = "myapp/color_form.html"
    form_class = ColorForm

    def form_valid(self, form):
        color = form.cleaned_data.get("color")
        return HttpResponse("Your color: {0}".format(color))

Template using django-crispy-forms

templates/myapp/color_form.html

{% extends "base.html" %}
{% load crispy_forms_tags %}
{% crispy form %}

Template using django-bootstrap3

templates/myapp/color_form.html

{% extends "base.html" %}
{% load bootstrap3 %}

<form action="." method="post" class="form">
    {% csrf_token %}
    {% bootstrap_form form %}
    {% buttons %}
        <button type="submit" class="btn btn-primary">Submit</button>
    {% endbuttons %}
</form>

Template with pure bootstrap3 css (without django-bootstrap3 and crispy)

templates/myapp/color_form.html

{% extends "base.html" %}
<form action="." method="post" class="form">
    <div class="form-group">
        <label class="control-label"> {{ form.color.label }} </label>
        {{ form.color }}
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

callback_data attribute

If you want pass extra parameters to your popup view, you should use callback_data attribute for PopupViewField. This argument should be dictionary or OrderedDict. This dictionary containing yours parameters will be encoded to ASCII text string and added to url address. In your popup view You can take this parameters from request.GET.

popups.py

from django.views.generic import View
from django_popup_view_field.registry import registry_popup_view

class FooPopupView(View):
    def get(self, request):
        print(request.GET['extra_param'])  # --> will be "Foo Bar"
        print(request.GET['my_pk'])        # --> will be 666
        ....

# REGISTER IS IMPORTANT
registry_popup_view.register(FooPopupView)

forms.py

from django import forms
from django_popup_view_field.fields import PopupViewField

class FooForm(forms.Form):

    some_field = PopupViewField(
        view_class=FooPopupView,
        callback_data={
            'extra_param': 'Foo Bar',
            'my_pk': 666
        }
    )

Advanced Example

Advanced Example use django-bootstrap3. Dialog is interactive, all links and forms will be send via Ajax and response will be loaded in dialog.

Advanced Example - screenshot

PopupView

templates/myapp/popups/alphabet.html

<h4> Select the first letter of your name </h4>

{% for char in alphabet %}
    <div class="btn btn-xs btn-info" data-popup-view-value="html()">
        {{ char }}
    </div>
    {% if forloop.counter|divisibleby:"13" and forloop.counter > 0 %}
        <br/><br/>
    {% endif %}
{% endfor %}

{# Button to change order #}
<a class="btn btn-xs btn-primary" style="margin-top:20px;"
          href="{% url "django_popup_view_field:get_popup_view" 'AlphabetPopupView' %}?direction={{direction}}">
    Reverse order
</a>

popups.py

from django.views.generic import TemplateView
from django_popup_view_field.registry import registry_popup_view
from string import ascii_uppercase

class AlphabetPopupView(TemplateView):
    template_name = 'myapp/popups/alphabet.html'
    direction = 1

    def get_context_data(self, **kwargs):
        self.direction = int(self.request.GET.get("direction") or self.direction)
        alphabet = ascii_uppercase[::self.direction]
        ctx = super(AlphabetPopupView, self).get_context_data(**kwargs)
        ctx['alphabet'] = alphabet
        ctx['direction'] = self.direction * -1
        return ctx

# REGISTER IS IMPORTANT
registry_popup_view.register(AlphabetPopupView)

Form with PopupViewField

forms.py

from django import forms
from django_popup_view_field.fields import PopupViewField
from myapp.popups import AlphabetPopupView

class AlphabetForm(forms.Form):

    char = PopupViewField(view_class=AlphabetPopupView, required=True)

View

templates/myapp/alphabet.html

{% extends "base.html" %}
{% load bootstrap3 %}

<form action="." method="post" class="form">
    {% csrf_token %}
    {% bootstrap_form form %}
    {% buttons %}
        <button type="submit" class="btn btn-primary">Submit</button>
    {% endbuttons %}
</form>

views.py

from django.views.generic import FormView
from myapp.forms import AlphabetForm
from django.http import HttpResponse

class AlphabetFormView(FormView):
    template_name = "myapp/alphabet.html"
    form_class = AlphabetForm

    def form_valid(self, form):
        char = form.cleaned_data.get("char")
        return HttpResponse("First letter of your name : {0}".format(char))

PopupViewModelField Example

PopupViewModelField allows you to send model objects through the form inheriting from ModelForm.

PopupViewModelField Example - screenshot

Model

models.py

from django.db import models


class Country(models.Model):
    code = models.CharField(max_length=2, primary_key=True)
    name = models.CharField(max_length=256)


class ExampleUser(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    country_code = models.ForeignKey(Country, on_delete=models.PROTECT)

PopupView

templates/myapp/popups/country.html

<ul>
    {% for country in countries %}
        <li style="cursor:pointer" data-popup-view-value="{{ country.code }}">
            <strong>{{ country.code }}</strong> - {{ country.name }}
        </li>
    {% endfor %}
<ul>
Note:
data-popup-view-value attribute should return the primary key value of the model object.

popups.py

class CountryPopupView(TemplateView):

template_name = "myapp/popups/country.html"
countries = None

def get(self, request, *args, **kwargs):
    self.countries = Country.objects.all()
    return super(CountryPopupView, self).get(request, *args, **kwargs)

def get_context_data(self, **kwargs):
    context = super(CountryPopupView, self).get_context_data(**kwargs)
    context['countries'] = self.countries
    return context

# REGISTER IS IMPORTANT
registry_popup_view.register(CountryPopupView)

Form with PopupViewModelField

forms.py

from django import forms
from django.forms import ModelForm
from .models import Country, ExampleUser
from django_popup_view_field.fields import PopupViewModelField

class CountryForm(ModelForm):

    country_code = PopupViewModelField(
        queryset=Country.objects.all(),
        view_class=CountryPopupView,
        required=True
    )

    class Meta:
        model = ExampleUser
        fields = ('first_name', 'last_name', 'country_code')
Note:
PopupViewModelField must have an additional queryset argument in which we pass model objects.

View

templates/myapp/country.html

{% extends "base.html" %}
{% load bootstrap3 %}

<form action="." method="post" class="form">
    {% csrf_token %}
    {% bootstrap_form form %}
    {% buttons %}
        <button type="submit" class="btn btn-primary">Submit</button>
    {% endbuttons %}
</form>

views.py

from django.views.generic import FormView
from myapp.forms import CountryForm
from django.contrib import messages

class CountryFormView(FormView):
    template_name = "myapp/country.html"
    form_class = CountryForm

    def form_valid(self, form):
        ret = super(CountryFormView, self).form_valid(form)
        country_code = form.cleaned_data.get("country_code")
        messages.success(
            self.request,
            "Success in create example user with code of country: {0}".format(country_code)
        )
        return ret

Others

django-popup-view-field's People

Contributors

djk2 avatar g1sky avatar

Stargazers

 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-popup-view-field's Issues

Not a bug, but I am asking if it is possible: pass another form field data value to the popup field view modal box

In form.py: I am passing the ID field to the PopupViewField instance.

class APReviewForm(Form):
 fields=['ID', 'Name', 'Rating' 'Reason']
def __init__(self, *args, **kwargs):
 super(APReviewForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.fields['ID'] = IntegerField()
self.fields['Name'] = CharField()
self.fields['Rating'] = ChoiceField(widget=Select(), choices=RATING_CHOICES)
self.fields['Reason'] = PopupViewField(
view_class=SelectionReasonPopUpView,
popup_dialog_title="Please select a reason for the Pattern",
callback_data={'my_id': self.fields['ID'].initial, 'other_param': 'xxx'},
required=True,
)

That goes in formset:
APReviewFormSet = formset_factory(APReviewForm, extra=0)

In my view, I have: I am setting some initial data for the formset in the get_context_data method.

class OntoRecAPView(FormView):
    form_class = APReviewForm
    template_name = "RecSys/ontoRecAPView.html"

    def get_context_data(self, **kwargs):
        context = super(OntoRecAPView, self).get_context_data(**kwargs)
        if self.request.POST:
            context['formset'] = APReviewFormSet()
        else:
            #Todo: Get attack patterns
            #returnWebAttackResults()
            context['formset'] = APReviewFormSet(
                initial=[{'ID':1, 'Name':"Ap Name1",
                          },
                         {'ID': 2, 'Name': "Ap Name2",
                          },
                         {'ID': 3, 'Name': "Ap Name3",
                          }
                         ])
        return context

In my popups.py, I have: I want when the load button is press, the ID from the respective APReviewForm is passed to the SelectionReasonPopUpView (PopupViewField) as shown below. I do some processing based on the ID value before the popup is shown to the user.

class SelectionReasonPopUpView(TemplateView):
    template_name='popups/selectionReason.html'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        my_id = self.request.GET.get("attackPattern_id")
       myFunc(my_id)
        context['myContext'] = myFunc(my_id)
        return context

This is variant of #5

Not a bug, but how can i use this widget in dynamic formset

Hello there,

i like this widget very much but have been struggling to implement in a dynamic formset.

When i add a new form to formset, jquery just clone the row corresponding to form fields, cleans it, and gives new ids. But it doesn't copy information about widgets.

my code is as below:

function cloneMore(selector, prefix) {
var newElement = $(selector).clone(true);
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
newElement.find(':input:not([type=button]):not([type=submit]):not([type=reset])').each(function() {
var name = $(this).attr('name')
if(name) {
name = name.replace('-' + (total-1) + '-', '-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
}
});
newElement.find('label').each(function() {
var forValue = $(this).attr('for');
if (forValue) {
forValue = forValue.replace('-' + (total-1) + '-', '-' + total + '-');
$(this).attr({'for': forValue});
}
});
newElement.find('.vDateField').each(function() {
// Remove the cloned spam element: it links to an incorrect calendar
$(this).parent().find('.datetimeshortcuts').remove();
// DateTimeShortcuts is defined in DateTimeShortcuts.js in the Django admin media
DateTimeShortcuts.addCalendar(this);
});
total++;
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
var conditionRow = $('.form-row:not(:last)');
conditionRow.find('.btn.add-form-row')
.removeClass('btn-success').addClass('btn-danger')
.removeClass('add-form-row').addClass('remove-form-row-new')
.html('-');
return false;
}

as you can see above, i had the same problem with AdminDateWidget, and what i did is to remove it first and add it back. so my question is how i could do for django-popup-view-field?

many thanks

regards,
Jun

Not work in IIS

Hi there,

would really appreciate if you let me know the way to fix it.

i have developed a django app which uses your pop up. it works fine on the development server. however, when i deploy the app using IIS on windows server, it stops working - when i click the magnify glass button, nothing happens.

could you please let me know whether there is anything i need to do in iis to get it work again? many thanks

regards,
Jun Wang

Django3, bootstrap4, no popup is being shown

I downloaded the new repo and installed the latest version of jango-popup-view-field. I tried running your demo, but I the popup for the the bootstrap is not displaying. In the logs, it shows that there is a request, but no popup is being shown. Also, I am running Django 3.x.x because I cannot install Django 2.2.9 that is in the requirement.txt.

Originally posted by @ImanoWilliams in #8 (comment)

AttributeError: 'PopupViewField' object has no attribute 'is_hidden'

I am trying to modify your demo to work with model forms. Below is what I have tried but getting "AttributeError: 'PopupViewField' object has no attribute 'is_hidden'"

 
class DemoForm(ModelForm):
	class Meta:
		model=Country
		fields ='__all__'
		widget={
		'name':PopupViewField(
                # Attrs for popup
                view_class=SexPopupView,
                popup_dialog_title='What is your SEX',
                # Attr for CharField
                required=True,
                help_text='female or male'
		))}
			

	def __init__(self, *args, **kwargs):
		super(DemoForm, self).__init__(*args, **kwargs)
		self.helper = FormHelper()

Passing values to Detailview of Popup

@djk2 I want to make a detailview popupview like so. When the user clicks on the selectionReason where the popupfield is placed, I want to pass a primary key from the AttackPatternForm to detail view of the popupview. I will then call the attackpattern values in the template file.

I basically want to get a value from the template file where the AttackPatternForm is and pass it to the
popupview that inherits from Detail view. See code below. It is quite similar to your CountryPopupView, but the user would not search since the query filter will be passed in from the template that renders AttackPatternForm.
My issue is how to pass the value from the form and then use it to query in the detailview of the popupfield view.

forms.py

class AttackPatternForm(ModelForm):
    class Meta:
        model=AttackPattern
        fields='__all__'
    selectionReason=PopupViewField(
        view_class=SelectionReasonPopUpView,
        popup_dialog_title="Please select a reason for",
        required=True
        )
    def __init__(self, *args, **kwargs):
        super(AttackPatternForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()

popups.py

class SelectionReasonPopUpViews(DetailView):
    template_name = 'popups/selectionReason.html'
    model = AttackPattern
    #How to get a value from the parent form in the detailview?

template: 'popups/selectionReason.html

<ul>
    <li data-popup-view-value="Description"> {{attackpattern.description}} </li>
	<li data-popup-view-value="Flow" > {{attackpattern.flow}} </li>
</ul>

Multiple nested popups

Sorry for my laziness but I have been checking lots of libraries looking for nested popups with no luck.

The question is if it handles multiple nested or level popups. For example:

We are at Blog post view: popup select Category (popup 1.0) > Category does not exist > New popup Create category (popup 1.1) > Category form, image for category does not exist > New popup Upload image for category (popup 1.2).

Thanks in advance.

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.