Been having an issue where I am unable to upload files into my form. From what I can gather on my own, it's because I'm not submitting in POST (since uploaded files aren't saved unless you're in POST) but I don't know why that's the case. Here's my code:
Views.py
def commission(request):
if request.method == "POST":
form = CommissionForm(request.POST)
if form.is_valid():
subject = str(form.cleaned_data.get("name")) + "'s commission request"
message = form.cleaned_data.get("name") + ",\nhas requested a commission, with the following request:\n" + form.cleaned_data.get("request") + "\n Reply to them using their email:\n" + form.cleaned_data['email']
email = form.cleaned_data['email']
print(form.cleaned_data)
attach = request.FILES['reference']
try:
mail = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [email])
if attach != None:
mail.attach(attach.name, attach.read(), attach.content_type)
mail.send()
return redirect("main-commissions-success")
except:
return render(request, "main/commissions.html", {"form": form})
return render(request, "main/commissions.html", {"form": form})
else:
form = CommissionForm()
return render(request, "main/commissions.html", {"form": form})
Commissions.html
<div class="row">
<div class="content-section card w-50 mx-auto my-5">
<div class="card-body">
<form method="POST" action="" class="border border-light m-10" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4 text-center">Request A Painting</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group text-center">
<button class="btn btn-outline-info" type="submit">Send Request</button>
</div>
</form>
</div>
</div>
</div>
And since this has no model relation, I'm not going to bother adding it here. Hopefully someone can help point out whatever dumb mistake I've made lol.
I figured out what went wrong so, for anyone else with a similar issue, I had forgotten to request the files from the post request. So this:
if request.method == "POST":
form = CommissionForm(request.POST)
is meant to be this:
if request.method == "POST":
form = CommissionForm(request.POST, request,FILES)
in order to access your files.
Related
im getting this error as_crispy_field got passed an invalid or inexistent field
every time im trying to use as_crispy_field with forms
here is my code
models.py
class Customer_Email(models.Model):
subject=models.CharField(max_length=50,null=True,blank=True)
message=models.TextField(max_length=1000,null=True,blank=True)
file_upload=models.FileField(null=True,blank=True)
sender=models.ForeignKey(User,on_delete=models.CASCADE ,null=True,blank=True)
company=models.ForeignKey(Customer,on_delete=models.CASCADE ,null=True,blank=True)
date=models.DateTimeField(auto_now=True)
views.py
def send_email(request,id):
customer=get_object_or_404(Customer,pk=id)
form=Customer_Email_Form(request.POST)
customers=Customer.objects.all()
context={"customer":customer,"email_form":form,"customers":customers}
if request.method == 'GET':
return render(request,'crm/email_form.html',context)
if request.method=='POST':
if form.is_valid():
form.save()
messages.success(request,"Email Sent")
return render(request,'crm/listing.html',context)
return render(request,'crm/email_form.html',context)
html
{% load crispy_forms_tags %}
<form class="" method="POST">
{% csrf_token %}
<div class="form-group m-2">
<label>Subject</label>
{{email_form.subject|as_crispy_field}}
</div>
<div class="form-group m-2">
<label>Message</label>
{{email_form.message|as_crispy_field}}
</div>
<div class="form-group m-2">
<label>Uplaod</label>
{{email_form.file_upload|as_crispy_field}}
<span class="color-secondary">you can attach 2M files (pdf,doc)</span>
</div>
{{email_form.company|as_crispy_field}}
{{email_form.sender|as_crispy_field}}
<button
class="btn btn-primary btn-lg mt-5"
type="submit"
hx-post="email_form/p={{customer.id}}"
hx-target="#crm-list"
data-dismiss="modal"
>Send Email <i class='bx bx-mail-send bx-xl'></i></button>
</form>
forms.py
class Customer_Email_Form(forms.ModelForm):
class Meta:
model=Customer_Email
fields=['subject','file_upload','message','sender','company']
i have tried to change it to forms.Form but it gives me the same error i dont know what excactly i should do and im new to it
Try this...
def send_email(request,id):
customer=get_object_or_404(Customer,pk=id)
form=Customer_Email_Form()
customers=Customer.objects.all()
context={"customer":customer,"email_form":form,"customers":customers}
if request.method == 'GET':
return render(request,'crm/listing.htm.html',context)
if request.method=='POST':
form=Customer_Email_Form(request.POST)
if form.is_valid():
form.save()
messages.success(request,"Email Sent")
return render(request,'crm/listing.html',context)
return render(request,'crm/listing.html',context)
You were passing POST data to your form before any was sent, and then rendering the form. I find it easier/clearer to restructure as such:
def send_email(request,id):
if request.method=='POST':
form=Customer_Email_Form(request.POST)
if form.is_valid():
form.save()
messages.success(request,"Email Sent")
return redirect('send_email', id)
else:
messages.error(request, form.errors)
return redirect('send_email', id)
else:
customer=get_object_or_404(Customer,pk=id)
form=Customer_Email_Form()
customers=Customer.objects.all()
context={"customer":customer,"email_form":form,"customers":customers}
return render(request,'crm/listing.html',context)
Assuming that you have imported redirect and your url name in urls.py is 'send_email'.
I was creating a post based website i want to show the author's name to show up in the post it works in the admin site when adding posts but when i try uploading a post from the site the form is not getting validated therefore it is not getting saved please help
model :
from django.conf import settings
class MemeImg(models.Model):
Title = models.CharField(max_length=500)
op = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=None, blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
Post_Img = CloudinaryField('Post')
forms :
class PostImg(forms.ModelForm):
class Meta:
model = MemeImg
fields = ['Title', 'op', 'Post_Img']
view :
#login_required(login_url='/login')
def post(request):
func = data(request)
if request.method == 'POST':
form = PostImg(request.POST, request.FILES, instance=request.user)
form.op = request.user
if form.is_valid():
print('success')
posts = form.save(commit=False)
posts.op = request.user
form.save()
return HttpResponseRedirect('https://youtu.be/dQw4w9WgXcQ')
else:
print("fail")
form = PostImg(request)
ctx = {
'form': form,
'url': func[0],
'name': func[1],
'date': func[2],
}
return render(request, 'Post.html', ctx)
and finally the post page template :
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="container">
{{ form.Title|materializecss }}
<div class="file-field input-field">
<div class="btn">
<span>File</span>
<input type="file">
</div>
<div class="file-path-wrapper">
{{ form.Post_Img }}
<input class="file-path validate" type="text">
</div>
</div>
<button class="btn waves-effect waves-light" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
</div>
</form>
If anymore code is required please comment it
Thanks a lot
I think your problem come from the form instance which is instance=request.user, actually the instance is supposed to be the MemeImg object instance and not the user, that's making it not to save the image. So i have deleted the instance and also i don't know what you are using those extra context variable for 'url': func[0],'name': func[1], 'date': func[2] ?, so i deleted them too keep things simple. Now i think you should be able to save without any Issues.
#login_required(login_url='/login')
def post(request):
if request.method == 'POST':
form = PostImg(request.POST, request.FILES)
if form.is_valid():
print('success')
data = form.save(commit=False)
data.op = request.user
form.save()
return HttpResponseRedirect('https://youtu.be/dQw4w9WgXcQ')
else:
print("fail")
form = PostImg(request.POST)
ctx = {
'form': form,
}
return render(request, 'Post.html', ctx)
Also your form had in it {{ form.Post_Img }} which i don't no what you are looking to accomplish with that variables?, the right way is doing {{ form.as_p }} or simply just calling the form like this {{ form }} so i have made the correction in you HTML
too.
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="container">
{{ form.Title|materializecss }}
<div class="file-field input-field">
<div class="btn">
<span>File</span>
<input type="file">
</div>
<div class="file-path-wrapper">
{{ form }}
<input class="file-path validate" type="text">
</div>
</div>
<button class="btn waves-effect waves-light" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
</div>
</form>
I'm coding a news website,I want the user can submit the comment of the news only after they have logged in,if not,the website will return to login.html.
Now I have made it that only the user who have logged in can submit a comment,the issue is once I log off and submit a comment the error says:
Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x10fed10b8>>": "NewsComments.user" must be a "UserProfile" instance.
Note:I have rewrote the User models and rename it UserProfile .It works very well.
Here is my news/views.py:
def newsDetailView(request, news_pk):
news = News.objects.get(id=news_pk)
title = news.title
author = news.author_name
add_time = news.add_time
content = news.content
category = news.category
tags = news.tag.annotate(news_count=Count('news'))
all_comments = NewsComments.objects.filter(news=news)
comment_form = CommentForm(request.POST or None)
if request.method == 'POST' and comment_form.is_valid():
comments = comment_form.cleaned_data.get("comment")
comment = NewsComments(user=request.user, comments=comments, news=news)
comment.save()
return render(request, "news_detail.html", {
'title': title,
'author': author,
'add_time': add_time,
'content': content,
'tags': tags,
'category': category,
'all_comments': all_comments,
'comment_form': comment_form
})
Here is my news.detail.html
<form method="POST" action="">{% csrf_token %}
<div class="form-group">
<label for="exampleFormControlTextarea1"><h5>评论 <i class="fa fa-comments"></i></h5></label>
<textarea id="js-pl-textarea" class="form-control" rows="4"
placeholder="我就想说..." name="comment"></textarea>
<div class="text-center mt-3">
<input type="submit" id='js-pl-submit' class="btn btn-danger comment-submit-button" value='Submit'>
</input>
</div>
</div>
</form>
Here is my urls.py:
path('-<int:news_pk>', newsDetailView, name="news_detail"),
You could use djangos login-required-decorator.
#login_required
def newsDetailView(request, news_pk):
...
EDIT to expand the idea from my comments.
You could have two views, one with the login_required decorator. (You could also use class-based-views (CBV) if you prefer)
def view_news_details(request, news_pk):
...
#login_required
def post_comments(request, news_pk):
...
Each view would have their own url:
url(r'^(?P<news_pk>[0-9]+)/$', views.view_news_details, name='view-details'),
url(r'^(?P<news_pk>[0-9]+)/comment/$', views.post_comments, name='comment'),
Then you can have only one template but with conditional rendering. This template will be rendered by the view views.view_news_details, but the form will send its data to the other view (note the forms action attribute).
... display the news details here ...
{% if request.user.is_authenticated %}
<form method="POST" action="{% url 'comment' news_instance.pk %}">
... here goes the content of the form ...
</form>
{% endif %}
Redirect the user to your login view before let him submit any data in your views.py :
# Codes here
if request.method == 'POST': # We separe those two "if statements", because
# We want to redirect the user to login even if the form is not valid, User can bypass your security concern
# For Django < 2.0, use it with () if request.user.is_authenticated():
if request.user.is_authenticated:
return redirect("login_url_name") # Or HttpResponseRedirect("login_url")
if comment_form.is_valid():
comments = comment_form.cleaned_data.get("comment")
# Rest of codes
Important
In your template, give access to the form to only authenticated users
{% if request.user.is_authenticated %}
<form method="POST" action="">{% csrf_token %}
<div class="form-group">
<label for="exampleFormControlTextarea1"><h5>评论 <i class="fa fa-comments"></i></h5></label>
<textarea id="js-pl-textarea" class="form-control" rows="4"
placeholder="我就想说..." name="comment"></textarea>
<div class="text-center mt-3">
<input type="submit" id='js-pl-submit' class="btn btn-danger comment-submit-button" value='Submit' />
</div>
</div>
</form>
{% endif %}
You can check whether the requested user is logged-in or not by user.is_authenticated() method, which returns a boolean value.
Try the following snippet,
def newsDetailView(request, news_pk):
# code
if request.method == 'POST' and comment_form.is_valid():
if not request.user.is_authenticated():
return HttpResponse("Please do login")
comments = comment_form.cleaned_data.get("comment")
comment = NewsComments(user=request.user, comments=comments, news=news)
comment.save()
return render(request, "news_detail.html", {
'title': title,
'author': author,
'add_time': add_time,
'content': content,
'tags': tags,
'category': category,
'all_comments': all_comments,
'comment_form': comment_form
})
My file is being uploaded in the correct path but I have an issues with it:
Whenever I refresh my HTML page the file gets uploaded again and again. How do I solve this? Also
Please help me with the code or suggest me.
Thanks in advance:)
My views.py
def about_experiment(request, ex_link_name):
researcher = None
study = None
posts = None
exp = get_object_or_404(Experiment,link_name = ex_link_name)
high_scores = ScoreItem.objects.filter(experiment=exp,active=True)
context = {
'request': request,
'exp':exp,
'high_scores': high_scores,
'awards':AwardItem.objects.filter(experiment=exp,visible=True),
}
if exp.about_file:
context['about_file'] = settings.EXPERIMENT_DIRS+exp.about_file.get_include_path()
return render(request, 'about_experiment.html', context)
if request.method == 'POST':
form = AboutHelp(request.POST, request.FILES)
posts = Help.objects.filter().order_by('-date')[0]
documents = Help.objects.all()
if form.is_valid():
obj = form.save(commit = False)
obj.save()
researcher = form.cleaned_data['researcher']
study = form.cleaned_data['study']
document = form.cleaned_data['document']
else:
form = AboutHelp()
posts = Help.objects.filter().order_by('-date')[0]
documents = Help.objects.all()
return render(request, 'about_experiment.html', {'posts': posts})
return render(request, 'about_experiment.html', {'posts': posts})
Source page
<form action="{% url 'lazer.views.about_experiment' exp.link_name %}" method="POST" name="form" enctype="multipart/form-data">
{% csrf_token %}
<label>Researcher Name(s):
<input type="text" name="researcher"><br>
<lable>Study Summary
<textarea rows="10" cols="50" placeholder="Start typing..." maxlength="500" class="form-control" name="study"></textarea>
<br>
<label>Upload your IRB approval letter:
<input type ="file" id="irb-file" class="file_input" name="document"></label>
<br>
<input type = "submit" value="Submit" class="btn btn-primary" />
</form>
destination page
<div class="tab-pane" id="irb">
<h4> List of file(s) uploaded:</h4>
<!--File upload-->
{% if documents %}
<ul>
{% for file in documents %}
<li> {{ file.document.name }} </li>
{% endfor %}
</ul>
{% else %}
<p>No such documents available.</p>
{% endif %}
<!--File upload ends-->
</div>
{% if high_scores %}
{% for hs in high_scores %}
<div class="tab-pane" id="{{ hs.link_name }}">
{% high_score request exp.link_name hs.link_name %}
</div>
{% endfor %}
{% endif %}
As #almost a beginner pointed out, you should be redirecting to some other view, if your form is submitted successfully. If not, (in your case), when the page reloads, the code for POST request is executed again. ie, your form is submitted again. I could suggest some changes in your view,
def about_experiment(request, ex_link_name):
exp = get_object_or_404(Experiment,link_name = ex_link_name)
high_scores = ScoreItem.objects.filter(experiment=exp,active=True)
context = {
'request': request,
'exp':exp,
'high_scores': high_scores,
'awards':AwardItem.objects.filter(experiment=exp,visible=True),
'posts':Help.objects.filter().order_by('-date')[0],
'documents':Help.objects.all()
}
if exp.about_file:
context['about_file'] = settings.EXPERIMENT_DIRS+exp.about_file.get_include_path()
if request.method == 'POST':
form = AboutHelp(request.POST, request.FILES)
if form.is_valid():
obj = form.save(commit = False)
obj.save()
return redirect(reverse('lazer.views.about_experiment', kwargs={ 'ex_link_name':obj.link_name }))
else:
form = AboutHelp()
return render(request, 'about_experiment.html', context)
Here, I merely assumed your obj has a field link_name. You may need to change that according to your models.
I am trying to authenticate a user(using the simple authenticate() function) in django.
def auth(request):
if request.method == 'POST':
auth_form = AuthenticationForm(request.POST)
if auth_form.is_valid():
auth_form.save()
user = authenticate(username=request.POST['id_username'],password=request.POST['id_password'])
if user is not None:
login(request,user)
return redirect('/profile/home/')
else:
return redirect('/')
else:
return redirect('/')
def register(request):
if request.method == 'POST':
form = SimpleUserCreation(request.POST)
if form.is_valid():
form.save()
user = authenticate(username=request.POST['id_username'],password=request.POST['id_password1'])
login(request,user)
return redirect('/profile/home/')
else:
return redirect('/')
This is the template displaying the forms - Just wanted to display login and register forms in the same page(for this example)
{% extends 'base.html' %}
{% load bootstrap_toolkit %}
{% block content %}
<div class="row">
<div class="span4 offset1 login">
<form class="form-signin" action="/auth/" method="POST">
{% csrf_token %}
{{ auth_form|as_bootstrap }}
<br>
<center>
<button class="btn btn-large btn-primary" type="submit">
Sign In
</button>
</center>
</form>
</div>
<div class="span4 offset2 signup">
<form action="/register/" method="POST">
{% csrf_token %}
{{ form|as_bootstrap }}
<br>
<center>
<button class="btn btn-large btn-primary" type="submit">
Register
</button>
</center>
</form>
</div>
</div>
{% endblock %}
I am getting an error like this:
ValueError at /auth/
The view SimpleUserAuth.auth.views.auth didn't return an HttpResponse object.
Any idea where i am going wrong?? I think its the authenticating function's inability to find the correct id for the fields...maybe i am wrong. I am a Noob :|
Cheers
In your auth method, if auth_form.is_valid() returns False, you do not return a response object.
The same is the case in def register(request): . If it is a GET request, the method does not return a response object.
Hence the error(s)
I made the mistake in these lines -
1) AuthenticationForm takes argument as follows:
AuthenticationForm(data=request.POST)
2) u can't save AuthenticationForm.
auth_form = AuthenticationForm(request.POST)
if auth_form.is_valid():
auth_form.save()
Thanks for the help karthik :)