I have a django (2.0) application with a page that contains two separate forms that are not meant to interact with each other at all. However, I am getting some weird behavior. Pictured here, when I click on one of the labels on the bottom form, it triggers the checkbox for the corresponding (based on row, not name) element in the upper form (clicking "members" on the group form selected "Email" on the person form). This only goes one way--clicking anywhere on the top form never effects the bottom form. Checking the actual boxes of the bottom form do trigger the expected boxes that their labels correspond to.
The html for this page is:
<head>
{% load static %}
<title>LDAP - Search</title>
<link rel="shortcut icon" href="{% static 'djangoWrapper/favicon.ico' %}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{% static 'ldap/style.css' %}">
</head>
<body>
<h1>Search</h1>
<div class="search-form">
<h2>Search for Person</h2>
<form action="{% url 'ldap:person_results' %}" method='post'>
{% csrf_token %}
<table>
{{ personForm }}
</table>
<input type="submit" value="Search">
</form>
</div>
<div class="search-form">
<h2>Search for Group</h2>
<form action="{% url 'ldap:group_results' %}" method='post'>
{% csrf_token %}
<table>
{{ groupForm }}
</table>
<input type="submit" value="Search" />
</form>
</div>
<div class="url">
or go back to login
</div>
</body>
And the forms are
class PersonSearchForm(forms.Form):
uniqname = forms.CharField(label="uniqname", max_length=10)
options = personFieldsDict.items()
attributes = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple, choices = options, label='',
required=False)
class GroupSearchForm(forms.Form):
groupName = forms.CharField(label='Group Name')
options = groupFieldsDict.items()
attributes = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple, choices = options, label='',
required=False)
And the view that renders this page is simply:
def search(request):
personForm = PersonSearchForm()
groupForm = GroupSearchForm()
context = {'personForm': personForm, 'groupForm': groupForm}
return render(request, 'ldap/search.html', context)
I am guessing that this has something to do with the fact that both forms use a MultipleChoiceField widget, but I can't see how they are interacting with each other if their attributes are different and they are in different div's. Any idea on why there is this interaction? Thanks.
You should use the prefix argument to one or both forms to prevent the fields from interferin with each other.
personForm = PersonSearchForm(prefix="person")
groupForm = GroupSearchForm(prefix="group")
Don't forget to also use the prefixes when instantiating the form on post.
Related
I have a large django model with about 800 objects and I want to create a view in which the user can select a certain number of those objects to pass to another view for further processing. The fact that there are so many objects of the model makes listing all the objects very unpractical, as the user would have to scroll through 800 objects.
In order to address this problem, I want to place an as-you-type search-bar in the top of the view so that the user can type the name of the objects and select them by clicking them. When the objects are selected, they should appear under the search-bar as tags that the user can remove by clicking an "x" next to each one.
When the user has made all the required selections, then they should be able to click a button and jump to the next view where those selected objects are accessible.
The model I am using can be simplified to:
class Song():
song_name = models.CharField(max_length=256)
song_author = models.CharField(max_length=256, blank=True)
song_content = models.TextField()
def __str__(self):
return self.song_name
class Meta:
ordering = ['song_order']
song_order = models.PositiveIntegerField(editable=False, db_index=True)
So far I have been able to make a view to search through the model.
mytemplate.html
<!DOCTYPE html>
{% load static %}
<html style="height: 100%;" lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="preload" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons" as="style" onload="this.rel='stylesheet'">
<link rel="preload" href="https://unpkg.com/bootstrap-material-design#4.1.1/dist/css/bootstrap-material-design.min.css" as="style" onload="this.rel='stylesheet'">
<link rel="stylesheet" href="{% static 'css/main.css' %}">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
</head>
<body>
{% block body_block %}
<div class="container" style="padding-bottom:40px;margin-top: 35px;">
<div class="form-group">
<label for="searchInput" class="bmd-label-floating">Search</label>
<input type="text" class="form-control" id="searchInput" oninput="filter()">
</div>
<ul class="list-group bmd-list-group-sm">
{% for song in songs %}
<div
class="list-group-item"
data-title="{{song.song_name}}"
data-author="{{song.song_author}}"
data-lyrics="{{song.song_content}}">
<h4>
{{song.song_name}}
{% if song.song_author %}
({{ song.song_author }})
{% endif %}
</h4>
</div>
{% endfor %}
</ul>
</div>
<script>
$('#searchInput').focus();
function short(s) {
let punctuationRegEx = /[.,\/#!$%\^&\*;:{}=\-_`~()]/g;
return s.replace(punctuationRegEx, '')
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "");
}
function filter() {
let f = short($('#searchInput').val());
$('.list-group-item').each(function (index) {
if (short($(this).data('title') + "").includes(f) ||
short($(this).data('author') + "").includes(f)
) {
$(this).show();
} else {
$(this).hide();
}
});
}
</script>
{% endblock %}
</body>
</html>
views.py
class SongListView(ListView):
context_object_name = 'songs'
model = Song
template_name = "songapp/mytemplate.html"
Any ideas on how to do the selection?
I have created a part inventory program with the as you type search.
It's a complete example of ajax call for search and database.
You can modify it to show the results under the search with the X.
https://github.com/edcodes/Django-Parts-Inventory
I want to make a Django app that searches on google a string and then saves the html page.
so far I managed to
create this
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div class="container text-center">
<h1>my search engine</h1>
<h3>Pressing search will run a google search for 'lallero search', then the code will scrape the first 5 links in that google search and store the corresponding html.</h3>
About page
<br>
<br>
<form action="{% url 'search' %}">
<input type='submit' value='search' class="btn btn-primary">
</form>
</div>
that searches on google a very specific string and it is just a press button.
I would like to add a form where I can write the string I want to search and then pass it as input to my "search" function
so far I came out with this
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div class="container text-center">
<h1>my search engine</h1>
About page
<br>
<br>
<form action="{% url 'search' %}">
<input type="search" value='lallero search' class="form-control rounded" placeholder="Search" aria-label="Search"
aria-describedby="search-addon" />
<button type="button" class="btn btn-outline-primary">search</button>
</div>
but I do not know how to pass the string I write as input to the function.
any advice?
--------------------update
Following comments, I put the SearchForm into a utils file that I import and then I changed my search function to
def search(request):
form = SearchForm(request.GET)
if form.is_valid(): # this will validate your form
search_text = form.cleaned_data["search"] # now you can access input
urls = searchWeb(num=5, stop=5, query_string=search_text)
threads = [threading.Thread(target=getSavePage, args=(url,)) for url in urls]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
return JsonResponse(urls, safe=False)
I changed my template to
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div class="container text-center">
<h1>my search engine</h1>
About page
<br>
<br>
<form action="{% url 'search' %}">
{{ form.non_field_errors }}
{{ form.as_p }} <!-- This will create a text input with attributes -->
<input type="submit" value="Submit">
</form>
</div>
I get an error as the form status is unknown
Briefly, in your view that is been invoked by the form can access your form data with request.GET, request.POST. Since its search functionality get method should be used. And your input will be in your querysting something like www.yourdomain.com/search-view?search=input.Instead of accessing it by request.GET["search"], django forms will be a better choice. In your case
from django import forms
class SearchForm(forms.Form):
search = forms.CharField(required=True, max_lenght=255, label="Search")
And you can use it in your template as
<form action="{% url 'search' %}">
{{ form.non_field_errors }}
{{ form.as_p }} <!-- This will create a text input with attributes -->
<input type="submit" value="Submit">
</form>
And you can use it in your view;
from . import SearchForm
form = SearchForm(request.GET)
if form.is_valid(): # this will validate your form
search_text = form.cleaned_data["search"] # now you can access input
Please check out working with forms.
Edit:
def search(request):
if request.method == 'GET':
# create a form instance and populate it with data
form = SearchForm(request.GET)
# check whether it's valid:
if form.is_valid():
print("Form is valid now you can process your data")
# return a response or render a different template
return HttpResponseRedirect('/redirect-url/')
# if not render the form back
return render(request, 'your_template.html', {"form": form})
# Assume post method is not allowed
return HttpResponseNotAllowed()
following #berkeeb answer I changed the code in this way.
I created a forms.py file with:
from django import forms
class SearchForm(forms.Form):
search = forms.CharField(required=True, max_length=255, label="search")
in my template (home.html) I used:
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div class="container text-center">
<h1>my search engine</h1>
About page
<br>
<br>
<form action="{% url 'search' %}">
<label for="search_text">Your search: </label>
<input id="search_text" type="text" name="search_text">
<input type="submit" value="Search">
</form>
</div>
and finally in the search function I wrote:
def search(request):
form = SearchForm(request.GET)
search_text = form.data["search_text"] # now you can access input
urls = searchWeb(num=5, stop=5, query_string=search_text)
threads = [threading.Thread(target=getSavePage, args=(url,)) for url in urls]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
return render(request, "engine/search.html", {"search": urls})
basically I had to remove the validation part of the form as I kept receiving status unknown.
For almost 5h I can't make detail view.
My app name -movies
My views:
"
def actor_view(request):
actor_list = Actor.objects.all()
context = {'actor_list': actor_list}
return render(request,'movies/actor.html',context)
def actor_detail_view(request,id):
actorrr=get_object_or_404(Actor,id=id)
context={
'actorrr':actorrr,
}
return render(request,"movies/actor_detail_view.html",context)
My model
class Actor(models.Model):
name = models.CharField(max_length=50)
date_of_birth = models.DateField()
age=models.IntegerField( null=True)
net_worth = models.TextField(max_length=140, null=True)
picture=models.URLField(default = '')
children =models.TextField(max_length=140, null=True)
marital_status=models.TextField(max_length=140, null=True)
My actor html:
{% load static %}
{% block mainbody %}
{% for actor in actor_list %}
<!DOCTYPE html>
<html>
<head>
<title>List of actors we have</title>
<link rel="stylesheet" href="{% static 'css/style_actor.css' %}">
</head>
<body>
<div class="card" >
<div class="card-image">
<img src="{{ actor.picture }}" alt="No poster in datebase" width="289" height="345">
</div>
<div class="card-text">
<h2>
{{ actor.name }}
</h2>
<p>{{movie.pilot}}</p>
</div>
<div class="card-imdb-score">
<p
>Age: {{ actor.age }}
</p>
</div>
</div>
</body>
</html>
{% endfor %}
{% endblock %}
My actor_detail html
<h6>TEST</h6>
movies url:
path('actor_detail_view/<int:id>',views.actor_detail_view,name='actor_detail_view'),
and the main url:
path('<int:id>/',views.actor_detail_view,name="actor_detail_view")
So I have no idea how to make urls and what to place in actor.html in href url.I've made many tutorials and still couldn't do it.
First of all, I recommends to you set the name of variable actorrr correctly.
If you're using Pycharm IDEA, the idea helps you to avoid problems with names of variables or spaces, following PEP08.
Some tips:
verify your urls.py file, to see if exists "/movies/actor_detail/{{actor.id }}
Probably, you have to add django template structure to appear the data of actor detail HTML, without for looping, because it's just one data.
your link to the actor detail page must be like this :
<a href={% url 'actor_detail_view' actor.id %}
also it's better to use django generic views to get detailed models.
I recommend you use CBVs, in this case, DetailView, I had same project and I put code here to use:
class DetailedActor(DetailView):
template_name = 'your_template'
model = models.YourModel
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
return context
then in your template, you have an instance of your model whit a specific actor! just don't forget to pass the id when you render to the URL assigned to this view
I am now studying Django form. Right now I am focusing on crispy form. For now crispy and then after I master the form I will move on to Django Admin form and Django admin model form.
Django 1.10
Python 3.6.0
I am following these tutorials:
https://blog.bixly.com/awesome-forms-django-crispy-forms
http://django-crispy-forms.readthedocs.io/en/latest/layouts.html#
https://godjango.com/29-crispy-forms/
Here are my source code:
views.py:
from django.views.generic import FormView
from apps.colors.forms import PersonDetailForm
class ColorStudyView(FormView):
template_name = 'colors/study.html'
form_class = PersonDetailForm
success_url = '/'
forms.py:
from crispy_forms.bootstrap import Tab, TabHolder
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Layout
from django import forms
class NoFormTagCrispyFormMixin(object):
#property
def helper(self):
if not hasattr(self, '_helper'):
self._helper = FormHelper()
self._helper.form_tag = False
return self._helper
class PersonDetailForm(forms.Form):
name = forms.CharField(max_length=100)
age = forms.IntegerField(required=False)
address1 = forms.CharField(max_length=50, required=False)
address2 = forms.CharField(max_length=50, required=False)
city = forms.CharField(max_length=50, required=False)
state = forms.CharField(max_length=50, required=False)
mobile = forms.CharField(max_length=32, required=False)
home = forms.CharField(max_length=32, required=False)
office = forms.CharField(max_length=32, required=False)
twitter = forms.CharField(max_length=100, required=False)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout(
TabHolder(
Tab('Information',
'name',
'age'
),
Tab('Address',
'address1',
'address2',
'city',
'state'
),
Tab('Contact',
'mobile',
'home',
'office',
'twitter',
)
)
)
self.helper.layout.append(Submit('submit', 'Submit'))
study.html:
{% load crispy_forms_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<meta charset="UTF-8">
<title>Study</title>
<form action="" method="POST">
{% crispy form %}
</form>
</head>
<body>
</body>
</html>
Problem:
Tab does not change.
Am I miss something?
Sorry for very basic level question, but this is my first day with Django frontend
Here is my picture. Tab Address and Contact are not work.
Update:
Zollie solves my problem. Here is my study.html
{% load staticfiles %}
{% load crispy_forms_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
<meta charset="UTF-8">
<title>Study</title>
<form action="" method="POST">
{% crispy form %}
</form>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.9.1.js">
</script>
<script src="http://code.jquery.com/ui/1.11.0/jquery-ui.js">
</script>
<script type="text/javascript" src="{% static 'bootstrap-tab.js' %}"> </script>
</body>
</html>
And here is my filesystem configuration
/Users/el/Code/siam-sbrand/static
(siam-sbrand) Sarits-MacBook-Air-2:static el$ ls
admin django_extensions img
bootstrap-tab.js file.txt js
dist font rest_framework
I had the same problem when first I wanted to use the Tabs in crispy forms. The documentation is quite weak unfortunately for this package.
The answer on why TabHolder and Tabs are not working is, because you have to include jquery and javascript in your html template head. Also, you have to download bootstrap-tab.js and put it in your 'static' folder in the bootstrap subfolder ie., and you also have to include the path to it in your html .
So, it is not enough if you just include Bootstrap or bootstrap.css in the html head.
Here is an example how it should look like:
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js">
</script>
<script src="http://code.jquery.com/ui/1.11.0/jquery-ui.js">
</script>
<script type="text/javascript" src="{% static 'bootstrap/js/bootstrap-tab.js' %}"> </script>
Check these things:
In settings.py you should have CRISPY_TEMPLATE_PACK = 'bootstrap3'
In your static files you should have a bootstrap-tab.js
Although the question is old and solved, I find it might be worthwhile to add some more observations: I came across the problem and found another cause.
First, I checked and confirmed that I had included the .js files as mentioned in the accepted answer. But the tab still did not work.
I found some bootstrap tab examples, such as https://mdbootstrap.com/docs/jquery/components/tabs/. And I concluded that, to make tab work, one should make sure there is a one-to-one relationship between the href attr of the 'tab header' and the id attr of the 'tab body'. Like this:
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#home" role="tab" aria-controls="home"
aria-selected="true">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile"
aria-selected="false">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" id="contact-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact"
aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">A Tab</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">B tab</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">C tab</div>
</div>
Note: pay attention to the href attrs of 'a' elements and the id attrs of 'div' elements.
I did some experimentation and concluded that: once related .js and other files are imported and href and id attrs are properly set, the tab would work.
Now the problem became "how to make crispy set them properly".
I checked following files:
1. /root/.pyenv/versions/3.7.3/lib/python3.7/site-packages/crispy_forms/bootstrap.py
class Tab(Container):
"""
Tab object. It wraps fields in a div whose default class is "tab-pane" and
takes a name as first argument. Example::
Tab('tab_name', 'form_field_1', 'form_field_2', 'form_field_3')
"""
css_class = 'tab-pane'
link_template = '%s/layout/tab-link.html'
def render_link(self, template_pack=TEMPLATE_PACK, **kwargs):
"""
Render the link for the tab-pane. It must be called after render so css_class is updated
with active if needed.
"""
link_template = self.link_template % template_pack
return render_to_string(link_template, {'link': self})
/root/.pyenv/versions/3.7.3/lib/python3.7/site-packages/crispy_forms/templates/bootstrap3/layout/tab-link.html
<li class="tab-pane{% if 'active' in link.css_class %} active{% endif %}">{{ link.name|capfirst }}{% if tab.errors %}!{% endif %}</li>
I noticed the css_id attr. And I guessed that if one set 'css_id' properly, maybe crispy would do the rest. I tried. And it worked like a charm.
Maybe crispy documentation needs some improvement.
If you- like me- search for answer why this solution doesn't work for you, check if you are using bootstrap 4. To my knowledge tabs from crispy don't work on 5 at least for now.
I want to use TinyMCE in my Django project, after doing all the necessary settings, when I visit the page, the form only render normal django form but not TinyMCE rich text form. Below are my settings.
I copied tinymce folder to media folder:
C:/Python27/Scripts/nate/media/js/tiny_mce
Settings.py
TINYMCE_JS_URL = '/media/js/tiny_mce/tiny_mce.js/'
TINYMCE_DEFAULT_CONFIG = {
'plugins': "table,spellchecker,paste,searchreplace",
'theme': "advanced",
'cleanup_on_startup': True,
'custom_undo_redo_levels': 10,
}
TINYMCE_SPELLCHECKER = True
TINYMCE_COMPRESSOR = True
urls.py
(r'^tinymce/', include('tinymce.urls')),
Models
class Finmall(models.Model):
user=models.ForeignKey(User)
name=models.CharField(max_length=250, unique=True)
content1 = models.TextField()
content2 = models.TextField()
def __unicode__(self):
return self.user
Template
<head>
<script type="text/javascript" src="{{ MEDIA_URL }}/js/tiny_mce/tiny_mce.js"></script>
</script>
</head>
{% block content %}
<div id="postcribbody" class="wrapper">
<p class="list">You can make it</p>
<form enctype="multipart/form-data" form action="." method="POST">
{% csrf_token %}
{{ FinmallForm.as_p }}
<input type="submit" class="cribput" value="Submit"/>
</form>
</div>
{% endblock %}
How can I make the content1 and content2 display TinyMCE rich text form?
An Example from the Documentation:
from django import forms
from tinymce.widgets import TinyMCE
class FinmallForm(forms.ModelForm):
...
content = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
...
class Meta:
model = Finmall
The problem is that you are displaying the form as a Django form.
The rich edit text field will be a JS thing which Django will not create. The django.form feature will be create a HTML element.
I suggest manually putting the rich edit in to the template. As long as you give the rich edit the same "name" as the Django form element you can use it in the POST which is returned.
EDIT: You are publishing a models.TextField() when the form is rendered. This will generate a element in the form. This form will have only default properties.
I am not 100% sure how TinyMCE works but you would need to bind it to that element though a "id" or "name" value or just put the forms code in yourself into the template.
I myself do not use Django to render the forms I create forms myself in the template and give them the same names what Django would give them.
Look at the source code for the rendered page and see what the form looks like. Then set up a test page with TinyMCE and get it working and look at the difference between the element.
:)
Try to put above form {{ form.media }} i.e. {{ FinmallForm.media }} in your template
<head>
<script type="text/javascript" src="{{ MEDIA_URL }}/js/tiny_mce/tiny_mce.js"></script>
</script>
</head>
{% block content %}
<div id="postcribbody" class="wrapper">
<p class="list">You can make it</p>
{{ FinmallForm.media }}
<form enctype="multipart/form-data" form action="." method="POST">
{% csrf_token %}
{{ FinmallForm.as_p }}
<input type="submit" class="cribput" value="Submit"/>
</form>
</div>
{% endblock %}