Im new to django and was struck by using slug, now Im confused how to use the ID parameter and convert to slug
URL.py
url(r'^deletePost/(?P<slug>[\w-]+)/$', views.delete_post, name='delete_post')
Template
<form method="POST" action="{% url 'delete_post' id=post.id %}">{% csrf_token %}
<button type="submit" class="btn btn-danger">   Delete</button>
</form>
Views.py
def delete_post(request,slug):
posts=Post.objects.get(slug=slug)
if request.method == 'POST':
posts.delete()
return redirect("home")
How can i use slug & id to delete the post which is created
Any help is appreciated. Thanks in advance
Error for reference
In my opionion, you dont want to convert the id to slug. You can just make your application flexible enough so that you could delete by either slug or id. You just need to handle the parameters accordingly.
So, you can do something like this:
urls.py
url(r'^deletePost/(?P<slug>[\w-]+)/$', views.delete_post, name='delete_post_by_slug'),
url(r'^deletePost/(?P<id>[0-9]+)/$', views.delete_post, name='delete_post_by_id')
And in the views:
def delete_post(request, slug=None, id=None):
if slug:
posts=Post.objects.get(slug=slug)
if id:
posts=Post.objects.get(id=id)
#Now, your urls.py would ensure that this view code is executed only when slug or id is specified
#You might also want to check for permissions, etc.. before deleting it - example who created the Post, and who can delete it.
if request.method == 'POST':
posts.delete()
return redirect("home")
Note that you can compress the 2 URL patterns into a single one - but this approach keeps it readable, and understandable. I shall let you figure out the URL consolidation once you are comfortable with the django framework, etc..
If you want to use both slug and id, your URL pattern should look like this:
url(r'^deletePost/(?P<slug>[\w-]+)-(?P<id>[0-9]+)/$',
views.delete_post, name='delete_post')
And your view should look like this:
def delete_post(request, **kwargs):
# Here kwargs value is {'slug': 'qw', 'id': '1'}
posts = Post.objects.get(**kwargs)
if request.method == 'POST':
posts.delete()
return redirect('home')
# ... (I guess this view does not end here)
And your template also have to set both:
<form method="POST" action="{% url 'delete_post' slug=post.id id=post.id %}">{% csrf_token %}
<button type="submit" class="btn btn-danger">   Delete</button>
</form>
Related
I have this view to show the previously populated data, which was only populated in the admin panel:
from .models import (Token,
Sell,
LogisticCost,
IncomeCost,
FinalPayment,
CustomerServiceCost,
Fatura)
def product_list(request):
context = {'product_list': ProductList.objects.filter(client=request.user.id).all(),
'data_payment': Fatura.objects.all()}
return render(request, 'Clientes/list_products.html', context)
This is the view to update these values:
class UpdateProduct(UpdateView):
model = ProductList
context_object_name = 'product_list'
template_name = 'Clientes/update_product.html'
fields = ['name', 'description', 'cost_price', 'sell_price', 'ncm']
My form in the update page is:
<form method="post" action="{% url 'client:product_list' %}">
{% csrf_token %}
{{ form }}
<button class="btn btn-inverse" type="submit">Atualizar</button>
</form>
My update page is working as expected, showing every value related to the selected object, but when I submit the form the model has not changed. What is happening to not update the values?
You are submitting the form to the product_list view - you should submit it to the update view instead.
Depending on your URLs, the form should look something like:
<form method="post" action="{% url 'client:update_product' product_list.pk %}">
After all, I removed the action from the form and I added the variable success_url = reverse_lazy('client:product_list') to my UpdateView. That solved the problem.
This is my first django project and I'm struggling to finish it.
I've been working to function that editing post. When user clicks button, it send no(int)for that article, and get information related to no and display on page. User can edit that post in the same form and when user click submit, it redirect to home.html
However, the function I made keep sending me an error message that it takes 2 arguments even though I did not use any function that takes 2 arguments.
Here is views.py
#login_required
def edit_article(request, article_no):
article = Article.objects.filter(pk=article_no)
form = ArticleForm(request.POST, instance=request.article)
if form.is_valid():
form.save()
messages.add_message(request, messages.SUCCESS, _('Article correctly saved.'))
# If the save was successful, redirect to another page
redirect_url = reverse('blog/home.html')
return HttpResponseRedirect(redirect_url)
else:
form = ArticleForm(instance=request.article)
return (request, {'form': form}, context)
This is form in detail.html where send no value to edit_article.html
<form action="{% url 'blog:edit_article' %}" method="post" style="display: inline;">
{% csrf_token %}
<input type="hidden" name="no" value="{{ item.no }}" />
<button type="submit">edit></button>
</form>
The article_no arg does not magically find its way into the function call via the POST submit. You need to provide it to the url tag:
{% url 'blog:edit_article' item.no %}
This assumes, of course, that you have a url pattern with an appropriate named group associated with this view/view name.
If You are talking about this function, it does recieve more than one Arg, it recieves the No you are talking about, and the request object
def edit_article(request, article_no):
...
If your view needs arguments you must give the arguments in the url templatetag, like this :
{% url 'accounts:detail_account' username = username %}
could you let me know how to pass my checkbox values to server?
views.py
def viewtest(request):
if request.method == "POST":
form=testForm(request.POST)
if(form.is_valid():
form.save()
elif request.method == "GET":
form=testForm()
return render(request,"test/register.html",{"testform":form})
forms.py
class testForm(forms.ModelForm):
workday=forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(), choices=workdayType)
class Meta:
model=test
fields=('name','tel')
register.html
<table>
<form method="post" action="{% url "viewtest" %}">
{{testform.as_table}}
</form>
<input type="submit" value="register"/>
</table>
I can see like below checkboxes.
but at server, can't see multiple data. could you provide me some idea?
there was my silly stuff. because I've used getting POST data as request.POST['workday']. it was wrong. I SHOULD USE form.cleaned_data.get("workday"). that's for my solution. But don't know what is different yet.
I am having trouble running a function in the view from an html button but the code seems to be right so if anyone knows what I am missing I would greatly appreciate it. The ultimate goal is to start a celery task so if there is a better way to do that please let me know.
template.html:
<form action="{% url 'save' pk=project.id %}" method="POST">
{% csrf_token %}
<button id="saveChanges" type="submit" class="btn btn-primary btn-sm">Save</button>
</form>
urls.py:
urlpatterns = patterns('',
....
url(r'^manage/save(?P<pk>\d+)/$', 'myapp.views.Save', name="save"),
....)
views.py
def Save(request, pk):
if request.method == 'POST':
project = Project.objects.get(id = pk)
....
task.delay(project.id)
return HttpResponse('OK', status=200)
#DoctorWizard run your server with manage.py runserver -- the log will be on the same terminal.
Your url pattern is using named groups which will pass keyword arguments to the view. Your view is only accepting positional arguments.
Either change the URL pattern to r'^manage/save(\d+)/$' (did you want a slash after save?)
OR
Change the view arguments to def Save(request, pk=None): or def Save(request, **kwargs): and pull pk from kwargs.
https://docs.djangoproject.com/en/1.6/topics/http/urls/#named-groups
First of all I'm glad to be here, I read you lately and i found useful answers here.
This is my first post so please be kind with me, I'm a newbie in programming.
So, I'm writing my 1st web application in Django - a todo app and I don't know how to write the function that does this this. I found something in Django docs and in other related discussions but it doesn't work.
Here's my code:
#models.py
class Task(models.Model):
user = models.ForeignKey(User)
task = models.CharField(max_length=200)
initialized_at = models.DateTimeField(auto_now_add=True)
due_date = models.DateField(default=datetime.now)
done = models.BooleanField(default=False)
def __unicode__(self):
return self.task
#views.py
def edit_task(request, id):
if request.method == 'POST':
task_to_edit = Task.objects.get(pk=task_id)
form = TaskForm(request.POST, instance=task_to_edit)
form.save()
if form.is_valid():
task_to_edit = form.save()
return HttpResponseRedirect('/')
else:
form = TaskForm()
return render(request, 'todo/edit_task.html', {'form': form})
#urls.py
url(r'^edit_task/(?P<task_id>\w+)/$', 'todo.views.edit_task')
#edit_task.html
{% block content %}
<form action="/edit_task/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
When I submit the updated form I get this error:
Page not found (404)
Request Method: POST
Request URL: hxxp://127.0.0.1:8000/edit_task/
Using the URLconf defined in jbz.urls, Django tried these URL patterns, in this order:
^admin/
^$ [name='index']
^(?P<task_id>\d+)/$
^(?P<task_id>\d+)/$
^add-task/$
^delete-task/(?P<task_id>\w+)/$
^edit_task/(?P<id>\w+)/$
^done/(?P<task_id>\d*)/$
The current URL, edit_task/, didn't match any of these.
and the root urls.py looks like:
url(r'', include('todo.urls'))
#edit_task.html
{% block content %}
<form action="/edit_task/{{task.id}}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
Notice how I added {{task.id}} expression in <form action="/edit_task/{{task.id}}" method="post">
IMPORTANT NOTE: Substitute {{task.id}} to whatever variable accomplishes this in your template.
The reason why you get the error is because edit_task/ is not getting the other part, task_id to match the regular expression:
url(r'^edit_task/(?P<task_id>\w+)/$', 'todo.views.edit_task')
UPDATE: Also your edit_task view has potential errors as well>
def edit_task(request, id):
task_to_edit = Task.objects.get(pk=id)
if request.method == 'POST':
form = TaskForm(request.POST, instance=task_to_edit)
form.save()
if form.is_valid():
task_to_edit = form.save()
return HttpResponseRedirect('/')
else:
form = TaskForm(instance=task_to_edit)
# you don't pass any task variable to the view so the form view
# won't know which task to edit, you'll have to handle that
return render(request, 'todo/edit_task.html', {'form': form, 'task':task_to_edit})
Note: I corrected the code in the view a little. Now the task_to_edit is passed also to the Form to fill the fields when the view is requested via GET. Notice that in order to access to this view, the url in the browser should look like this http://www.example.com/edit_task/2
If other wise you try to access http://www.example.com/edit_task without passing the id you'll get Error 404.
Hope this helps!
I think your pattern for edit task expects an id - task name. Try changing your URL pattern:
'^edit_task/(?P<task_id>\w+)/$'
to
'^edit_task/$'
or providing the task id that you want to edit.
Just add name space to your url and according update your template.
#urls.py
url(r'^edit_task/(?P<task_id>\w+)/$', 'todo.views.edit_task', name= "edit_task")
#edit_task.html
{% block content %}
<form action="{% url 'edit_task' task_id %}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}