Django - HTML template form does not pass content to django view - django

I'm trying to make a Django application, but I have an Issue that template doesn't pass it's content to view.
this is my form..
<form action="{% url 'view-job' %}" method="post" enctype=application/x-www-form-urlencoded>
{% csrf_token %}
<div>
<label for="name">Job name: </label>
<input type="text" id="name" />
</div>
<div>
<label for="owner">Owner: </label>
<input type="text" id="owner" />
</div>
...
and this is my post handling view (views_job.py)
def job(request, pk=None):
if request.method == 'GET':
return get(request, pk)
elif request.method == 'POST':
return post(request)
...
and post(request)
def post(request):
#data = json.loads(request.body.decode("utf-8"))
#data = load_json(request)
new_job = create_new_job(request)
#new_job = create_new_job(request)
if new_job != False:
return new_job
else:
return HttpResponse(status=500)
create_new_job(req)
def create_new_job(req):
config = parse_config()
try:
queryset = Job.objects.create(
name=req.POST.get('name'),
owner=req.POST.get('owner'),
execute_date=req.POST.get('execute_date'),
created_date=timezone.now(),
master=req.POST.get('master') if 'master' in req.POST != None else config[DEFAULT][MASTER],
deploy_mode=req.POST.get('deploy_mode') if 'deploy_mode' in req.POST != None else config[DEFAULT][DEPLOY_MODE],
conf=req.POST.get('conf'),
classpath=req.POST.get('classpath'),
app_arguments=req.POST.get('app_arguments'),
user_params=req.POST.get('user_params'),
status=READY,
)
#queryset.save()
except:
print("Error")
print(req.POST.get('name'))
return False
return render(req, 'jobUI/job_details.html',
{
#'job':queryset
}
)
The console prints
INFO 2018-03-21 18:48:29,033 basehttp 1321 140106696156928 "GET /jobUI/job/ HTTP/1.1" 200 1799
INFO 2018-03-21 18:48:30,208 basehttp 1321 140106696156928 "GET /jobUI/job/newjob/ HTTP/1.1" 200 1620
Error
None
ERROR 2018-03-21 18:48:47,499 basehttp 1321 140106696156928 "POST /jobUI/job/ HTTP/1.1" 500 0
I don't know why request.POST['name'] is None and other things too..
How can I fix it?
thank you.

Because your input fields don't have a name attribute; without that the browser won't send any data.
Note, you should really be using the Django forms framework for this. And you certainly absolutely shouldn't have a blank except clause.

Related

Django getting ERROR: Invalid syntax for time type

