I have a model Product:
class Product(models.Model):
name = models.CharField(verbose_name="name", max_length=40)
cost = models.FloatField(verbose_name="price")
def __unicode__(self):
return self.name
I created a view where i can add new products but how can i delete these products?
my idea:
def delete_product(request, pk):
if request.method == "POST":
if form.is_valid():
product = form.delete(commit=False)
product.delete()
return redirect('homeshop.views.product_list', pk=product.pk)
But what next? I added to template (where i can edit product and save it) but it does not work:
{{ delete_product }}
Now in my template:
{% block content %}
<h1>Nowy wydatek</h1>
<form method="POST" class="product-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock %}
You would need to do something like this:
template.html
{% for product in products %}
{% csrf_token %}
...
<form action="{% url 'delete_product' product.id %}" method="POST">
<button type="submit">Delete</button>
</form>
...
{% endfor %}
then you would need to update your urls.py to have a URL defined that calls your delete function when the proper URL is visited.
url(
r'^delete/<product_id>$',
'delete_product',
name='delete_product'
)
I don't know exactly how your urls.py is laid out so your URL may have to look a little different.
Related
The code sample as novice of Django, is it right practice to achieve page load per ID as shown below?
View.py
def testidbasesearch(request,id=None):
if request.method == "GET":
print ('Inside IF GET')
if not id:
form = MtiForiegnForm()
else:
instance = Mt_Issue_foriegn.objects.get(id=id)
form = MtiForiegnForm(request.POST or None, instance=instance)
else:
print ('Inside Else GET')
id=request.POST.get('pkid')
return redirect(reverse('testidbasesearch', kwargs={"id": id}))
return render(request,'testingpost.html',{'form':form})
url.py
path('testidbasesearch',testidbasesearch,name='testidbasesearch'),
path('testidbasesearch/<int:id>',testidbasesearch,name='testidbasesearch'),
testingpost.html
{% extends 'base.html' %}
{% block content %}
<form id="postform1" method="post" action="">
{% csrf_token %}
<input type="text" name="pkid" />
<input type="submit" id="submit-form" />
{% for form1 in form %}
<fieldset disabled="disabled">
{{ form1 }}
</fieldset>
{% endfor %}
</form>
{% endblock %}
First of all my functionality is working as expected , I just need review is it right code practice, I purposely avoid AJAX/jquery ( i.e. js) pure django /python code to load form based on id submitted.
User login info is deleted when I delete posts.I wrote in views.py
def top(request):
if request.method == 'POST':
loginform = LoginForm(request, data=request.POST)
if loginform.is_valid():
user = loginform.get_user()
info = Info.objects.order_by('-created_at')
return render(request, 'top.html', {'info':info,'user': user})
loginform = LoginForm()
info = Info.objects.order_by('-created_at')
return render(request, 'top.html',{'info':info,'loginform':loginform,'user': request.user})
def delete(request):
delete_ids = request.POST.getlist('delete_ids')
if delete_ids:
Info.objects.filter(id__in=delete_ids).delete()
return redirect(reverse("app:top"))
in top.html
<div>
{% if user and not user.is_anonymous %}
<h2>{{ user.username }}</h2>
{% else %}
<form action="" method="POST">
<div>
{{ loginform.non_field_errors }}
{% for field in loginform %}
{{ field }}
{{ field.errors }}
{% endfor %}
</div>
<button type="submit">LOGIN</button>
{% csrf_token %}
</form>
{% endif %}
<div>
<form action="{% url 'app:delete' %}" method="POST">
{% csrf_token %}
{% for i in info %}
<input id="chkbox" type="checkbox" name="delete_ids" value="{{ i.pk }}" />
<div>
<p>{{ i.name }}</p>
</div>
{% endfor %}
<button type="submit">Delete</button>
</form>
Firstly I login to this app by putting LOGIN button,user.username is shown. And when I put Delete button to delete info,login info is deleted too(user.username is not shown).info is deleted but I really cannot understand why login info is deleted too.I cannot send user's info in redirect(reverse("app:top")),so shouldn't I use redirect?How should I fix this?
Looks like you forgot to login user. Try to add login() method:
from django.contrib.auth import login
def top(request):
if request.method == 'POST':
loginform = LoginForm(request, data=request.POST)
if loginform.is_valid():
user = loginform.get_user()
login(request, user)
Also it's better to use is_authenticated instead of is_anonymous:
{% if user.is_authenticated %}
This is my forms:
class signup_form(forms.ModelForm):
bio = forms.TextInput()
class Meta:
model = User
fields = ['username',
'password',
'first_name',
'last_name',
'email',
'date_joined']
And This one is my template page:
urlpatterns = [
......
url(r'^profile/(?P<username>[\w\-]+)/$', user_profile, name='user_profile'),
]
And this is signup template page:
{% extends parent_template|default:"tick/base_tick.html" %}
{% block title %}
{{ block.super }} ---> Sign Up HERE!!
{% endblock %}
{% block content %}
<div>
<div>
<form action="{% url 'user_profile' username={{ form.username }} %}" method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Create User</button>
</form>
</div>
</div>
{% endblock %}
As you can see in the 'action' part of the form i want to access to the 'username' field of 'form' but i can't and the Django get me some error.
What Should I do?
Edit: This is the Error
Value of a field is accessed by form.field_name.value. Use can update your code by below code
<form action="{% url 'user_profile' username=from.username.value %}" method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Create User</button>
</form>
I want to replace the add object button in the listview of an admin page. The underlying idea is that an administrator can download data on all models in the db, use a tool to edit the data, and then reupload as a CSV file.
In the list view I am struggling to override the form, as setting
class SomeModelForm(forms.Form):
csv_file = forms.FileField(required=False, label="please select a file")
class Meta:
model = MyModel
fields = '__all__'
class SomeModel(admin.ModelAdmin):
change_list_template = 'admin/my_app/somemodel/change_list.html'
form = SomeModelForm
other stuff
The admin change_list.html is overridden as follows:
{% extends "admin/change_list.html" %}
{% load i18n admin_urls admin_static admin_list %}
{% block object-tools-items %}
<form action="{% url 'admin:custom_submit_row' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>
{{ form.as_p }}
</p>
<p><input type="submit" value="Upload" /><input type="reset" value="Reset"></p>
</form>
{% endblock %}
Previously SomeModel was missing the class Meta, as per sebbs response this is updated. The original error has been resolved but now currently the admin page is displaying the upload and reset buttons but no field for file uploads.
cheers
Edited with sebb's input below. Thanks sebb.
The error fixed was
< class ‘my_model.admin.SomeModelAdmin'>: (admin.E016) The value of 'form' must inherit from 'BaseModelForm'
OP here, solution is as follows:
class SomeModelForm(forms.Form):
csv_file = forms.FileField(required=False, label="please select a file")
class SomeModel(admin.ModelAdmin):
change_list_template = 'admin/my_app/somemodel/change_list.html'
def get_urls(self):
urls = super().get_urls()
my_urls = patterns("",
url(r"^upload_csv/$", self.upload_csv, name='upload_csv')
)
return my_urls + urls
urls = property(get_urls)
def changelist_view(self, *args, **kwargs):
view = super().changelist_view(*args, **kwargs)
view.context_data['submit_csv_form'] = SomeModelForm
return view
def upload_csv(self, request):
if request.method == 'POST':
form = MineDifficultyResourceForm(request.POST, request.FILES)
if form.is_valid():
# process form
with the template overridden as so:
{% extends "admin/change_list.html" %}
{% load i18n admin_urls admin_static admin_list %}
{% block object-tools %}
{% if has_add_permission %}
<div>
<ul class="object-tools">
{% block object-tools-items %}
<form id="upload-csv-form" action="{% url 'admin:upload_csv' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ submit_csv_form.as_p }}</p>
<p>{{ submit_csv_form.csv_file.errors }}</p>
<p><input type="submit" value="Upload" />
<input type="reset" value="Reset"></p>
</form>
{% endblock %}
</ul>
</div>
{% endif %}
{% endblock %}
The form needs some custom validation but otherwise this solves the difficult part of customizing the admin page.
To elaborate what is going on here:
get_urls is overridden so that an additional endpoint can be added to the admin page, this can point to any view, in this case it points upload_csv
changelist_view is overridden to append the form info to the view
the change_list.html template block "object-tools" is overridden with the form fields
Hopefully someone else finds this helpful as well.
to your class SomeModelForm add something like this:
class Meta:
model = YourModel
fields = '__all__'
and change from forms.Form to forms.ModelForm
I have set of questions and its answers stored in db.I have a form to get answer for each question.I need to display only one question at a time in template and validate that answer against the original answer stored in db.
For now am able to display one value.But what i need is to display a question in a page and validate if the answer is correct,move on to display next question from db and so on. How do I achieve this?
form.py
from django import forms
class details_form(forms.Form):
answer = forms.CharField(widget=forms.TextInput())
views.py
def display_question(request):
context = RequestContext(request)
if request.method == 'GET':
print "GET"
form_class = details_form()
que_data = details.objects.get(que_id=1)
else:
##POST request
return render_to_response('sample/display_question.html',{'form':form_class,'que_data':que_data},context)
template:
{% extends 'sample/base.html' %}
{% block title %} Question {% endblock %}
{% block body_block %}
<p><strong>Your question : </strong></p>
"{{ que_data.que }}"
<p><strong>Type your answer here :<strong></p>
<form id='details_form' method = 'post' action='/next'>
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<br></br>
<input type ="submit" name="submit" value="Submit"/>
</form>
{% endblock %}
Update:
views.py
def display_question(request,question_id):
context = RequestContext(request)
form_class = details_form()
try:
quesno_id = {'id':question_id}
que_data = details.objects.get(que_id=question_id)
except details.DoesNotExist:
pass
if request.method == 'POST':
form = details_form(request.POST)
if form.is_valid():
user_answer = form.cleaned_data['answer']
if que_data.original_answer == user_answer:
return HttpResponseRedirect("question/%s/" %question_id+1)
else:
print form.errors
else:
pass
return render_to_response('sample/display_question.html',{'form':form_class,'que_data':que_data,'quesno_id':quesno_id},context)
template
{% extends 'sample/base.html' %}
{% block title %} Question {% endblock %}
{% block body_block %}
<p><strong>Your question {{ quesno_id.id}} : </strong></p>
"{{ que_data.que }}"
<p><strong>Type your answer here :<strong></p>
<form id='details_form' method = 'post' action="/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<br></br>
<input type ="submit" name="submit" value="Submit"/>
</form>
{% endblock %}
urls.py
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^question/(?P<question_id>\w+)/$',views.display_question,name='display_question'),
)
models.py
from django.db import models
class Songdata(models.Model):
que_id = models.AutoField(primary_key=True)
que = models.CharField(max_length=256)
original_answer = models.TextField()
def __unicode__(self):
return self.song_name
form.py
from django import forms
class details_form(forms.Form):
user_answer = forms.CharField(widget=forms.TextInput())
You need to use an absolute URL path like HttpResponseRedirect("/question/%s/" % (question_id+1)) (notice the leading slash)