Django form to query database (models) - python

So I want to create a super basic form with a single input field which will be used to query my database.
My model (models.py) is as follows:
from django.db import models
class Book(models.Model):
uid = models.IntegerField(primary_key=True)
title = models.CharField(max_length=30)
class Meta:
db_table = u'books'
forms.py:
from django import forms
from myapp.models import Book
class EnterIDForm(forms.form):
book_id = forms.CharField()
# add a custom clean function to validate that the user input
# is a valid book ID
def clean_book_id(self):
try:
book_id = int(self.cleaned_data["book_id"])
except:
book_id = None
if book_id and Book.objects.filter(uid=book_id).count():
return book_id
else:
raise forms.ValidationError("Please enter a valid book ID number.")
views.py:
from django.shortcuts import render_to_response
from myapp.models import Book
def form_view(request):
if request.method == "POST":
# the user has submitted the form, see if we have a book
book_id_form = EnterIDForm(request.POST) # instantiate our form class with the user data
if book_id_form.is_valid():
# if our form is valid, then we have a book_id that works:
the_book = Book.objects.get(uid=book_id_form.cleaned_data["book_id"])
return render_to_response("book_template.html", { "the_book": the_book }, context_instance=RequestContext(request))
# if the form wasn't valid, it will fall through to the other return statement.
else:
# If the user didn't submit a form, instantiate a blank one.
book_id_form = EnterIDForm()
return render_to_response("form_template.html", { "book_id_form": book_id_form }, context_instance=RequestContext(request))
I want the input field to collect the "uid" from the user and display the all of the data from the Book model instance where uid is some book in the database.
I have an understanding of how the form is tied in with the view, and later templates, but I just cannot seem to get it to work.
I've endlessly searched the Django site and many other resources for an example I can learn from, but nothing.
Anyone mind helping me out?
Thanks.

You can do a simple search here. You do not need any POST calls or form creation. However, if you want to create a form this should still point you in the correct direction.
Try something like this:
search.html:
<form method="get" action="/search/">
Search Notecards:<input type="text" name="q" id="id_q" value="{{ query }}"/>
<input type="submit" value="Search" />
</form>
views.py:
from myapp.models import Book
from django.template import RequestContext
from django.shortcuts import render_to_response
def search(request):
query = request.GET.get('q')
try:
query = int(query)
except ValueError:
query = None
results = None
if query:
results = Book.objects.get(uid=query)
context = RequestContext(request)
return render_to_response('results.html', {"results": results,}, context_instance=context)
results.html:
{% if results %}
{% for result in results %}
{{ result.uid }}
{{ result.xxxx }}
{{ result.xxxx }}
{% endfor %}
{% else %}
<h3 class='error'>Please enter a valid UID</h3>
<form method="get" action="/search/">
Search Notecards:<input type="text" name="q" id="id_q" value="{{ query }}"/>
<input type="submit" value="Search" />
</form>
{% endif %}

Related

How to insert data to SQLite in Django

I am new to Django and I am following this website https://simpleisbetterthancomplex.com/tutorial/2018/02/03/how-to-use-restful-apis-with-django.html#passing-parameters-to-an-api-github-public-api
views.py
from django.shortcuts import render
import requests
def github(request):
user = {}
if 'username' in request.GET:
username = request.GET['username']
url = 'https://api.github.com/users/%s' % username
response = requests.get(url)
user = response.json()
return render(request, 'core/github.html', {'user': user})
core/github.html
{% extends 'base.html' %}
{% block content %}
<h2>GitHub API</h2>
<form method="get">
<input type="text" name="username">
<button type="submit">search on github</button>
</form>
{% if user %}
<p><strong>{{ user.name }}</strong> has <strong>{{ user.public_repos }}</strong> public repositories.</p>
{% endif %}
{% endblock %}
After passing parameters to an API and retrieve some location data, I would like to store the data to my SQLite in Django. I have created the model but I have no idea how to insert the data because I can't find examples under similar situations. And I am not sure where I should modify. Any hint or where I should look for? Many thanks.
I don't know yours models... let's asume:
models.py
from django.db import models
class Uuser(models.Model):
name = models.CharField(max_length=45,)
public_repos = models.CharField(max_length=45,)
then in your view.py
from django.shortcuts import render
import requests
from models import Uuser
def github(request):
user = {}
if 'username' in request.GET:
username = request.GET['username']
url = 'https://api.github.com/users/%s' % username
response = requests.get(url)
user = response.json()
usr = Uuser(name=user['name'], public_repos=user['public_repos']) # create new model instance
usr.save() #seve to db
return render(request, 'core/github.html', {'user': user})
I'm not checking if that exact name exist in db so there will be new record on the same name each time you post it to view.

How to loop through a form and add same form in django if we click add more button and store that in django

