Use two different forms in same template - python

I am trying to write a condition where if 1st part is ok then 2nd part will show.I wrote my forms.py in a following way :
class SubmissionForm(forms.Form):
first_name=forms.CharField(max_length=120, required=True)
last_name=forms.CharField(max_length=120, required=True)
class UploadForm(forms.Form):
file1 = forms.Field(label='File1', widget = forms.FileInput,required = True )
file2 = forms.Field(label='File1', widget = forms.FileInput, required = True )
In my views.py:
def submission(request):
validform=False
title="Please submit your data"
form = SubmissionForm(request.POST)
contextsumission={"title":title, "form":form}
if form.is_valid():
first_name = form.cleaned_data.get("first_name")
last_name = form.cleaned_data.get("last_name")
validform=True
if validform:
contextupload={"title":"Please upload your files","valid":True}
return render(request, 'submission.html', contextupload)
form2 = UploadForm(request.FILES)
contextsumission={"title":'Upload files', "form2":form2}
if form2.is_valid():
file1 = form2.request.FILES.get("file1")
file2 = form2.request.FILES.get("file2")
contextsumission={"title":"Thank you for your data submission"}
return render(request, 'submission.html', contextsumission)
And I have tried to write my template in a following way
{% if valid %}
<h1 class ='text-align-center', style="color: blue;"> {{ title }} </h1>
<form method ='POST' enctype="multipart/form-data" action =''> {% csrf_token %}
{{form2|crispy}}
<input class='btn btn-primary', type='submit', value='Upload'>
</form>
{% else %}
<h1 class ='text-align-center', style="color: blue;"> {{ title }} </h1>
<form method ='POST' enctype="multipart/form-data" action =''> {% csrf_token %}
{{form|crispy}}
<input class='btn btn-primary', type='submit', value='Submit'>
</form>
{% endif %}
I can see my SubmissionForm clearly in template but after pressing submit button I want to show file upload form but it is not working.
Anyone can please tell me where I need to change my code?
Thanks
Paul
Yes I have realized that and modified my code but still I have problem and def submission function is not validating two forms!! That means when ever I am trying to do form2.is_valid(), is returning false.
def submission(request):
title="Please submit your data"
form = SubmissionForm(request.POST)
contextsubmission={"title":title, "form":form}
if form.is_valid():
first_name = form.cleaned_data.get("first_name")
last_name = form.cleaned_data.get("last_name")
form2 = UploadForm(request.FILES)
contextsubmission ={"title":"Please upload your files","form2":form2,"valid":True}
if form2.is_valid():
file1 = form2.request.FILES.get("file1")
file2 = form2.request.FILES.get("file2")
contextbsumission={"title":"Thank you for your data submission"}
return render(request, 'submission.html', contextsubmission)

Related

How do I get the current item in the model from the request?

