I wrote a way to add comments, but it didn't run - django

My idea is to create a model of articles and comments. When users initiate comments, they can directly create data, but adding comments in the actual operation does not respond.
#views.py
def details(request, article_id):
detail = LifeArticle.objects.get(id=article_id)
comment = LifeComment.objects.get(article=detail)
return render(request, 'lifedetail.html', locals())
def addcomment(request, article_id):
article = LifeArticle.objects.get(id=article_id)
if request.method == "POST":
content = request.POST['content']
r = LifeComment.create(article=article, user=request.user, content=content)
msg = '添加成功'
return render(request, 'lifedetail.html', locals())
else:
return render(request, 'lifedetail.html',)
#urls.py
urlpatterns = [
url(r'^life/(?P<article_id>\d+)/', views.details),
url(r'^article/life/(?P<article_id>\d+)/addcoment/', views.addcomment)
]
#lifedetail.html
{% if detail %}
<div id='article'>
<form action="/article/life/{{detail.id}}/addcoment/" method="POST">
{% csrf_token %}
<tr>
<td>{{ detail.title }}</td>
<td>{{ detail.content }}</td>
<td>{{ detail.user }}</td>
</tr>
</div>
<div id="comment">
{% if comment %}
<tr>
<td>{{ comment.content }}</td>
<td>{{ comment.user }}</td>
</tr>
</div>
{% else %}
<p>暂无评论</p>
{% endif %}
<input type="text" name="content">
<input type="submit" value="提交">
</form>
{% else %}
<p>暂无文章</p>
{% endif %}
{{msg}}
</div>
These are my code. Now I can't find the reason. I'm also looking at Django2.2's documentation to find the problem

I think the problem is in this line:
r = LifeComment.create(article=article, user=request.user, content=content)
I think you should use objects here:
r = LifeComment.objects.create(article=article, user=request.user, content=content)
Also, you need to send detail information from context:
def addcomment(request, article_id):
article = LifeArticle.objects.get(id=article_id)
if request.method == "POST":
# rest of the code
else:
return render(request, 'lifedetail.html', context={'detail':article})

Related

How i can create a delete button in django python?

I'm new to Django and i try my best to resolve this problem.
So i try to create a delete button on my template. I create my view and i create my url but it doesn't work.
So here my views :
def book_delete(request, pk):
book = get_object_or_404(Book, pk=pk)
if request.method == 'POST':
book.delete()
return redirect('/')
return render(request, "livre/newbook_form.html", {'form': book})
My urls
from . import views
from django.conf.urls import url
urlpatterns = [
url(r'^livre/(?P<pk>[0-9]+)/$', views.book_delete, name='book_delete')
]
My template
<form action="liste" method="POST">{% csrf_token %}
<table>
<th>Titre</th><th>Auteur</th><th>Nombre de pages</th><th>Supprimer</th>
{% for Book in Book %}
<tr>
<td>{{ Book.title }}</td>
<td>{{ Book.author }}</td>
<td>{{ Book.num_pages }}</td>
<td>
<form action="{% url 'book_delete' Book.id %}" method="POST">
{% csrf_token %}
<input type="button" value="{{Book.id}}"/>
</form>
</td>
</tr>
{% endfor %}
</table>
</form>
I don't know why it doesn't work. Can you help me ?
You need to submit the form, so with type="submit" [dev-mozilla]:
<form action="{% url 'book_delete' Book.id %}" method="POST">
{% csrf_token %}
<input type="submit" value="delete"/>
</form>

Unable to edit/delete existing formets

