Django 1.10 : view function() takes exactly 2 arguments (1 given) - python

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 %}

Related

Django custom login form not displaying inputfields

I have a problem with my login template. I´m not sure, but I think I´m using a custom form since the path is templates/registration/login.html . So, I think it gets replaced to the usual django form. But the input fields of my form dont show up, so I only have the login button and some text underneath it. Similar questions I read couldn´t solve it, so I hope someone can me help here. If you need any code more, please let me know. Thanks in advance.
views.py
def login(response):
if response.method == "POST":
form = LoginForm(response.POST)
if form.is_valid():
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password")
user = authenticate(username=username, password=password)
auth_login(response,user)
return redirect("home")
else:
form = LoginForm()
return render(response, "registration/login.html",{})
urls.py
from register import views as v
path("", v.login, name="login"),
login.html
{% block content %}
<form method="POST">
{% csrf_token %}
<div class="content">
<h3>{{form.username}}</h3>
<h3>{{form.password}}</h3>
<button type="submit">Login</button>
</div>
</form>
<br>
<p>Don´t have an account yet?</p>
<p>Create one here</p>
{% endblock %}
The render() function takes the request object as its first argument, a template name as its second argument and a dictionary as its optional third argument.
so, you should pass {"form": form} as the third argument to the render function.

Django HttpResponseRedirectwith URL Variables handling

I created an input form to get the data into web and use the inputs for an AP call.
When I want t refresh the page, there is a popup asking if you want to refresh the input. This is very annoying.
The solution was to use HttpResponseRedirect, which workout nicely, but it's throwing away all the inputs. Then the though would be to use variable in the URL with "URL?rds=2".
How do you get the input variables through the HttpResponseRedirect to the same site?
And also how to get variables from URL to input and from input to the URL?
HTML input definition:
<form action="{% url 'page' %}" method="post">
{% csrf_token %}
<input type="number" value="{{request.GET.rds}}" name='rds'>
<input type="submit" value="Search">
</form>
views.py:
Getting the data from the URL input
if 'rds' in request.GET.keys():
radius = request.GET.get('rds')
else:
request.GET.rds = '3'
radius = '3'
Redirecting input if user pressed. Add more variables with "&" if needed.
if request.method == 'POST':
radius = request.POST.get('rds')
redirect_link = request.path_info + '?rds=' + str(radius)
return HttpResponseRedirect(redirect_link)
This will redirect the radius to the same page and will put rds as a get attribute, which will be fatched by the if method.
Afterwards you can use the data with.
context = {'radius': radius}
return render(request=request, template_name='realestate/page.html', context = context)
I hope this is helpfull. Maybe there is also a way better solution then this.

Django NoReverseMatch at /qw-1/

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"> &nbsp 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"> &nbsp Delete</button>
</form>

Why does my Django request.method is 'GET' not 'POST'?

I met this strange problem when doing a pre-populated form.
In my template, the form method is clearly stated as POST:
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">{% csrf_token %}
But in my view function, the request.method turns out to be GET.
Below is my view function:
def editProfile(request,template_name):
theprofile = request.user.profile
print theprofile.fullname
notificationMSG = ''
print request.method
if request.method == 'POST':
form = UserProfileForm(request.POST,request.FILES, instance=theprofile)
if form.is_valid():
form.save()
notificationMSG = "success!"
else:
form = UserProfileForm()
print "error"
dic = {'form':form,
'notificationMSG':notificationMSG}
return render_to_response(template_name, dic, context_instance=RequestContext(request))
When I run it, it prints out GET.
Anyone met this odd before?
In my case I was missing a "/" at the end of action in the HTML Template, while posting.
When you are loading the form and retrieving remote data by hitting a url, the request method is GET.
When you fill the form values and submit the form(with post method) i.e. insert/update remote data, the request method is POST.
So, in your code when you print request.method, the output is GET when you are loading the form. This has nothing to do with your pre-populated form.
Here are the steps I needed so far to solve this kind of error:
Add method="post" to your <form> element
Add a missing "/" at the end of the url at the action property on your <form> element
Add a type="submit" to your <button> element
Ps. Don't forget to add {% csrf_token %} after your <form>.
Every time I submitted my form with action="" I was getting a GET response, but once I filled the actual URL action="/client/" it went through as a POST.
I am also facing this problem but, In my case, in input type, I have written
type =" button" when I change it to type="submit" it get resolved.
Sorry, I get misunderstood when again I face the same problem then I got actual solution.

How to post to a view in django from a django template?

Heres the scenario:
I have a email subscriber/un-subscriber app. I am stuck up in the un-subscribing a user part. The user is given a link, which if he/she follows will be able to un-subscribe. The link is typically a view, in the following format:
r^'/unsub_view/(?P<user_id>\w+)/$'
So, when the user follows this links he/she is doing a GET request on the view unsub_view with a parameter user_id. So I have coded up my view as:
def unsub_view(request, user_id):
if request.method == 'GET':
### Do some DB lookup to determine if it is a valid user or not
if user_is_valid:
return direct_to_template(request, '/app/unsub.html', {'user': user})
Now when a valid user is doing the GET, a confirmation dialogue is shown, along with a button. If he/she clicks on the button, I want the template to post the 'user' to the same view, thus the unsub_view also has this piece of code:
if request.method == 'POST':
if user_is_subscribed:
#Unsubscribe the user.
else:
#Show error meessage.
My question is how can I have the button in my template to post to this view ? I have looked around but I got POST-ing to a .php or .asp
Please help.
Note: If there is a better workflow idea, I am also open to that, so please do suggest if there is one.
In the template unsub.html rendering the form with the button, you should pass the url of your view using the reverse method
from django.code.urlresolvers import reverse
def unsub_view(request, viewid):
if request.method == 'POST':
if user_is_subscribed:
#Unsubscribe the user.
submit_url = reverse('unsub_view', viewid)
return direct_to_template(request, '/app/unsub.html', {'user': user, 'submit_url'})
else:
#Show error meessage.
in your template you can then render the form like follows :
...
<form method='post' action='{{ submit_url }}'>
{% csrf_token %}
<input type="hidden" value="{{ user_id }}" name="user_id" />
<input type="submit" value="unsubscribe"/>
</form>
...
Django also has a full framework dedicated to form modeling and rendering. You could take advantage of that to generate the form.

Categories

Resources