When a submit button is clicked, I want to be able to know what item the user was on. The button would be on an item's page that the user gets taken to when they click on an item. This button is is part of a django form (PlaceBid) that allows the user to bid for the item. So I want to be able to update what the item's highest bid is if the bid is higher than the current highest. This means that I need to know what item the user was viewing.
I also want to save the bid in a model called Bid and in that model I also need to know what listing the bid is for.
So how do I get the correct item from the model?
The models:
Listing() is the model for the item
Bid() is the model for the bid
views.py:
def bid(request):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
current = Listing.objects.get(pk=request.id) # my attempt to get the current item
highest = current.highest_bid
if form.cleaned_data['bid'] < highest:
obj = Bid()
obj.price = form.cleaned_data['bid']
obj.item = current
obj.user = User.objects.get(pk=request.user.id)
obj.save()
current.highest_bid = form.cleaned_data['bid']
current.save()
return HttpResponseRedirect(request.path_info)
forms.py:
class PlaceBid(forms.Form):
bid = forms.FloatField(required=False, widget=forms.NumberInput(attrs={
'class': 'bid',
}))
html:
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
With the limited code shown, I can only assume at this point that you have a bidding form for each item in a forloop. Example:
{% for item in items %}
...
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
...
{% endfor %}
But here are two methods that can be done...
Use a hidden input field to hold the item object id then retrieve that field name on the server to get the item's id value.
# html
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="hidden" value="{{ item.id }}" name="item_id">
<input type="submit" value="Place Bid" class="place-bid">
</form>
# views.py
def bid(request):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
item_id = request.POST.get('item_id', None)
current = Listing.objects.get(id=item_id)
# rest of code follows...
Pass the item's id via the url. (My recommendation)
# html
<form action=" {% url 'bid' item.id %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
# urls.py
# update the necessary url to accept an id
path('bid/<int:id>/', views.bid, name='bid')
# views.py
def bid(request, id):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
current = Listing.objects.get(id=id) # id passed to this method used here...
# rest of code follows...
Also, instead of using Listing.objects.get(id=id), I'd suggest using get_object_or_404(Listing, id=id) as this will handle any potential error that Listing.objects.get(id=id) will throw.
You won't get it from the request. Hide it in the form.
class PlaceBid(forms.Form):
bid = forms.FloatField(required=False, widget=forms.NumberInput(attrs={
'class': 'bid',
}))
listing_id = forms.IntegerField(widget=forms.HiddenInput())
Then in your method that displays the form (I'm using function-based views)
def view_listing(request, listing_id)
listing = Listing.objects.get(id=listing_id)
myForm = PlaceBid(initial={"listing_id" : listing_id})
return render("whatever.html", {"listing" : listing, "form" : form })
I suppose another option would be to stash the listing_id in the session, but I try to avoid that.

How to subtract from a Django model?

I am trying to add and subtract 1 from the value of a Django model's IntegerField and display it on the webpage, depending on when a button is clicked.
models.py
class User(AbstractUser):
following = models.ManyToManyField("self", related_name="followers", symmetrical=False)
following_num = models.IntegerField(default=0)
In views.py:
To add: following_num = page_visitor.following_num +1
To subtract: following_num = page_visitor.following_num -1
This is displaying in the html where the number should be displaying:
<django.db.models.query_utils.DeferredAttribute object at 0x0000022868D735E0>
entire view:
def username(request, user):
#get user
user = get_object_or_404(User.objects, username=user)
posts = Post.objects.filter(user=user).order_by('-date_and_time')
page_visitor = get_object_or_404(User.objects, username=request.user)
if user == request.user:
followButton = False
else:
followButton = True
if request.method == "POST":
if "follow" in request.POST:
request.user.following.add(user)
following_num = page_visitor.following_num +1
#following_num = F('User.following_num') + 1
elif "unfollow" in request.POST:
request.user.following.remove(user)
following_num = page_visitor.following_num -1
#following_num = F('User.following_num') - 1
followers_num = page_visitor.following_num
following_num = User.following_num
return render(request, "network/username.html",{
"user": user,
"posts": posts,
"followButton": followButton,
"followers": followers_num,
"following": following_num
})
html
{% block body %}
<h1>{{ user }}</h1>
<h4>Followers:{{ followers }}</h4>
<h4>Following:{{ following }}</h4>
<!--follow/unfollow button-->
{% if followButton == True %}
<form action = "{% url 'username' user %}" method = "POST">
{% csrf_token %}
{% if user not in request.user.following.all %}
<input type="submit" value="Follow" name="follow">
{% else %}
<input type="submit" value="Unfollow" name="unfollow">
{% endif %}
</form>
{% endif %}
<!--displays all the posts-->
{% for post in posts %}
<div class = "individual_posts">
<h5 class = "post_user">{{ post.user }}</h5>
<h6 id = "post_itself">{{ post.post }}</h6>
<h6 class = "post_elements">{{ post.date_and_time }}</h6>
<h6 class = "post_elements">{{ post.likes }} Likes</h6>
</div>
{% endfor %}
{% endblock %}
you reference the class (model) and not the object (instance)
following_num = User.following_num
as you alredy passed your user object to the template you can also access the attributes directly
{{user.following_num }} {{request.user.following_num }}
but you better rename the passed user variable to avoid confusion / errors
Get user information in django templates
Without the html that is supposed to display the number I cant tell why it is displaying that, but if you intend to change the following count then you need to call page_visitor.save() after changing a property of page_visitor in order for it to save the new property's value in the database

Django TypeError using TextField bounding the form

I want to create a simple wiki page, which is comprised of several entries.
But have an error TypeError at /addentry
__init__() got an unexpected keyword argument 'title'
The main thing here is entry model.
Here is part of my models.py:
class wikies(models.Model):
num = models.CharField(max_length=15)
title = models.CharField(max_length=150)
text = models.TextField()
And here is part of my forms.py:
class entryform(ModelForm):
class Meta:
model = wikies
fields = ['num', 'title', 'text']
Part of my template:
<form action="{% url 'addentry' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p> {{entryform.num}} </p>
<p> {{entryform.title}} </p>
<p> {{entryform.text}}</p>
<p><input type="submit" value="Add Entry" /></p>
This is part of my views.py, where I catch the error:
def addentry(request):
if request.method =='POST':
form = entryform(num = request.POST['num'],
title = request.POST['title'],
text = request.POST['text']
)
I want to bound the form with values I just get, but have the following error:
TypeError at /addentry
init() got an unexpected keyword argument 'title'
Here are POST values:
num
'1.2.3'
text
'Water is very important resource.'
title
'Importance of water'
I've read the docs, I've searched through StackOverflow, but I have no idea what to do. Will appreciate any help.
#views.py
def addentry(request):
if request.method =='POST':
form = entryform(request.POST)
if form.is_valid():
form.save(commit=Fale)
num = form.cleaned_data['num'],
title = form.cleaned_data['title'],
text = form.cleaned_data['text']
form.save(commit=True)
return redirect('/')
else:
form=entryform()
return render(request,....,{'form':form})
#template
<form action="{% url 'addentry' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="submit">
</form>

Django - Form is not saving the modifications

I'm creating a page where my users can edit their articles but there is one problem, my form is not saving the modifications when I submit my form. Let's have a look:
views.py
def edit(request, id=None, template_name='article_edit.html'):
if id:
article = get_object_or_404(Article, id=id)
if article.user != request.user:
return HttpResponseForbidden()
else:
article = Article(user=request.user)
if request.POST:
form = ArticleForm(request.POST, instance=article)
if form.is_valid():
save_it = form.save()
save_it.save()
form.save_m2m()
return HttpResponseRedirect("/")
else:
form = ArticleForm(instance=article)
context = {'form': form}
populateContext(request, context)
return render(request, template_name, context)
line 3 to 8 : Is to check if it's your own articles there is no problem with that.
line 10 to 18 : There is a problem between these lines, my form is not saving when I submit my form
forms.py (ModelForm)
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
exclude = ['date', 'rating', 'user']
form = ArticleForm()
(Line 4 : I'm excluding the date, the ratings and the username when saved so that the user can not change these informations.)
I don't have any problem in my template.html and the urls.py don't bother with that I checked over 10 times :)
Any help would be great, I'm blocked on this problem since over 1 month...
******* EDIT *******
Models.py
class Article(models.Model):
user = models.ForeignKey(User)
titre = models.CharField(max_length=100, unique=True)
summary = RichTextField(null=True, max_length=140)
contenu = RichTextField(null=True)
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date de parution")
image = models.ImageField(upload_to='article', default='article/amazarashi.jpeg')
rating = RatingField(can_change_vote=True)
tags = TaggableManager(through=TaggedItem, blank=True)
def __str__(self):
return self.titre
Template.html
{% block body %}
{% if user.is_authenticated %}
<p>Authentificated as <strong>{{ user.username }}</strong></p>
{% else %}
<p>NOT Authentificated</p>
{% endif %}
<h1>Edit this {{ article.titre }}</h1>
<br>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8">
<form enctype='multipart/form-data' action="{% url "article.views.index" %}" method="post" class="form" autocomplete="off" autocorrect="off">
{% csrf_token %}
<div class="form-group">TITRE
{{ form.titre.errors }}
{{ form.titre }}
</div>
<div class="form-group">SUMMARY
{{ form.media }}
{{ form.summary.errors }}
{{ form.summary }}
</div>
<div class="form-group">CONTENU
{{ form.media }}
{{ form.contenu.errors }}
{{ form.contenu }}
</div>
<div class="form-group">
{{ form.image.errors }}
{{ form.image }}
</div>
<div class="form-group">TAGS
{{ form.tags.errors }}
{{ form.tags }}
</div>
<input type="submit" class="btn btn-default" value="Submit"/>
</div>
</form>
{% endblock %}
According to your error message.. Modify your form in templates:
<form enctype='multipart/form-data' ...>
Add request.FILES to your Form creation:
if request.POST:
form = ArticleForm(request.POST, request.FILES, instance=article)
UPDATE:
You have strange url tag parameter. Are you sure you have defined your url like: ('...', your_view, name='article.views.index')? I am in doubt cause url tag takes url name as parameter but not view path and nobody usually uses url names like this.

Showing a empty GET form without raising any error on Django

I'm trying to set an home page one my project that show a search form (with GET method).
The problem is that it raises an error at the moment I load the very page since the default request method is GET. Of course I can change the form's method to POST but that would not be the correct way, so I was wondering if there was any condition that I can set to avoid this issue and still be able to check any errors.
I'm working on Django 1.5 and Python 2.7
This if the form class:
class Search(forms.Form):
middleschool = 'MS'
highschool = 'HS'
university = 'U'
blank = '-'
school_choices = ((middleschool, 'Middle School'),
(highschool, 'High school'),
(university, 'University'),
(blank, 'Not defined'),)
title = forms.CharField(label='Keyworld')
subject = forms.ModelChoiceField(queryset=Subject.objects.order_by('?'),
required=False, label='Whitch subject you want to search?')
school = forms.ChoiceField(choices = school_choices, required=False,
label='What level of material are you searching?')
price = forms.BooleanField(required=False)
This is the relative view:
def home(request):
if request.method == 'GET':
form = Search(request.GET)
if form.is_valid():
cd = form.cleaned_data
ftitle = cd['title']
fsubject = cd['subject']
fschool = cd['school']
fprice = cd['price']
if fprice:
forms = File.objects.filter(name__contains='ftitle', subject='fsubject', school='fschool', price = '0,0')
return render(request, 'search.html', {'form': form})
else:
forms = File.objects.filter(name__contains='ftitle', subject='fsubject', school='fschool')
return render(request, 'search.html', {'form': form})
else:
form = Search()
return render(request, 'home.html', {'form': form})
This is the HTML:
{% block content %}
<hr>
<div id='search'>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="/search/" method="get">
<div class="field">{{ form.title.errors }}<label for="keyworld">Keyworld:</label>{{ form.title }}</div>
<div class="field"><label for="subject">Subject:</label>{{ form.subject }}</div>
<div class="field"><label for="school">Level:</label>{{ form.school }}</div>
<div class="field"><label for="price">Price yes or no:</label>{{ form.price }}</div>
<input type="submit" value="Search">
<input type="reset" value="Reset">
</form>
</div>
<hr>
{% endblock %}
You simply have to add or None, like this:
form = SearchForm(request.GET or None)
Rather than checking the request method, you could check whether request.GET is empty:
if request.GET:
form = SearchForm(request.GET)

Categories

Resources