I'm using using Django forms to collect information from users. But when I change between pages I want to use one of the value from url to be displayed in a from in the next page.
Example.
I have url for checking out a book like
http://127.0.0.1:8000/checkout/780374157067
780374157067 is the ibn of the book
Next page has a form where I get the ISBN and card id of the user. How to fill the form with the ISBN and show the form to user. rather than the user giving the ISBN again.
ISBN Filed should be pre filled with thw isbn in URL.
HTML :
<div class ="col-md-3">
<form method='POST' action=''>{%csrf_token%}
{{template_form | crispy}}
<input class="btn btn-lg btn-primary" type='submit'
value='Submit'/>
</form>
</div>
Forms.py
class loansform(forms.Form):
Isbn = forms.IntegerField()
Card_id = forms.IntegerField()
def clean_Isbn(self):
isbn = self.cleaned_data.get("Isbn")
isbn_string = str(isbn)
if len(isbn_string) != 13:
raise forms.ValidationError("Enter a valid ISBN-13")
return isbn
views.py
template_form = loansform();
in your view you can put intial data in form first get paramter from url then :
data = {'isbn': 154646486,}
form = Myform(initial=data)
in urls.py:
url(r'^checkout/(?P<isbn>\d+)/$',check_page)
view example :
def check_page(request, isbn):
data = {'isbn': isbn,}
form = Myform(initial=data)
template = 'mytem.html'
context = {'form': form,}
return render(request, template, context)
Say you've got url like
url(r'^checkout/(?P<isbn>\d+)/$')
In your view, when you instantiate form class, provide initial data to it like this.
form = YourFormClass(initial={'isbn': kwargs['isbn']})
kwargs contain url parameters, so you can get isbn from url.
Related
I'm building a simple web app where users can log new entries that have a name (CharField) and a date.
By default, the date is set to the current date:
class EntryForm(forms.Form):
entry_name = forms.CharField(label='New Entry', max_length=100)
entry_date = forms.DateField(initial=datetime.date.today, widget=forms.widgets.DateInput(attrs={'type': 'date'}))
If users select a different date and add an entry with that date, I want the selected date to persist as new initial value when the page reloads.
I know there are a lot of related questions on setting initial values dynamically, but unfortunately, I still could achieve setting an initial value dynamically.
My view with the form looks like this:
#login_required
def index(request):
if request.method == 'POST':
form = EntryForm(request.POST)
if form.is_valid():
# get the label name and strip and convert to lower before saving it
entry_name = form.cleaned_data['entry_name'].strip().lower()
entry_date = form.cleaned_data['entry_date']
entry = Entry.objects.create(name=entry_name, date=entry_date, owner=request.user)
return HttpResponseRedirect(reverse('app:index'))
else:
form = EntryForm()
# other, unrelated stuff stuff ...
context = {
'form': form,
}
return render(request, 'app/index.html', context)
Even setting the initial value of a form field to a fixed value inside the view's else branch didn't work. I tried EntryForm(initial={'entry_name': 'test'}) (also for entry_date) without success. Also form.fields['entry_name'].initial = 'test', which didn't work either. In both cases, the from's entry_name remained empty when reloading the page.
What's the problem? How can I set the initial value in the form (neither for name nor for date)?
Is it somehow because the form is still unbounded?
If setting the initial value in the view worked, I think I could simply set it when the date is entered and it should stay when the page is reloaded since I pass the form (with the adjusted initial value) in the context dict when rerendering the page.
Edit: This is how I render my form in the template:
<div class="input-group">
<input type="text" class="form-control" id="{{ form.entry_name.id_for_label }}" name="{{ form.entry_name.html_name }}" aria-label="new entry field">
{{ form.entry_date }}
<div class="input-group-append">
<button type="submit" class="btn btn-primary">Add</button>
</div>
</div>
Oh, I think I didn't test correctly. In fact, setting
form = EntryForm(initial={'entry_date': '2020-12-12'})
inside my view does work fine and the date gets initialized as configured.
I guess, I just tried passing a datetime.date before or tested with initializing entry_name, but that didn't work because of how I render entry_name in the template.
To persist the previously entered date, I added an optional argument init_date to my index view, which is set according to the previously entered date:
def index(request, init_date=datetime.date.today()):
if request.method == 'POST':
form = EntryForm(request.POST)
if form.is_valid():
entry_name = form.cleaned_data['entry_name'].strip().lower()
entry_date = form.cleaned_data['entry_date']
entry = Entry.objects.create(name=entry_name, date=entry_date, owner=request.user)
return HttpResponseRedirect(reverse('app:index_with_date', args=[entry_date]))
else:
form = EntryForm(initial={'entry_date': init_date})
For that, I added another URL pattern:
path('add/<entry_name>/<yyyymmdd:entry_date>/', views.add_entry, name='add_entry_with_date'),
With the following date converter:
class DateConverter:
regex = '\d{4}-\d{2}-\d{2}'
def to_python(self, value):
return datetime.datetime.strptime(value, '%Y-%m-%d')
def to_url(self, value):
return value
register_converter(DateConverter, 'yyyymmdd')
I have a Django form NameForm. I am attempting to iterate over an array of values and, for each value, have an option to display the same form. The only thing that should change with the form submission should be the associated value to which the form is displayed next to.
This becomes much clearer with an example. For some array [1,2,3] we should display:
We can then click on any open form icon, fill out the NameForm form. The resultant information, including the form_id (in this case 1, 2, or 3) should be returned to forms.py. How can I fetch the form_id variable from an instance of NameForm in index.py?
My (hacky) attempt can be found below. The problem is I don't know how to access the form_id variable I created in the NameForm object.
forms.py
class NameForm(forms.Form):
form_id = None
your_name = forms.CharField(label='Your name', max_length=3)
views.py
def index(request):
if request.method == 'POST':
form = NameForm(request.POST)
form_id = form.form_id # The problem line, as form_id is always None
if form.is_valid():
return HttpResponse( \
' '.join((str(form.cleaned_data['your_name']),form_id ))\
) #Throws TypeError as can't join None and string
else:
forms = []
vals = [1,2,3]
for val in vals:
form = NameForm()
form.form_id = val
forms.append(form)
return render(request, 'post/index.html', {'forms': forms})
index.html
{%for form in forms%}
{{form.form_id}}
<button class="button" onclick="openForm()">Open Form</button>
<div class="myForm">
<form class="form-container" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
<button class="button" onclick="closeForm()">Cancel</button>
</form>
</div>
</br>
{%endfor%}
In Django Form or Django Model, when you set a field's value to None, it is assumed that you want to ignore said field. This is helpful when creating a model that inherits from another model and you want to remove some unnecessary fields.
If you want to set value for a field on Form creation, you should pass it into __init__ method. E.g:
class NameForm(forms.Form):
form_id = forms.IntegerField(widget=forms.HiddenInput())
your_name = forms.CharField(label='Your name', max_length=3)
def __init__(self, form_id, *args, **kwargs):
self.fields['form_id'].initial = form_id
Alternatively, instead of overriding the __init__ method, you can set an initial value for form_id when you create an instance of NameForm. For example:
vals = [1,2,3]
forms = [NameForm(initial={'form_id': val}) for val in vals]
I'm new in python/django and i have a problem, i'm trying to use checkbox filtering in my html table and i don't really know how to do it.
This is what i have now
I want to add these
models.py
class Tags(models.Model):
tag_frequency = models.CharField(max_length=250)
views.py
#login_required(login_url='/login/')
def index(request):
title = 'Tags'
all_tags = Tags.objects.all()
return render(request, 'tag/index.html' ,{'all_tags':all_tags, 'title':title})
How do i use filter with these, i tried something like this but doesn't work:
LF = 125 - 134.2 KHz
HF = 13.56 MHz
UHF = 860 - 960 MHz
LF = Tags.objects.filter(tag_frequency__gt=125, tag_frequency__lt=134.2)
In order to make your query works, you have to change your field to FloatField:
class Tags(models.Model):
tag_frequency = models.FloatField(default=0.00, null=True, blank=True)
Set null, blank and default values based on your needs.
Then, put your checkboxes (or radio inputs) in your html form like this:
<form action="" method="post">
<!-- other form fields and csrf_token here -->
<div><label for="input_lf"><input type="checkbox" name="is_lf" id="input_lf"> LF</label></div>
<div><label for="input_hf"><input type="checkbox" name="is_hf" id="input_hf"> HF</label></div>
<div><label for="input_uhf"><input type="checkbox" name="is_uhf" id="input_uhf"> UHF</label></div>
<input type="submit" value="Submit"/>
</form>
Then in your view, you can try something like this:
def form_view(request):
if request.method == 'POST':
# these strings come from HTML Elements' name attributes
is_lf = request.POST.get('is_lf', None)
is_hf = request.POST.get('is_hf', None)
is_uhf = request.POST.get('is_uhf', None)
# Now make your queries according to the request data
if is_lf:
LF = Tags.objects.filter(tag_frequency__gt=125, tag_frequency__lt=134.2)
if is_hf:
# another query here
# and rest of your view
I'm creating a project with django and am having trouble with some of the basics, my aim is to have a homepage with a search box. When a search term is entered, the server gathers data from various api's, saves the data to the database then directs the user to a results page which displays this data.
So far I have managed to create a page that takes the search term and saves the data to the database. However if I try to then redirect to a new page it breaks, specifically the data doesn't save to the database. I'm having real trouble finding information on what to do next.
I have a model:
class film(models.Model):
filmName = models.CharField(primary_key=True, max_length=120)
quotient = models.FloatField()
rating = models.FloatField()
gross = models.IntegerField()
star = models.CharField(max_length=120)
releaseDate = models.DateField()
def __unicode__(self):
return self.filmName
With a form:
class searchFilm(forms.ModelForm):
class Meta:
model = film
fields = ['filmName']
A two view methods:
def home(request):
title = "Culturnomicon"
form = searchFilm(request.POST or None)
if form.is_valid():
searchedFilm = form.save(commit = False)
fixedName = searchedFilm.filmName.replace(' ', '+')
url = 'http://api.themoviedb.org/3/search/movie?api_key=APIKEY&query='+fixedName
urlRequest = Request(url)
try:
reponse = urlopen(urlRequest)
filmData = reponse.read()
parsed_json = json.loads(filmData)
except URLError, e:
print "didnt work"
firstResult = parsed_json['results'][0]
filmId = str(firstResult['id'])
filmData = getFilmData(filmId)
if parsed_json['total_results'] != 0:
searchedFilm = saveFilm(searchedFilm, filmData)
searchedFilm.save()
context = {
"template_title": title,
"form": form,
}
return render(request, "home.html", context)
def results(request):
return render(request, "results.html", {})
and a template:
<form method="POST" action="{% url 'results' %}">
{{form}}
{% csrf_token %}
<input type="submit" value ="Search" class = 'btn'/>
</form>
Any advice on what to do next would be greatly appreciated.
I also have the feeling that having methods to gather the API information may be a bad idea, is it bad to do this and if so how can I fix it?
If all you really want to do is load a different template then you don't need to have a separate view, you just move the return render(..."results.html" inside of the if form.is_valid() statement after you've done all you need with the database.
You may need to extend the render call to include some context data about what results that template should actually display however.
If you do want a separate view, then you need to move the handling of the form to the other view.
def home(request):
title = "Culturnomicon"
form = searchFilm(request.POST or None)
if form.is_valid():
# Your logic
return render(request, "results.html", {})
context = {
"template_title": title,
"form": form,
}
return render(request, "home.html", context)
I have a form with radio buttons and text fields. When I submit the form, the boolean field does not get created in the record. The boolean field is supposed to be updated via the radio buttons. What could be the issue here?
Here is the relevant part of my forms.py file:
CHOICES = (
(1,'yes'),
(0,'no')
)
class ServiceForm(forms.ModelForm):
one_time_service = forms.ChoiceField(required = True, choices = CHOICES, widget=forms.RadioSelect())
class Meta:
model = Service
fields = ('one_time_service')
This is my models.py one_time_service field
one_time_service = models.BooleanField(default=False)
This is my views.py:
def create(request):
if request.POST:
form= ServiceForm(request.POST)
if form.is_valid():
service_obj = form.save(commit=False)
service_obj.user_id = request.user.id
service_obj.save()
return render_to_response('services/service_created.html',
{'service': Service.objects.get(id=service_obj.id)})
else:
form = ServiceForm()
args= {}
args.update(csrf(request))
args['form'] = form
return render_to_response('services/create_service.html', args )
Edit: Here is my create_service.html
<form action="/services/create" method="post" enctype="multipart/form-data">{% csrf_token %}
<ul>
{{form.as_p}}
</ul>
<input type="submit" name="submit" value="Create Service">
</form>
I have no idea if this is the problem, but the line:
fields = ('one_time_service')
is wrong. That's not a single element tuple, that's a string with parens around it. Add a comma to make it a tuple:
fields = ('one_time_service',)
Edit: also, form.save() does not update any database records -- it creates a new one! That may be your problem.