I am new here. I have been working on this issue for the past couple of days. Could someone help me, please?
Problem: Unable to edit/delete existing formsets
I have 1 form and 2 formsets in a view. I can create all 3, successfully.
Template rendering 1 form and 2 formsets
Also, I can edit/delete the form, but can't with the 2 formsets.
models.py
class Component(models.Model):
...
class ComponentImage(models.Model):
component = models.ForeignKey(Component, on_delete=models.CASCADE, related_name='componentimage')
image = models.ImageField(upload_to='component_pics')
caption = models.CharField(max_length=100, null=True, blank=True)
class ComponentWeblink(models.Model):
component = models.ForeignKey(Component, on_delete=models.CASCADE, related_name='componentweblink')
url = models.URLField()
caption = models.CharField(max_length=100, null=True, blank=True)
views.py
def component_create(request):
template = 'component/component_add.html'
if request.method == 'GET':
form = ComponentForm()
images = ImageFormset(queryset=ComponentImage.objects.none(), prefix='images')
links = WeblinkFormset(queryset=ComponentWeblink.objects.none(), prefix='links')
elif request.method == 'POST':
form = ComponentForm(request.POST)
images = ImageFormset(request.POST, request.FILES, prefix='images')
links = WeblinkFormset(request.POST, prefix='links')
if form.is_valid() and images.is_valid() and links.is_valid():
component = form.save(commit=False)
component.updated_by = request.user
component.save()
for form in images:
if form.has_changed():
componentimage = form.save(commit=False)
componentimage.component = component
componentimage.updated_by = component.updated_by
try:
componentimage.save()
except ValueError:
pass
for form in links:
if form.has_changed():
componentweblink = form.save(commit=False)
componentweblink.component = component
componentweblink.updated_by = component.updated_by
componentweblink.save()
messages.success(request, 'Component successfully created.')
return HttpResponseRedirect(reverse_lazy('component:component_detail', args=(component.pk,)))
return render(request, template, {
'form': form,
'images': images,
'links': links,
})
def component_update(request, pk):
obj = get_object_or_404(Component, id=pk)
template = 'component/component_update.html'
if request.method == 'GET':
form = ComponentForm(instance=obj)
images = ImageFormset(instance=obj, prefix='images')
links = WeblinkFormset(instance=obj, prefix='links')
elif request.method == 'POST':
form = ComponentForm(request.POST or None, instance=obj)
images = ImageFormset(request.POST or None, request.FILES or None, instance=obj, prefix='images')
links = WeblinkFormset(request.POST, instance=obj, prefix='links')
if form.is_valid() and images.is_valid() and links.is_valid():
component = form.save(commit=False)
component.updated_by = request.user
component.save()
for form in images:
if form.has_changed():
componentimage = form.save(commit=False)
componentimage.component = component
componentimage.updated_by = component.updated_by
try:
componentimage.save()
except ValueError:
pass
for form in links:
if form.has_changed():
componentweblink = form.save(commit=False)
componentweblink.component = component
componentweblink.updated_by = component.updated_by
componentweblink.save()
messages.warning(request, 'Component successfully updated.')
return HttpResponseRedirect(reverse_lazy('component:component_detail', args=(component.pk, ))) #trailing comma is required for single-item tuples to disambiguate defining a tuple or an expression surrounded by parentheses
return render(request, template, {
'form': form,
'images': images,
'links': links,
})
template.html (for update view)
{% block content %}
<script type="text/javascript" src="{% static 'js/jquery.formset.js' %}"></script>
<script type="text/javascript">
$(function() {
$('#images tbody tr').formset({
prefix: '{{ images.prefix }}',
formCssClass: 'dynamic-images'
});
$('#links tbody tr').formset({
prefix: '{{ links.prefix }}',
formCssClass: 'dynamic-links'
});
})
</script>
<div class="row justify-content-center">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend style="text-align:center" class="border-bottom mb-4">
Update Component
</legend>
<h5 style="text-align:center" >Data</h5>
{% include 'snippets/form.html' %}
<hr>
<h5 style="text-align:center" >Images</h5>
<table class="col col-md-12" id="images">
<tbody>
{{ images.management_form }}
{{ images.non_form_errors }}
{% for form in images.forms %}
<tr>
<td class="px-0 py-0 form-control{% if form.image.errors %} is-invalid{% else %} border-0{% endif %}">{{ form.image }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.image.non_field_errors }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.image.errors }}</td>
<td class="px-0 py-0 form-control{% if form.image.errors %} is-valid{% else %} border-0{% endif %}">{{ form.caption }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.caption.non_field_errors }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.caption.errors }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h5 style="text-align:center" >Weblinks</h5>
<table class="col col-md-12" id="links" border="0" cellpadding="0">
<tbody>
{{ links.management_form }}
{{ links.non_form_errors }}
{% for form in links.forms %}
<tr>
<td class="px-0 py-0 form-control{% if form.url.errors %} is-invalid{% else %} border-0{% endif %}">{{ form.url }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.url.errors }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.url.non_field_errors }}</td>
<td class="px-0 py-0 form-control{% if form.url.errors %} is-valid{% else %} border-0{% endif %}">{{ form.caption }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.caption.errors }}</td>
<td class="border-0 px-0 py-0 form-control" style="color:red">{{ form.caption.non_field_errors }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<button class="btn btn-primary" type="submit">
Update
</button>
<a class="btn btn-outline-secondary" href="{% if request.GET.next %}{{ request.GET.next }}{% else %}{% url 'component:components_list' %}{% endif %}">
Cancel
</a>
</fieldset>
</form>
</div>
{% endblock content %}
Please help. Thank you
Used VSCode debugger, as per a friend's suggestion. The problem was with not adding id (hidden_fields).
I added this in the update template:
{% for form in images.forms %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for form in links.forms %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
Also added the image.has_changed() to views.py to avoid accepting empty image fields.
for image in images:
if image.is_valid() and image.has_changed():
try:
image.save()
except ValueError:
pass

Queryset for current logged in user Django

I am doing queryset with my model. Now the queryset is displaying all the data in my html page. But I want to display only the logged in users data.
models.py
class Data(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Status = models.CharField(max_length=10, blank=False)
Date = models.DateField(blank=True, null=True)
views.py
#login_required
def search(request):
status_list = Data.objects.all()
status_filter = UserFilter(request.GET, queryset=status_list)
return render(request, 'users/data.html', {'filter': status_filter})
filters.py
class UserFilter(django_filters.FilterSet):
class Meta:
model = Data
fields = {
'Date': ['year','month', ], 'user': ['exact', ],
}
I tried with different views.py also but it didn't work.
#login_required
def search(request, user):
status_list = Data.objects.get(user=self.request.user).search(query)
status_filter = UserFilter(request.GET, queryset=status_list)
return render(request, 'users/data.html', {'filter': status_filter})
data.html
<!DOCTYPE html>
{% load django_tables2 %}
{% load staticfiles %}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% block content%}
<form method="get">
{{ filter.form.as_table }}
</select>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</form>
<ul>
{% for user in filter.qs %}
<li>{{ user.username }} - {{ user.get_full_name }}</li>
{% endfor %}
</ul>
<table id="datatable" style="margin-top: 20px" style="margin-
bottom:20px" class="table table-bordered" >
<thead>
<tr>
<th>user</th>
<th>EndDate</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for Data in filter.qs %}
<tr>
<td>{{ Data.user }}</td>
<td>{{ Data.EndDate }}</td>
<td>{{ Data.Status }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content%}
</body>
Above I added my HTML code also.Please look into html code also.
There could be better ways to do this. As you are still learning below code does the trick.
#login_required
def search(request, *args, **kwargs):
status_list = Data.objects.get(user=request.user)
month = request.GET.get("month", None)
year = request.GET.get("year", None)
if month:
status_list = status_list.filter(Date__month=month)
if year:
status_list = status_list.filter(Date__year=year)
return render(request, 'users/data.html', {'filter': status_list})
You can simplify your code, django provides many helpers function to help to programmer.
in your views.py you can do:
#login_required
def search(request):
status_list = Data.objects.all()
status_filter = status_list.filter(user=request.user) //get current user id
return render(request, 'users/data.html', {'filter': status_filter})
status_list = Data.objects.get(user=self.request.user)
is wrong as self is only used in class based views. No wonder it did not work.
Please try with the below code instead
status_list = Data.objects.filter(user=request.user) or
status_list = Data.objects.get(user=request.user)
So, the final code will be like
#login_required
def search(request):
status_list = Data.objects.get(user=request.user)
render(request, 'users/data.html', {'filter': status_list})
Below code should work fine.
{% for data in filter %}
<li>{{ data.user.username }} - {{ data.user.get_full_name }}</li>
{% endfor %}
{% for Data in filter %}
<tr>
<td>{{ Data.user }}</td>
<td>{{ Data.Date }}</td>
<td>{{ Data.Status }}</td>
</tr>
{% empty %}
As you would not be using filters, so filters.py should be removed.
This will also not work. Make the changes as required.
{{ filter.form.as_table }}

Flask app not displaying list as expected

I have an app that scrapes a website using beautiful soup. It returns the data in a table for me. I implemented a search bar using wtforms and a sqlite3 query.
Web page sample
This returns the data I want, but not how I want it. As soon as I submit the search it loads a list on a page instead of on the index.
the results after search
This is my flask app (part of):
#app.route('/', methods=('GET', 'POST'))
def index():
products = get_products()
form = SearchForm()
if form.validate_on_submit():
item = '%' + form.searchFor.data + '%'
c.execute("SELECT * FROM supplementInfo WHERE (name) LIKE (?)", (item,))
search_results = c.fetchall()
return str(search_results)
return render_template('index.html', products=products, form=form)
And this is the html:
<div col-12 class="wrap">
<div class="search">
<form method="POST" action="/">
{{ form.csrf_token }}
{{ form.searchFor(class_="searchTerm") }}
<button type="submit" class="searchButton">
<i class="icon-search"></i>
</button>
</form>
</div>
</div>
<div class="infoTable">
<table>
{% for row in products %}
<tr>
<td>{{ row[0] }}</td>
<td> {{ row[1] }}</td>
<td> {{ row[2] }}</td>
<td> {{ row[3] }}</td>
</tr>
{% endfor %}
</table>
</div>
</center>
<div>
<table>
{% for item in search%}
<tr>
<td>{{ item.name}}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
Ok, I figured it out. I had to change the app to read as such:
#app.route('/', methods=('GET', 'POST'))
def index():
products = get_products()
form = SearchForm()
if form.validate_on_submit():
item = '%' + form.searchFor.data + '%'
c.execute("SELECT * FROM supplementInfo WHERE (name) LIKE (?)", (item,))
search_results = c.fetchall()
return render_template('index.html', products=products, form=form, search_results=search_results)
return render_template('index.html', products=products, form=form)
I realized I was returning the list instead of returning the template and passing it the list.

Saving data from ModelForm

I am new to Django and I'm trying to save data using ModelForm. Template 'Vlozit' has a ModelForm and when submitted, I want the data saved in the DB and the redirect to base.html that actually loads the data from the DB and lists the output. The problem is that all works fine but the data is not saved. Please help me find what I am missing. Thank you.
Here's the model:
class Customer(models.Model):
Name = models.CharField(max_length=30)
Description = models.CharField(max_length=150)
Creation_Date = models.DateField(default=datetime.now)
Active = models.BooleanField(default=False)
def __unicode__(self):
return self.Name
Customers = models.Manager()
Here's the ModelForm:
class CustomerForm(forms.ModelForm):
Description = forms.CharField(widget=forms.Textarea)
class Meta:
model = Customer
Here's the view:
def vlozit(request):
if request.method == 'POST':
form = CustomerForm(request.POST, instance=Customer)
if form.is_valid():
form.save(True)
return HttpResponseRedirect(reverse('Base.html'))
else:
form = CustomerForm()
return render_to_response("Vlozit.html", {'form': form}, context_instance = RequestContext(request))
Here's the template 'Vlozit':
{% extends "base.html" %}
{% block head %}
{{ form.media }}
<script>
$(function() {
$( "#id_Creation_Date" ).datepicker();
});
</script>
{% endblock %}
{% block title %}{{block.super}} - Vlozit{% endblock %}
{% block content %}
<div id="content">
<form method="POST" action="{% url url_home %}">
{% csrf_token %}
<table>
<tr>
<td>Name</td>
<td>{{ form.Name }}</td>
</tr>
<tr>
<td>Description</td>
<td>{{ form.Description }}</td>
</tr>
<tr>
<td>Creation Date</td>
<td>{{ form.Creation_Date }}</td>
</tr>
<tr>
<td>Active</td>
<td>{{ form.Active }}</td>
</tr>
</table>
<input type="submit" value="Vlozit">
</form>
</div>
{% endblock content %}
As Timmy says in the comments, you don't catch the case where the form is not valid. Not only do you not show errors in the template, but you also don't even redisplay the template if form.is_valid() is False. Move the last line of the view back one indentation level, and add {{ form.errors }} to the template.