What I really want to do is , if a user click on "ADD more" button then a same form repeat itself and the values should store in database, if he/she doesn't click of that button then only the values from first form should be stored.
I am not able to get this, I just created a form , and a table in database for those details but can't loop though the form neither in data.
please help.
This is the form and the button:
This is the model.py code:
from django.db import models
class experience(models.Model):
company_name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
startdate = models.Datefield(default = 01-01-2020)
lastdate = models.DateField(default = 01-01-2020)
profile = models.CharField(max_length=100)
description = models.TextField(max_length = 250)
This is the views.py code:
from django.shortcuts import render, redirect
import requests
from django.contrib.auth.models import User, auth
# Create your views here.
def profile(request):
return render(request, 'profile.html')
Unfortunately, there's no built-in way (as far as I know) in Django to do that without Javascript, but here's an approach:
HTML:
<div class="container" id="experiencesContainer">
<form method='POST' name='experienceForm'>
{{form.as_p}}
</form>
<form method='POST' name='experienceForm'>
{{form.as_p}}
</form>
<button type="button" id="addMoreButton">Add more</button>
<button type="submit">Save Changes</button>
</div>
Django POST method:
# Get a list of submitted forms
experiences = request.POST.getlist('experienceForm')
for experience in experiences:
# this is how you loop throuh every form
experience.get('company_name)
Your javascript something like:
// clonning his childs as well
let cloneForm = document.querySelector('form[name=experienceForm]').cloneNode(true);
document.querySelector('div#experiencesContainer').appendChild(cloneForm);
// see this https://www.w3schools.com/jsref/met_node_clonenode.asp
Of course this code is not tested but I've done this in several projects before, hope it works!
A simple way would be to request the same view from the "Add", just make sure your form view saves the data when request method is POST.
<form action="{% url 'your-form-url' %}" method="GET">
{% csrf_token %}
<input type="submit" value="Add">
</form>
one other way to repeat forms would be using formsets. Formsets allow you to repeat the same form 'extra' times. Check out the documentation for more about this.
def repeat_form(request):
ExpFormSet = formset_factory(ExperienceForm, extra=3)
#extra defines the no. of forms you want to display
if request.method == 'POST':
formset = ExpFormSet(request.POST, request.FILES)
if formset.is_valid():
# do something with the formset.cleaned_data
#loop through each form in the formser
for form in formset.cleaned_data:
obj = form.save()
else:
formset = ExpFormSet()
return render(request, 'exp_form.html', {'formset': formset})
The corresponding template should be:-
<form method="post">
{{ formset.management_form }}
{% for form in formset %}
{{ form.as_p }}
{% endfor %}
</form>
Make sure you add form.management_form. Using the combination of the above might solve your problem of taking and saving several inputs.

MultipleChoiceField django python, impossible display datas in the template

I have big problem, I use MultipleChoic Field into django for "input multiselect",
a user at the possibility of make many choices via the "input select multiple"
I explain to you :
I use this Package : https://pypi.org/project/django-multiselectfield/
this is my model :
class Profil(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,)
skill = MultiSelectField(max_length=500, null=True, blank=True, choices=Skillz)
board = MultiSelectField(max_length=500, null=True, blank=True, choices=Boardz)
this is my form :
class ProfilForm(forms.ModelForm):
skill = forms.MultipleChoiceField(required=False, widget=forms.SelectMultiple, choices=Skillz)
board = forms.MultipleChoiceField(required=False, widget=forms.SelectMultiple, choices=Boardz)
this is my datas of the choices (used in models Profil and form ProfilForm):
Boardz = (
('Reddit', 'reddit.com'),
('Discord', 'discord.com'),
('Twitter', 'twitter.com'),
)
Skillz = (
('Python', 'PythonDjango'),
('Rust', 'RustRocket'),
('Ruby', 'RubyOnRails'),
)
Now the concern problem is views.py and my template.html
<!-- this is what I want with my datas -->
<select multiple class="form-control" id="id_board">
<option>reddit.com</option>
<option>discord.com</option>
<option>twitter.com</option>
</select>
<select multiple class="form-control" id="id_skillz">
<option>PythonDjango</option>
<option>RustRocket</option>
<option>RubyOnRails</option>
</select>
<input type="submit" value="Save">
Into the views.py (which is surely wrong) :
def GetDatasForRegisterForm(request):
form = ProfilForm()
return render_response(request, "registration/register.html",{'form': form})
template.html :
I'm totally lost for display my data choices in select multiple for the user, please guys, how make ?
Update : It's good, I have what I wanted, here is for your members of stack overflow, my solution :
class ProfilForm(forms.ModelForm):
skill = forms.MultipleChoiceField(widget=forms.SelectMultiple, choices=Skillz) # skillz and boardz into choices.py
board = forms.MultipleChoiceField(widget=forms.SelectMultiple, choices=Boardz)
class Meta:
model = Profil
fields = ('skill', 'board',)
in views.py > form = ProfilForm(), return render..
{% for value,text in form.board.field.choices %}
<option value="{{ value }}">{{ text }}</option>
{% endfor %}
This is how i go about generating my template and views.py when dealing with forms.
First here you have defined your form ProfilForm one quick way to know the html generated in your form when your views look like
def GetDatasForRegisterForm(request):
form = ProfilForm()
return render_response(request, "registration/register.html",{'form': form})
In your templates you can just do
<form method="POST" action="<your_action>">
{{ csrf_token }}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
Now when you render this django will create a basic HTML for you, based on model specified. You can copy the HTML and customize the styling and populate the values by accessing the form field values.
Now you haven't asked about how to save this form. But let me do that anyway.
We are going to handle the form post in the same controller which will look like.
def GetDatasForRegisterForm(request):
form = ProfilForm(request.POST or None)
if request.method == "POST" and form.is_valid():
form.save()
return redirect("/<sucess_page>")
return render_response(request, "registration/register.html",{'form': form})
In the view here, i am loading the form with POST data if it exists and checking if the form is valid in the POST and saving it as well. You can where to lead the page to if it is success or error.

Rendering django model validation error in template

I am building a web application on django. As part of this, I have created one html form like following:
<form method="post" action="/voting/add_state/">{% csrf_token %}
State name:<br>
<input type="text" name="state_name"><br>
<input type="submit" value="Submit">
</form>
In models.py I have added unique constraint validation on name like following:
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
So for duplicate name, it throws a unique constraint error which I would like to capture in the template. Can anyone please give any suggestion.
Create a form based on your model
#forms.py
from django import forms
from .models import State
class StateForm(forms.ModelForm):
class Meta:
model = State
fields = ('name',)
now use this form on your views
#views.py
from django.views.generic import FormView
from .forms import StateForm
class MyView(FormView):
template_name = 'template.html'
form_class = StateForm
success_url = '/my-url-to-redirect-after-submit/'
template.html
<form method="post">
{% csrf_token %}
Name
{{ form.name }}
{{ form.name.errors }}
<input type="submit" value="Create">
</form>
Django has Form processing built in. Django has "Model Forms", which automatically render the form for your model. If you pass it through the view and reference it in the context it will automatically generate the html for you, but if you would like more control over what is rendered in the template then you can reference the form attributes that Django Model Form produces.
I strongly suggest working within the framework Django provides to you for building forms; it provides a lot of boilerplate code for building, validating and abstracting forms and is especially competent for simple forms like these.
Here is an example:
models.py
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
forms.py
class StateForm(forms.ModelForm):
model = State
fields = (name,)
views.py
from django.views.generic.edit import FormView
class StateForm(FormView):
template_name = 'state_form.html'
form_class = StateForm
success_url = '/thanks/'
state_form.html (example of auto generated form)
{{ form }}
state_form.html (example of custom form)
<form action="/" method="post">
{% csrf_token %}
{{ form.errors }}
{% for field in form %}
<input type="{{ field.type }}" name='{{ field.name }}' class="submit" value="{{ field.value}}">
{% endfor %}
<input type="submit" name='submit" value="Submit">
</form>
References:
Django Forms:
https://docs.djangoproject.com/en/1.9/topics/forms/
Django Model Forms: https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/
Django Generic Views:
https://docs.djangoproject.com/en/1.9/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView
You could create a form for State model and create the validator, so if the user try with a duplicate name, the form raise a message something like this:
models.py
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
forms.py
def unique_name(value):
exist = State.objects.filter(name=value)
if exist:
raise ValidationError(u"A state with the name %s already exist" % value)
class StateForm(forms.Form):
name = forms.CharField(label=('Name:'), validators=[unique_name])
Then you just need to render the StateForm in the template.

Multiple text inputs in django form via Google App Engine

Goal: to create a question where a user creates a poll question that is "mad-libs" style (i.e. "Would you fool around with _(text)__ if she wasnt dating _(text)_?").
Code: This file creates a django form corresponding to an appengine entity.
from django import newforms as forms
import models
from google.appengine.ext.db import djangoforms
class PollForm(djangoforms.ModelForm):
class Meta:
model = models.Poll
This is an excerpt from the models.py file
from google.appengine.ext import db
from django import newforms as forms
class Poll(db.Model):
question = db.StringProperty()
created_on = db.DateTimeProperty(auto_now_add = 1)
created_by = db.UserProperty()
def __str__(self):
return '%s' %self.question
def get_absolute_url(self):
return '/poll/%s/' % self.key()
here is the html for this section
<form action="." method="post">
{{pollform.as_p}}
{% for form in choiceforms %}
{{form.as_p}}
{% endfor %}
<input type="submit" name="createpoll" value="createpoll" />
</form>
Is there a fairly straightforward way to create a question like this with some pre-coded text and some input text? Can I harcode it in the HTML?
Any direction is greatly appreciated!
I still don't totally understand your question. If you post your full source and an example of the result you are trying to get, then you will get a better response.
Here's an example of constructing a form for someone to answer the question. I hard coded the question, but you could easily retrieve that dynamically.
class Answer(models.Model):
answer1 = models.CharField(max_length=100)
answer2 = models.CharField(max_length=100)
class AnswerForm(forms.ModelForm):
class Meta:
model = Answer
def test(request):
if request.method == 'GET':
form = AnswerForm()
question_template = 'Would you fool around with %s if she wasn\'t dating %s?'
html = question_template % (form['answer1'], form['answer2'])
params = {'form': form,
'html': html}
return render_to_response('test.html',
params,
context_instance=RequestContext(request))
Template:
<form method="post" action="">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{{ html|safe }}
<input type="submit" value="Save"/>
</form>

Categories