Why is my delete button not deleting my database object? Django - python

I cobbled together a delete button and edited my view, it isn't working. Can someone help me fix it?
I've moved some code around and tried some things but I can't get it to work. I need someone to show me what I'm doing wrong.
My view:
def post_edit(request, pk):
post = get_object_or_404(Listing, pk=pk)
if request.method == "POST":
form = ListingForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('post_view', pk=post.pk)
else:
form = ListingForm(instance=post)
if request.POST.get('delete'):
post.delete()
return redirect('listings')
return render(request, 'post_edit.html', {'form': form})
My html:
{% extends 'base.html' %}
{% block title %}Post Edit{% endblock %}
{% block content %}
Hi {{ user.username }}!
<p>logout</p>
<h1>Edit listing:</h1>
<p>The listing will only be viewable to users if "Is Live" is checked.</p>
<form method="POST" enctype="multipart/form-data" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
<p>Click the button below to delete this listing. No second warning is given, once you click delete it will be
removed.</p>
<button type="delete" class="delete btn btn-default">delete</button>
</form>
{% endblock %}

"delete" is not a valid type for an HTML form control. You'l need to change it to "submit" (Since you still want to submit the form).
What you'll want to do is create two buttons with the same name, and different values like this:
<button type="submit" name="submit" value="submit" class="save btn btn-default">Save</button>
<p>Click the button below to delete this listing. No second warning is given, once you click delete it will be
removed.</p>
<button type="submit" name="submit" value="delete" class="delete btn btn-default">delete</button>
Then you can check in your view if the delete button was clicked, like this:
def post_edit(request, pk):
post = get_object_or_404(Listing, pk=pk)
if request.method == "POST":
if request.POST.get('submit') == 'delete':
post.delete()
return redirect('listings')
form = ListingForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('post_view', pk=post.pk)
else:
form = ListingForm(instance=post)
return render(request, 'post_edit.html', {'form': form})
Note that I move the check for the delete button to inside the if request.method == "POST": block, for two reasons:
You'll only want to check the POST values if it's actually a post method.
There is no use editing a post, then deleting it.

Related

Django problem with form using action and not the if method == post in the view

So i am trying to add a value to the session dictionary because i wanted to make a cart/checkout for guests.
This is the code in my views.py
def productdetail(request, pk):
Decks = decks.objects.get(id=pk)
if request.method == 'POST':
form = order(request.POST)
if form.is_valid():
request.session['cart'] = [pk]
else:
form = order()
return render(request, 'shop/single_product.html', {'deck': Decks, 'form': form})
And the code in my html
<form action="{% url 'productdetailcart' deck.id%}" method="post">
{% csrf_token %}
{{ form }}
<input class="btn btn-lg btn-block btn-round btn-b" type="submit" value="Add To Cart">
Now my problem is that without the action in the form tag the session['cart'] in the views.py adds the value in the session which is what i want. But if i have the action to go to that url i only go to the url without adding the pk to the session['cart'] . Its like im forced to choose between going to the page or saving to session.

Django form.errors not showing up in template

I have refrenced this stackoverflow page and tried to display my forms error on the html template.
I did:
{% if form.error %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
as said in the stackoverflow question I also tried simply doing:
{% if form.error %}
This should pop up if there is an error
{% endif %}
Nothing comes up regardless:
Heres my view.py code:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password2')
user = authenticate(username=username, password=password)
login(request, user)
return HttpResponseRedirect('/')
else:
print(form.errors)
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})
I am able to get the form errors onto the django console but it refuses to show up on the template.
Printing form.errors prints to the console: <li>password2<ul class="errorlist"><li>The two password fields didn't match.</li></ul></li></ul>
forms.errors fired up, but at the end, you declare a new form form = UserCreationForm() just before you render your view.
After checking whether the form is valid or not, all your validation errors are inside form instance, remember processes run as sequence, at the end, you destroy the variable form with form = UserCreationForm() so no validation errors anymore.
What you can do is add this new form form = UserCreationForm() to else statement when your request method is GET to keep having an empty form. By adding the else statement you avoid the new assignment of the form; after the validation process, it will jump to render(request,....) with the form instance containing all validation errors
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password2')
user = authenticate(username=username, password=password)
login(request, user)
return HttpResponseRedirect('/')
else:
print(form.errors)
else:
form = UserCreationForm()
return render(request, 'registration/register.html', {'form': form})
Note, the correct call for form errors in templates is form.errors with s not form.error
{% if form.error %} {% if form.errors %}

Form is not shown in html correctly