When I try to send messages to a temporary email address, it arrives there but does not go into the django database.
view.py
def about(req):
form = MessangeForm()
if req.method == "POST":
form = MessangeForm(req.POST)
if form.is_valid():
subject = form.cleaned_data.get('title')
body = form.cleaned_data.get('body')
try:
send_mail(subject, body, settings.EMAIL_HOST_USER, ["nakkosikni#gufum.com"], fail_silently=False)
form.save()
except Exception as err:
print(str(err))
return redirect('index')
return render(req, "about.html", {"form": form})
models.py
class Messange(models.Model):
title = models.CharField(verbose_name='Subject', max_length=250, null=True, blank=True )
body = models.TextField(verbose_name='Body')
def __str__(self):
return f'(self.body)'
forms.py
class MessangeForm(ModelForm):
class Meta:
model = Messange
fields = ["title", "body"]
widgets = {
"body": forms.Textarea(attrs={'class': 'form-control'}),
}
HTML Template
{% extends 'index.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h1>About</h1>
<!-- <p>{{ user.username }} </p> -->
<form method="POST" >
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary">Add Comment</button>
</form>
{% endblock %}
When I click on submit button I get this error.
[07/Dec/2022 22:19:08] "GET /about HTTP/1.1" 200 2437 ОШИБКА: неверный синтаксис для типа time: "иавипачич" LINE 1: ...service_messange" ("title", "body") VALUES ('сч', 'иавипачич... ^
[07/Dec/2022 22:19:26] "POST /about HTTP/1.1" 302 0 [07/Dec/2022 22:19:26] "GET / HTTP/1.1" 200 226
Translated:
[07/Dec/2022 22:19:08] "GET /about HTTP/1.1" 200 2437 ERROR: Invalid syntax for time type: "avipacich" LINE 1: ...service_messange" ("title", "body") VALUES ('sch', 'iawipacich... ^
I don't understand what needs to be changed there.
The DataError exception shown in the image is a django database exception. The cause of the error in this case was not due to any problems in the code shown, rather a change in the model before the database migrations were run. The body field of the class Mesange was changed from a date to a CharField, but the migrations were not run, leading to the error. The database was simply looking for a date and/or time, but was receiving a CharField.
The solution was simply to run
python manage.py makemigrations
python manage.py migrate

Django add User and Listing model to a Watchlist model

I'm trying to add a Listing model for an eCommerce app to a Wishlist model, but I'm not quite sure where I'm going wrong.
I referenced this post in order to create a Wishlist model and link it to my User and Listing models via a Foreign key for each.
Wishlist post
urls.py
from django.urls import path
from . import views
app_name = "auctions"
urlpatterns = [
# Listing paths
path("", views.index, name="index"),
path("login/", views.login_view, name="login"),
path("logout/", views.logout_view, name="logout"),
path("register/", views.register, name="register"),
path("addlisting/", views.add_listing, name="add_listing"),
path("viewlisting/<int:listing_id>", views.view_listing, name="view_listing"),
# Watchlist paths
path("watchlist_add/<int:listing_id>", views.watchlist_add, name="watchlist_add"),
]
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from datetime import datetime
# Categories
categories = [
('misc', 'misc'),
('computers','computers'),
('toys','toys'),
('pets','pets'),
('beauty','beauty'),
('video games','video games'),
('food','food'),
('clothing','clothing'),
]
ACTIVE_CHOICES = [
('Yes', 'Yes'),
('No', 'No'),
]
class User(AbstractUser):
pass
class Listing(models.Model):
listing_owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="owner")
listing_title = models.CharField(max_length=100)
listing_description = models.TextField(max_length=1200)
listing_img = models.URLField(null=True, blank=True, max_length=250)
created_on = models.DateTimeField(auto_now=True)
starting_price = models.DecimalField(decimal_places=2, max_digits=10, default=1.00)
# From above categories list
category = models.CharField(max_length=30, choices=categories, default='misc')
# From active or inactive list
active_flag = models.CharField(max_length=10, choices=ACTIVE_CHOICES, default="Yes", verbose_name="active listing")
class Meta:
ordering = ['-created_on']
def __str__(self):
return f"Name: {self.listing_title}, Price: ${self.starting_price}, Posted By: {self.listing_owner}"
class Watchlist(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
item = models.ForeignKey(Listing, on_delete=models.CASCADE, null=True)
def __str__(self):
return f"{self.item}"
views.py
#login_required
def view_listing(request, listing_id):
listing = get_object_or_404(Listing, pk=listing_id)
if request.method == "GET":
return render(request, "auctions/view_listing.html" , { "listing": listing})
else:
try:
form = ListingForm(request.POST, instance=listing)
form.save()
return redirect("auctions:index")
except ValueError:
return render(request, "auctions/view_listing.html", {"listing": listing, "form": form})
#login_required
def watchlist_add(request, listing_id):
listing = get_object_or_404(Listing, pk=listing_id)
obj, created = Watchlist.objects.get_or_create(user=request.user, item_id=listing_id)
return HttpResponseRedirect(reverse("auctions:index"))
view_listing.html
{% extends "auctions/layout.html" %} {% block body %}
<h1 class="display-3 text-center mb-5">{{ listing.listing_title }}</h1>
<div class="container d-flex">
<figure class="figure">
{% if listing.listing_img %}
<img src="{{ listing.listing_img }}" alt="{{ listing.listing_title }}" title="{{ listing.listing_title }}"> {% else %}
<img src="https://res.cloudinary.com/guez/image/upload/v1606759078/cs50_commerce_project/default_image.jpg" alt="default image" title="default image"> {% endif %}
<figcaption class="figure - caption">Listed By: {{ listing.listing_owner|capfirst }}</figcaption>
</figure>
<div class="container m-4">
<p class="display-4">${{ listing.starting_price }}</p>
<hr>
<p class="">Description: {{ listing.listing_description }}</p>
<p class="figure-caption">Category: {{ listing.category|capfirst }}</p>
<small></small>
</div>
<div class="container">
<form action="{% url 'auctions:watchlist_add' listing.pk %}" method="post">
{% csrf_token %}
<input type="hidden" value="{{ listing.pk }}" name="listing">
<input type="submit" value="Add To Watchlist" class="btn btn-outline-warning">
</form>
<!--Add To Watchlist-->
</div>
</div>
{% endblock %}
Before there are any items on my wishlist, I go to view_listing.html and hit the 'Add To Watchlist' button. I then get an AttributeError that reads "AttributeError: 'Listing' object has no attribute 'remove'". Here's the stack trace:
System check identified no issues (0 silenced).
December 07, 2020 - 00:08:42
Django version 3.1, using settings 'commerce.settings'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.
[07/Dec/2020 00:08:44] "GET /admin/auctions/watchlist/2/delete/ HTTP/1.1" 200 5409
[07/Dec/2020 00:08:45] "POST /admin/auctions/watchlist/2/delete/ HTTP/1.1" 302 0
[07/Dec/2020 00:08:45] "GET /admin/auctions/watchlist/ HTTP/1.1" 200 5215
[07/Dec/2020 00:08:46] "GET /admin/jsi18n/ HTTP/1.1" 200 3187
[07/Dec/2020 00:08:48] "GET /admin/auctions/watchlist/ HTTP/1.1" 200 5215
[07/Dec/2020 00:08:48] "GET /admin/jsi18n/ HTTP/1.1" 200 3187
[07/Dec/2020 00:08:51] "GET /admin/auctions/watchlist/ HTTP/1.1" 200 5215
[07/Dec/2020 00:08:51] "GET /admin/jsi18n/ HTTP/1.1" 200 3187
[07/Dec/2020 00:09:01] "GET / HTTP/1.1" 200 3962
[07/Dec/2020 00:09:03] "GET /viewlisting/8 HTTP/1.1" 200 2350
Name: Sega Genesis, Price: $1.00, Posted By: guez already in cart.
Internal Server Error: /watchlist_add/8
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/ubuntu/.local/lib/python3.7/site-packages/django/core/handlers/base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ubuntu/.local/lib/python3.7/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/ubuntu/project2/commerce/auctions/views.py", line 108, in watchlist_add
obj.listings.remove(listing)
AttributeError: 'Listing' object has no attribute 'remove'
[07/Dec/2020 00:09:06] "POST /watchlist_add/8 HTTP/1.1" 500 73233
I want to add the item to Wishlist via the watchlist_add function and then pass that new Wishlist object to the view_listing function in order to determine whether the button should or should not exist in the view_listing.html template if the item is already in request.user 's Watchlist.
?
Your code seems having a logic problem. You get_or_create a WatchList object, and you test if that obj is in the WatchList or not. The obj will always be in your WatchList.objects.all(), because it was there before or you just created.
obj.listings.remove(listing)
According to [django doc about remove()][1], you should use it the following way:
obj.listing_set.remove(obj)
together, how about something like:
#login_required
def watchlist_add(request, listing_id):
listing = get_object_or_404(Listing, pk=listing_id)
already_existed = Watchlist.objects.get_or_create(user=request.user, item=listing).exists()
if already_existed:
# do something:
# return ...
else:
Watchlist.objects.create(user=request.user, item=listing)
# do something
# return ....
Or you can still use get_or_create...
#login_required
def watchlist_add(request, listing_id):
listing = get_object_or_404(Listing, pk=listing_id)
obj, created = Watchlist.objects.get_or_create(user=request.user, item_id=listing_id)
if created: # means it was a new one
# do something
# return ...
else:
# do something, maybe delete whatever button you want to delete,
# maybe return a variable like below
# and in template you have {% if delete_button %}
# delete_button = True
# return ....
[1]: https://docs.djangoproject.com/en/3.1/ref/models/relations/#django.db.models.fields.related.RelatedManager.remove

Error : MultiValueKeyError at /quiz/2/11 'choice'

I am creating a multi-choice quiz app, I have created a view which shows the question and 4 option. I have given radio button to each option but is giving me this error:
MultiValueDictKeyError at /quiz/2/11/ 'choice'
views.py
def question_detail(request,question_id,quiz_id):
q = Quiz.objects.get(pk=quiz_id)
que = Question.objects.get(pk=question_id)
ans = que.answer_set.all()
selected_choice = que.answer_set.get(pk=request.POST['choice'])
if selected_choice is True:
come = que.rank
came = come + 1
later_question = q.question_set.get(rank=came)
return render(request,'app/question_detail.html',{'que':que , 'later_question':later_question, 'ans':ans})
else:
come = que.rank
later_question = q.question_set.get(rank=come)
return render(request, 'app/question_detail.html', {'que': que, 'later_question': later_question, 'ans': ans})
question_detail.html
<form action="{% 'app:detail' quiz_id=quiz.id question_id=que.id %}" method="post">
{% csrf_token %}
{% for choice in que.answer_set.all %}
<input type="radio" name="choice" id="choice{{forloop.counter}}" value="{{choice.id}}">
<label for="choice{{forloop.counter}}">{{choice.answer}}</label>
{% endfor %}
</form>
Okay like I said in my comment, you're most likely getting that error because the POST object will be empty during a normal GET request. So you should wrap everything that's meant to happen after a request in an IF block:
if request.method === 'POST':
selected_choice = que.answer_set.get(pk=request.POST['choice'])
# Every other post-submit task
You should always check for the POST method in your views if you're expecting form data. Others have answered this more in-depth before so I would just direct you there:
What does request.method == "POST" mean in Django?

Django request.method automatically set to GET and not POST

I'd like to setup an LDAP Authentication Backend in Django, and I've already used ldap3 to confirm a bind, with success.
I'm now realising that writing a class for my LDAP Backend with just ldap3 is not so straightforward, and that installing
django_auth_ldap could be another route to explore.
I've tested already some code to create a bind to the LDAP "server", and then perform a simple search. All okay. This method I tested is outside of my Django framework.
When implementing the same method into my Django framework, I encounter an issue when the method gets called. Because of the print statements, I know the view is getting called as exptected, but the part of the code whereby the first "if" statement should be executed, does not get called unless I change from "POST"
to "GET". But then this seems to create the next issue (when I set to "GET", so to force the next lines to be executed), because I'd like that a login page then gets called, where I can then input my LDAP credentials,
ultimately confirming the LDAP connection. Here is my code:
views.py
def login_ldap(request):
LDAP_SERVER = '10.222.4.88'
searchFilter='random'
print (request)
print (LDAP_SERVER)
print ("request.method:{0}".format(request.method))
if request.method == "GET":
print ("if statement executed")
username = request.GET['username']
print ("U:{0}".format(username))
password = request.GET['password']
print ("P:{0}".format(password))
# Define the server and bind_dn
server = Server(LDAP_SERVER, get_info=ALL)
bind_dn = 'cn={0}, ou=Prod, ou=Extern, ou=User, ou=ABC, dc=DEF, dc=com'.format(username)
# Define the Connection
conn = Connection(server, bind_dn, password, auto_bind=True) # Use raise_exceptions=True for exceptions
print ("search: {0}",format(conn.search))
print ("conn: {0}",format(conn))
conn.start_tls() #Session now on a secure channel. See output from following print statement and "tls started"
print ("conn_tls: {0}",format(conn))
d = conn.extend.standard.who_am_i()
print (d)
#print ("Server Info: {0}",format(server.info))
conn.open()
conn.bind()
# The LDAP search base for looking up users.
LDAP_AUTH_SEARCH_BASE = "ou=ABC, dc=DEF, dc=com"
if conn.bind():
conn.search(
search_base=LDAP_AUTH_SEARCH_BASE,
search_filter= '(cn={})'.format(searchFilter), # This is the user being searched for
search_scope=SUBTREE # BASE & LEVEL also possible settings
)
entry = conn.entries[0]
res = conn.bind()
print (res)
return render(request, 'search_page.html', {'entry':entry})
The error message received on my webpage:
MultiValueDictKeyError at /login_ldap/
"'username'"
Request Method: GET
Request URL: http://127.0.0.1:8000/login_ldap/
Django Version: 1.11
Exception Type: MultiValueDictKeyError
Exception Value:
"'username'"
I assume this is related to the GET and no longer the POST method. Why is the request.method being automatically set to GET and not POST when implementing
this in Django? Is this class for the authentication in the correct location, in the views.py file or should there be a separate file for this?
What should be included in the settings.py exactly (related to BACKEND_AUTH)?
EDIT:
views.py
def login_view(request):
if request.POST:
username = request.POST['username']
print ("U:{0}".format(username))
password = request.POST['password']
print ("P:{0}".format(password))
user = authenticate(username=username, password=password)
print (user)
if user is not None:
if user.is_active:
login(request, user)
return redirect('index')
else:
messages.error(request, "User is not active in Database")
else:
print ("Please check your credentials!")
messages.error(request, "Please check your username and password!")
return render(request, 'login.html')
index.html
<div class="row">
<div class="col-lg-3"></div>
<div class="col-lg-6"><H1>This is the public page, Please Login</H1></div>
</div>
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login_ldap/$', login_ldap, name='login_ldap'),
url(r'^login/$', login_view, name='login'),
url(r'^logout/$', logout_view, name='logout'),
url(r'^change_password/$', change_password, name='change_password'),
url(r'^$', index, name='index'),
]
settings.py
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
search_page.html
{% load static %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href='{% static "login.css" %}' rel="stylesheet">
<div class="wrapper">
<form method='post' action="" class="form-signin">{% csrf_token %}
<h2 class="form-signin-heading">Please login</h2>
<input type="text" class="form-control" name="username" placeholder="Username" required="" autofocus=""/>
<br>
<input type="password" class="form-control" name="password" placeholder="Password" required=""/>
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">Login</button>
</form>
</div>
You can use get() function to get the data.
if request.method == "GET":
print ("if statement executed")
username = request.GET.get('username')
For more reference you can see here,
MultiValueDictKeyError in Django
And about POST method you may require to import the csr_exempt and use the decorator before your view.
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def myView(request):

Duplicate entry in database on refreshing the submitted form in django

After i submit my form using GET method and then refresh the page the data get resubmitted
i am using javascript for form validation
my views are:
def show(request,post_id):
try:
p = post.objects.get(pk=post_id)
c = comment.objects.filter(blog_id=p)
if 'cbox' in request.GET:
c = comment(text=request.GET['cbox'],name=request.GET['cname'],blog=p)
c.save()
c_list = comment.objects.filter(blog_id=p)
except post.DoesNotExist:
raise Http404
return render_to_response('show.html',{'post':p,'c_list':c_list})
my form is:
<form name="comment" action="" method="get" onsubmit="return validateForm()">
<input id="carea" type="text" placeholder="leave a comment" name="cbox" >
<input id="cb" type="submit" value="Post" />
<input id="cn" type="text" placeholder="Name" name="cname">
</form>
i want that when i refresh my page my data should not get resubmited
thanks
If you really insist on using GET to submit which practically is not a good method. You should do a request redirect using HttpResponseRedirect from the server side which will remove the query string from the url . This way it wouldn't resumit the form.
def show(request,post_id):
try:
p = post.objects.get(pk=post_id)
c = comment.objects.filter(blog_id=p)
if 'cbox' in request.GET:
c = comment(text=request.GET['cbox'],name=request.GET['cname'],blog=p)
c.save()
#Do a redirect here
return HttpResponseRedirect("URL of the page you would like to redirect")
c_list = comment.objects.filter(blog_id=p)
except post.DoesNotExist:
raise Http404
return render_to_response('show.html',{'post':p,'c_list':c_list})