I'm trying to create a button like in django - django

I have created a model and would like to use a like button afterwards
It did not work.How can I connect users and HTML with a function in views.py.
accounts.modles.py
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
likes = models.ManyToManyField(User,related_name='likes',blank=True)
profilepic = models.ImageField(upload_to='profile_pic',blank=True)
likeme.views.py
def like_post(request):
obj = get_object_or_404(UserProfile,id=request.POST.get('userprofile_id'))
obj.likes.add(request.user)
return redirect('profile_details')
likeme.ursl.py
path("like/",likeview.like_post,name="like_post")
like.html
<form class="" action="{% url 'like_post' %}" method="POST">
{% csrf_token %}
<button type="submit" name="post_id" value="{{ user.id }}" class="btn btn-info">Like</button>
</form>

Don't put the user pk in the button. It's better to use a hidden input field:
<input type="hidden" id="userprofile_id" name="userprofile_id" value="{{ user.pk }}">

Related

pass data to form filed in django templae

How can I pass data to form fields in django templat ? , for example I have below code in my project:
<td class="col-3">
{{form.number|as_crispy_field}}
</td>
Can I use
<td class="col-3">
{{form.number}} = 10
</td>
in django template ?
#mosi -
<td class="col-3">
{{form.number}} = 10
</td>
No, you cannot use this. If you are planning to pass data from views to template then do something like this
Let's say you have a form something like this
forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=30)
email = forms.EmailField(max_length=254)
views.py
def home(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
pass # your logic here
else:
form = ContactForm()
return render(request, 'home.html', {'form': form})
template.html
<form method="post" novalidate>
{% csrf_token %}
{{ form.name }}
{{form.email}}
<button type="submit">Submit</button>
</form>
OR
Simply
<form method="post" novalidate>
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
Now, if you want to set initial values to your form in template
Lets say you have the following
class ContactForm(forms.Form):
name = forms.CharField(max_length=30,initial='test')
Then in your template you do something like this
<form method="post" novalidate>
{% csrf_token %}
<input type="text" name="name" id="name" value="{{ form.name.value }}">
<button type="submit">Submit</button>
</form>
Now, in case of an UpdateView where data is pulled in dynamically from the Database based on let's say product id. The following is just an example
class ProductForm(forms.ModelForm):
class Meta:
model = Product
exclude = (
"created_by",
"slug",
)
class ProductUpdateView(UpdateView):
# specify the model you want to use
model = Product
form_class = ProductForm
template_name = "catalog/product/update_product.html"
product_update.html
<form method="post" enctype="multipart/form-data">
<div class="card-body">
{% csrf_token %}
{{ form.as_p}}
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>
Or
<form method="post" enctype="multipart/form-data">
<div class="card-body">
{% csrf_token %}
<input type="text" name="name" id="name" value="{{ form.name.value }}">
<input type="text" name="description" id="description" value="{{ form.description.value }}">
.........
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>

Forbidden (403) CSRF verification failed

When I click on ok button in add_tech.html then it will redirect me on upload_type.html.
But it show error while clicking on ok button.
ERROR -
Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
CSRF token missing or incorrect.
My template(add_tech.html) -
<form action="/uploads/type/" method="post">
<label for="your_name">New Tech: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
My Template(upload_type.html)-
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form}}
</form>
My View.py -
def upload_type(request):
if request.method =='POST':
details = NameForm(request.POST)
if details.is_valid():
return render(request, "core/upload_type.html", {'form':details})
else:
details = NameForm()
return render(request, 'core/upload_type.html', {'form': details})
My Url.py -
urlpatterns = [
url(r'^uploads/type/$', views.upload_type, name='upload_type'),]
My form.py -
from uploads.core.models import Name
class NameForm(forms.ModelForm):
class Meta:
model = Name
fields = ('your_name', )
My Models.py-
class Name(models.Model):
your_name = models.CharField(max_length=100)
You need to have the csrf token like this for your post method in the django template
<form action="/uploads/type/" method="post">
{% csrf_token %}
<label for="your_name">New Tech: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
For POST request, csrf token is required. So in your template, add `{% csrf_token %}.
<form action="/uploads/type/" method="post">
{% csrf_token %}
<label for="your_name">New Tech: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
From the Docs:
Django ships with an easy-to-use protection against Cross Site Request
Forgeries. When submitting a form via POST with CSRF protection
enabled you must use the csrf_token template tag as in the preceding
example.

Submitting dynamically created input field in django

am working on a project with Django, i dynamically created an input field and am trying to submit it, but i could not do so, i searched online and i saw that it could be done with formset_factory but when i tried it, i got this error
CatName = int(float(request.POST.get('CatName')))
TypeError: float() argument must be a string or a number, not 'NoneType'
here is my code
the form.html
<form action="." method="post" id="PostCat__form">{% csrf_token %}
<input type="hidden" name="deyHidden" value="category_hidden">
{% comment %} {{ catForm | crispy }}
<input type="hidden" name="deyHidden" value="category_hidden"> {% endcomment %}
<input type="text" class="form-control" name="CatName[]" >
<input type="text" class="form-control" name="CatName[]" >
<input type="text" class="form-control" name="CatName[]" >
<input type="text" class="form-control" name="CatName[]" >
<div class="form-group">
<h6 id="PostCat__show"></h6>
<img src=" {% static 'images/ajax-loader.gif' %}" style="Display:none;" id="PostCat__img">
<button class="btn btn-outline-info" type="submit" id="PostCat__submit">Create</button>
</div>
</form>
the model.py
class Category(models.Model):
CatName = models.CharField(max_length=100)
the view.py
myFormCat = CatPostForm(request.POST)
CatName = int(float(request.POST.get('CatName')))
# print(CatName)
formset = formset_factory(FormsetForm, CatName=CatName)(request.POST)
if myFormCat.is_valid() and formset.is_valid():
for form_c in formset:
if not form_c.cleaned_data['CatName']:
Category.objects.get_or_create(CatName=CatName)
response_data = {
'SType': 'success',
'message': "Saved Successfully"
}
return HttpResponse(json.dumps(response_data), content_type="application/json")
the forms.py
class CatPostForm(forms.ModelForm):
class Meta:
model=Category
fields = ['CatName']
pls how can i do it so that i can successfully submit the form,
on your views.py
from django.forms import formset_factory
CatPostFormSet = formset_factory(CatPostForm)
catformset = CatPostFormSet() #this goes to your page context. do the validations here also after the post
on your form.html
<form method="post">
{{ formset.management_form }}
{{formset}}
</form>

Delete object with form in django

I'm displaying a table. In every line there should be a delete button which deletes the element from the table.
My problem is, I'm not sure how to pass the id of the element to the view.
html:
{% for post in posts %}
<div>
<h3>Zuletzt ausgewählt:</h3>
<p>published: <b>{{ post.pub_date }}</b>
</p>
<p>
name: <b>{{ post.Name }}</b>
anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
essen: <b>{{ post.get_Essen_display }}</b>
<form action="" method="POST">
{% csrf_token %}
<input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
</form>
</p>
<p>
Email: <b>{{ post.Email }}</b>
</p>
</div>
{% endfor %}
views.py
if request.method == 'POST' and 'delete' in request.POST:
Eintrag.objects.filter(pk=id).delete()
return HttpResponseRedirect(request.path)
So I need to pass post.pub_date of every post to the view, how can I accomplish that?
My problem is, I'm not sure how to pass the id of the element to the view.
I can think of two ways to do this. I'll cover them both one by one.
1. Create a separate url route in your app specifically for deleting objects:
('/post/<pk>/delete/', name="delete_post"),
Then point your form's action to this url:
<form action="{% url 'delete_post' post.pk %}" method="POST">
...
Finally, modify your view function to accept the pk argument:
def my_view(request, pk):
...
2. Second method is to just create another field in your form and pass it the pk of the object:
Just create another field in your form.
<form action="" method="POST">
<input type="hidden" value="{{ post.pk }}" name="pk">
...
Then in your view just look at request.POST['pk'] to get the pk of the post.
A non-ajax way which is super easy to implement as it uses the Django generic views is this:
template.html
{% for post in posts %}
<div>
<h3>Zuletzt ausgewählt:</h3>
<p>published: <b>{{ post.pub_date }}</b>
</p>
<p>
name: <b>{{ post.Name }}</b>
anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
essen: <b>{{ post.get_Essen_display }}</b>
<form action="" method="POST">
{% csrf_token %}
<input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
</form>
</p>
<p>
Email: <b>{{ post.Email }}</b>
</p>
<a href="/deleteurl/{{ post.pk }}">
Delete this!
</a>
</div>
{% endfor %}
Once the user clicks on the delete link they will be redirected to the delete view and template which will have a URL that looks like this "/deleteurl/1/".
Then your set of views, url, and template for processing the delete could look like this:
views.py
class DeleteMe(generic.DeleteView):
template_name = 'deleteconfirmation.html'
model = YourModel
success_url = '/YourRedirectUrl/'
urls.py
url(r'^deleteurl/(?P<pk>\d+)/$',
views.DeleteMe.as_view(), name='deletemeview'),
deleteconfirmation.html
<form action="" method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>
Again, this is without the use of Ajax.
The views and template are taken directly from the Django Docs
Using POST is our priority, but I thought that adding another form will be redundant.
Found solution in django-allauth' email view.
Though it doesn't include confirmation step (as in docs, mentioned by #HoneyNutIchiros or in more details, or via onclick), it can be useful.
They add name (action_remove) to button and check it in the request.POST dict:
# account/email.html
<button type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
<button type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button>
<button type="submit" name="action_remove" >{% trans 'Remove' %}</button>
...
<button name="action_add" type="submit">{% trans "Add E-mail" %}</button>
# account/views.py
class EmailView(AjaxCapableProcessFormViewMixin, FormView):
...
def post(self, request, *args, **kwargs):
...
if "action_add" in request.POST:
res = super(EmailView, self).post(request, *args, **kwargs)
elif "action_remove" in request.POST:
res = self._action_remove(request)
...
return res

django-ckeditor request dont get changes in form

I have one form called in ajax function, this function return one django form with one ckeditor field.
This field is displayed without problems, but when I make a request, the field value, dont sended in request, but if I make another, in the same form, with the same values, the value is update and is sended in request.
My form field
class EditCommentForm(IdeiaForm):
content = forms.CharField(
max_length=settings.COMMENT_TEXT_LIMIT if hasattr(settings, "COMMENT_TEXT_LIMIT") else 10000,
required=True,
widget=CKEditorWidget(config_name='question')
)
comment_id = forms.IntegerField(required=True)
My html template
<form class="create-comment" data-group-class=".comment-group" data-ajaxform="true" data-toggle="replace" class="create-comment" data-update="#{{ to_update }}" action="{% url 'comment:edit' %}" method="post">{% csrf_token %}
<div class="comment-group create-comment-body{% if form.content.errors %} has-error{% endif %}">
<textarea name="content" class="form-control" placeholder="Deixe seu comentário">{{ instance.content }}</textarea>
<span class="help-block"></span>
</div>
<input name="comment_id" value="{{ instance.id }}" type="hidden"/>
<div class="create-comment-footer">
<input type="submit" value="Editar" class="btn btn-primary">
</div>
</form>