Form is not shown in html correctly.I wrote in search.html,
{% load static %}
<form action='/search/' method='POST>
<table>
{{ form.as_table }}
</table>
<input name="submit" type="Search" />
{% csrf_token %}
</form>
in views.py
def search(request):
form = SearchForm()
if request.method == 'GET':
return render_to_response(
'search.html', {'form': form}, RequestContext(request))
elif request.method == 'POST':
form = SearchForm(request.POST)
search_result = POST.objects.all()
if form.is_valid():
result = search_result.filter(Q(title__contains=form.cleaned_data['keyword']))
return render_to_response('search.html',{'form':form, 'result':result})
When I access search method,search.html is shown as strings like
now search.html
It is not From,so I really cannot understand why such a thing happens.No error happens but UserWarning: A {% csrf_token %}was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext.
"A {% csrf_token %} was used in a template, but the context " is shown in terminal.How should I fix this?What is wrong in my code?
This may not be the issue, but I think your input tag is wrong, it should be this:
<input name="submit" type="Search">
As here : https://www.w3schools.com/tags/tag_input.asp

django user creation form with auth.user clean method

I have created a form to add users in my front-end but the form does not validate duplicated username.I am using auth.user model.
This is my code:
views.py
from django.contrib.auth.models import User, Group
#login_required(login_url='/login/')
#permission_required('auth.add_user',raise_exception=True)
def user_new(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(user.password)
user.save()
return redirect('userdetail', user.id)
else:
form = NewUserForm()
return render(request, 'ace/user_edit.html', {'form': form})
forms.py
class NewUserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username','first_name','last_name','password','email','is_active','is_staff','groups']
widgets = {
'username':TextInput(attrs={'class': u'form-control'}),
'first_name':TextInput(attrs={'class': u'form-control'}),
'last_name':TextInput(attrs={'class': u'form-control'}),
'password':PasswordInput(attrs={'class': u'form-control'}),
'email':EmailInput(attrs={'class': u'form-control'}),
'is_active':NullBooleanSelect(attrs={'class': u'form-control'}),
'is_staff':NullBooleanSelect(attrs={'class': u'form-control'}),
'groups':SelectMultiple(attrs={'class': u'form-control'}),
}
def clean_username(self):
username = self.cleaned_data['username']
user_exists = User.objects.get(username=username)
if user_exists:
raise ValidationError("User exists")
template
...
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<form method="POST" class="service-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-info">Salvar</button>
<a href="{% url 'userlist' %}">
<button class="btn btn-danger" type="button">Cancelar</button>
</a>
</form>
...
When I create a new user OK, but when a try create a user that same username of other I get a error:
The view ace.views.user_new didn't return an HttpResponse object. It
returned None instead.
If I add a print line "print form.errors" in view i get in console:
usernameUser
exists
Your view does not have an else statement for if, form is not valid it should render the template with form errors.
You need to change your view like this,
def user_new(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(user.password)
user.save()
return redirect('userdetail', user.id)
else:
return render(request, 'ace/user_edit.html', {'form': form})
else:
form = NewUserForm()
return render(request, 'ace/user_edit.html', {'form': form})
And also you need to add the tag {%for field in form%} {{field.error}}{%endfor%} along with the form fields and labels.
You need to make sure that your view returns a response for POST requests when the form is invalid. You can do this by moving the final return render() statement out of the else block.
def user_new(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
...
return redirect('userdetail', user.id)
else:
form = NewUserForm()
return render(request, 'ace/user_edit.html', {'form': form})
For registration django.contrib.auth User needs the username field to be unique. If you want to use other model field as unique (as unique registration field) and not the username, for example the email field, you can use this approach or use other registration bakends like django registration or django registration redux.
Instead of fixing the bug in your code I suggest to not invent the wheel and use excellent django-allauth package. It handles user login, logout, change password, registration and social sign in. I always start new projects from adding django-allauth - it handles all authentication problems with no effort.
You can use the saved time and effort to write actual application code instead of solving trivial user management details.
Also, the proper way to check for existence of the model instance is this:
user_exists = User.objects.filter(username=username).exists()
if user_exists:
raise ValidationError("User exists")

Can't add file in django 1.7

I cannot add a file in Django. When I click the "save" button, it does not save the database.
This is my view.py:
def add_product(request):
if request.method == "POST":
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.userprofile = request.user
post.save()
return redirect('kerajinan.views.add_product', pk=post.pk)
else:
form = PostForm()
return render(request, 'kerajinan/add_product.html', {'form': form})
add_product.html:
{% block content %}
<h1>New Product</h1>
<from method="POST" class="post-form" enctype="multiple/form-data">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</from>
{% endblock %}
forms.py:
class PostForm(forms.ModelForm):
class Meta:
model = Product
fields = ('category','title', 'price','image', 'description')
and urls.py:
url(r'^add_product/$', views.add_product, name='add_product'),
Can you help me solve my problem?
You need to change your enctype to: enctype="multipart/form-data"
Your current value (multiple/form-data), is not a valid method of encoding.
From the docs:
Note that request.FILES will only contain data if...the <form> that posted the request has the attribute enctype="multipart/form-data". Otherwise, request.FILES will be empty.

Categories