So I have a form you can fill from the webpage which I want to save to my django database to create a new object when submitted instead of adding it in admin. I've tried it and the system works except for one thing, saving it, the function starts as I've managed to switch pages from that function when clicking submit but the object isnt found in the database after so I guess the saving is the only issue.
Here is my views.py :
def uploadform(request):
if request.method == 'POST':
name = request.POST['name']
details = request.POST['details']
littype = request.POST['littype']
image = request.POST['image']
new_object = PostForm.objects.create(name=name, details=details, littype=littype, image=image)
new_object.save()
return render(request, 'uploadform.html', {})
Here is my models.py (The one to save the form is the "PostForm" class) :
from email.mime import image
from django.db import models
from django.db.models import Model
# Create your models here.
class info(models.Model):
name = models.CharField(max_length=100)
details = models.CharField(max_length=10000)
littype = models.CharField(default="Type of Litterature", blank=True, max_length=100)
image = models.ImageField(default=None, blank=True, upload_to='app/files/covers')
class PostForm(models.Model):
name = models.CharField(max_length=200)
details = models.TextField()
littype = models.TextField()
image = models.FileField(upload_to='app/files/')
def __str__(self):
return self.name
Here is my html page :
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<link type="text/css" rel="stylesheet" href="templates/uploadform.css">
<link type="text/css" rel="stylesheet" href="templates/form.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fascinate&family=Roboto:wght#400;500;700&display=swap" rel="stylesheet">
</head>
<body style="height: 1000px;">
<div class="page-title">
<h1 class="page-title-text">Book & Movie & Series Recommendations</h1>
</div>
<div class="page-title-add-button-div">
<a class="page-title-add-button-link" href="/"> Home </a>
</div>
<div>
<form method="POST" action="{% url 'uploadform' %}" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" id="name" name="name" placeholder="Title">
<input type="text" id="details" name="details" placeholder="Summary Details">
<input type="text" id="littype" name="littype" placeholder="Type of Literature">
<input type="file" id="image" name="image" placeholder="Cover Picture">
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
Any ideas? Thanks for your time and answers! Have a good day!
This is a quick answer to anyone wondering how I fixed the issue. First off, I had a few things I had to correct which Adam helped me find in the comments but the main issue was when I was creating a new object to my database instead of saving from the "info" model which looks exactly the same and is found in my database i was saving from the "PostForm" model which cannot be found in the database.
I hope this helps someone and I'll try to stay active and answer any questions if you have any.
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.
I am trying to save documents/images into my SQL database using dropzone.js ,for my web app made using Django
HTML FILE:
{% extends 'Main/logged_base_expert.html' %}
{% block content %}
{% load static %}
<head>
<script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>
<link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">
</head>
<body>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.7.5/css/bootstrap-select.min.css" media="screen">
<form action="{% url 'document_upload' %}" method = "POST" class="dropzone dz" role="form" enctype="multipart/form-data">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file" id="file" multiple >
</div>
<button type="submit" class="form-control" id="cf-submit" name="submit">Submit</button>
</form>
<!-- client section end -->
<!-- footer section start -->
{% endblock %}
views.py :
def document_upload(request):
c = main.objects.get(username = request.session['username'])
unq_id = c.unq_id
print("overall")
if request.method == 'POST':
images = request.FILES.get('file')
print("image")
fs = FileSystemStorage()
filename = fs.save(images.name, images)
Doc1 = Doc(user_id = unq_id, upload = images)
Doc1.save()
return render(request, 'Main/document_upload.html')
models.py:
class Doc(models.Model):
unq_id = models.AutoField(primary_key=True)
user_id = models.BigIntegerField()
upload = models.ImageField(upload_to= 'expert/images')
def __str__(self):
return str(self.unq_id)
The issue I keep facing is that , i keep getting the error
AttributeError at /document_upload/
'NoneType' object has no attribute 'name'
It occurs in the following line, in views.py:
filename = fs.save(images.name, images)
Additional Info : the relative path of the image seems to be storing just perfectly in the database, but since i keep getting the error , i am unable to redirect the app to another page
you're getting AttributeError because this couldn't be found in your request - request.FILES.get('file'). Print request.FILES and see what you have in there.
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.
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.