forms.py
class ImageCreateForm(forms.ModelForm):
class Meta:
model = Image
fields = {'title', 'url', 'description'}
widgets = {
'url':forms.HiddenInput,
}
def clean_url(self):
url = self.cleaned_data['url']
valid_extensions = ['jpg', 'jpeg']
#The two below codes do exactly the same thing but partition is faster
extention = url.rpartition('.')[2].lower()
#extension = url.rsplit('.',1)[1].lower()
if extension not in valid_extensions:
raise forms.ValidationError('The given URL does not match valid image extensions')
return url
def save(self, force_insert=False,force_update=False,commit=True):
image = super(ImageCreateForm, self).save(commit=False)
image_url = self.cleaned_data['url']
image_name = '{}.{}'.format(slugify(image.title), image_url.rpartition('.')[2].lower())
#download image from the given URL
response = request.urlopen(image_url)
image.image.save(image_name,ContentFile(response.read()),save=False)
if commit:
image.save()
return image
The image appears alright but the fields are not showing
index.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}Bookmark an image{% endblock %}
{% block content %}
<h1>Bookmark an image</h1>
<img src="{{ request.GET.url }}" class="image-preview">
<form action="." method="post">
{{ forms.as_p }}
{% csrf_token %}
<input type="submit" value= 'Bookmark it!'>
</form>
{% endblock %}
change your form to this
you pass the fields in list and not set type {}
class ImageCreateForm(forms.ModelForm):
class Meta:
model = Image
fields = ['title', 'url', 'description']
widgets = {
'url':forms.HiddenInput,
}
in your views
def image_create(request):
if request.method == 'POST':
#form is sent
form = ImageCreateForm(request.POST)
if form.is_valid():
#form data is valid
cd = form.cleaned_data
new_item = form.save(commit=False)
#assign current user to the item
new_item.user = request.user
new_item.save()
messages.success(request, 'Image added successfully')
#redirect to new created item detail view
return redirect(new_item.get_absolut_url())
else:
#build form with data provided by the bookmarklet via GET
form = ImageCreateForm()
return render(request, 'images/image/index.html',{'section':'images', 'form':form})
and in html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}Bookmark an image{% endblock %}
{% block content %}
<h1>Bookmark an image</h1>
<img src="{{ request.GET.url }}" class="image-preview">
<form action="." method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="submit" value= 'Bookmark it!'>
</form>
{% endblock %}
Although it does not look like it, make sure that the if request.method and its related else are on the same level. I sometimes get the else indented to match the if form.is_valid level.
Related
After displaying my posts, I don't manage to Edit any of them.
When I print the instance variable which is in views.py in my terminal, it displays only the title and the author like this title - author, which is the method defined in models.py.
Help please!
Views.py
#login_required(login_url='login_view')
def update_post_view(request, post_id, slug=None):
instance = Article.objects.get(id = post_id)
if request.method == 'POST':
form = UpdatePostForm(request.POST, request.FILES, instance=instance)
if form.is_valid():
form.save()
return redirect('posts_view')
else:
form = UpdatePostForm(instance=instance)
return render(request,'update_post.html', {'form':form})
forms.py
class UpdatePostForm(forms.ModelForm):
class Meta:
model = Article
fields = ('author',)
title = forms.CharField(max_length=255, label='username',
widget= forms.TextInput(attrs= {'placeholder':'Title...', 'class': 'title'}))
body = forms.CharField(max_length=255, label='body', required=True, widget=forms.Textarea(attrs={'placeholder':'Start writing your post...'}))
urls.py
path('update_post/<int:post_id>/<slug:slug>', views.update_post_view, name='update_post_view')
update_post.html
{% extends 'base.html' %}
{% block title %}Update Post{% endblock %}
{% block content %}
<h2>Update Posts...</h2>
<form action="" method="POST">
{% csrf_token %}
<div>
<h3>{{form.title}}</h3>
<small>{{form.author}}</small>
<p>{{form.body}}</p>
</div>
<button class="btn btn-secondary">Update</button>
</form>
{% endblock %}
I've been trying to debug this issue for a day together with my expert coder but we were unable to identify the issue here. The like button works perfectly all right and I am able to query the total likes, but the Clap button does not change to unlike and we are unsure why. I believe the error lies in either the html line:
{% if liked and post.slug == blog_post.slug %} Unlike {% else %} Like {% endif %}
or the django line:
context["liked"] = True if blog_post.likes.filter(id=request.user.id).exists() else False
Big thanks if you can identify the issue here!
views.py
def home_feed_view(request, *args, **kwargs):
context = {}
blog_posts = BlogPost.objects.all()
context['blog_posts'] = blog_posts
if request.method=="POST":
slug=request.POST["submit_slug"]
blog_post = get_object_or_404(BlogPost, slug=slug)
context['blog_post'] = blog_post
context["liked"] = True if blog_post.likes.filter(id=request.user.id).exists() else False
context['total_likes'] = blog_post.total_likes()
type_of_post = TypeofPostFilter(request.GET, queryset=BlogPost.objects.all())
context['type_of_post'] = type_of_post
paginated_type_of_post = Paginator(type_of_post.qs, 13 )
page = request.GET.get('page')
post_page_obj = paginated_type_of_post.get_page(page)
context['post_page_obj'] = post_page_obj
return render(request, "HomeFeed/snippets/home.html", context)
def LikeView(request, slug):
context = {}
user = request.user
if not user.is_authenticated:
return redirect('must_authenticate')
post = get_object_or_404(BlogPost, slug=slug)
liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
return redirect(request.META.get('HTTP_REFERER', ''))
<td class="table-primary">
<form action="{% url 'HomeFeed:like_post' post.slug %}" method="POST">
{% csrf_token %}
<button type="submit" name="submit_slug" value="{{ post.slug }}" class='btn btn-primary btn-sm'>
{% if liked and post.slug == blog_post.slug %} Unlike {% else %} Like
{% endif %}
</button>
{{ post.total_likes }} Clap {{ post.total_likes|pluralize }}
</form>
</td>
urls.py
path('<slug>/like/', LikeView, name='like_post'),
models.py
class BlogPost(models.Model):
chief_title = models.CharField(max_length=50, null=False, blank=False)
body = models.TextField(max_length=5000, null=False, blank=False)
likes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='blog_posts', blank=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(blank=True, unique=True)
Ok so here's a much simpler way to perform a check if a model exist in a m2m field in another model:
html
{% if request.user in blog_post.likes.all %} Unlike {% else %} Like {% endif %}
view
if request.user in blog_post.likes.all():
P.S. In your model you should rename the field likes to likers since its a relation with a User model not a Like model :)
EDIT
So, to easily display a list of posts and their like buttons accordingly on a single page you wanna do this in your template:
views.py
def posts(request):
blog_posts = BlogPost.objects.all()
return render(request, 'index.html', {'blog_posts': blog_posts})
index.html
{% for post in blog_posts %}
<h1>{{ post.chief_title }}</h1>
<p>{{ post.author }} says: </p>
<b>{{ post.body }}</b>
<p> This post is liked by: </p>
{% for user in post.likes %}
<p>{{ user.username }}</p>
{% endfor %}
{% if request.user not in post.likes.all %}
Like
{% else %}
Unlike
{% endif %}
{% endfor %}
I'm making a search bar in Django using Class-Based Views on my Views.py. When I try to get the value submitted in the input it's not showing the query name and if I don't submit anything is NOT giving me an error. Also what is the way to get the post showed by the world searched? Thanks for all. My code is:
Models.py:
class Post(models.Model): # Post core
title = models.CharField(max_length=299)
author = models.ForeignKey(User,default=ANONYMOUS_USER_ID, on_delete=models.CASCADE)
category = models.CharField(max_length=50)
image = models.ImageField(blank=True)
desc = models.TextField()
text = RichTextField(blank = True, null = True )
date = models.DateTimeField(auto_now=False, auto_now_add=True)
slug = models.SlugField(null = True, blank = True, unique=True)
class Meta: # Order post by date
ordering = ['-date',]
def __str__(self): # Display title
return self.title
def get_absolute_url(self): # #TODO da cambiare
return reverse("listpost")
Views.py:
class SearchView(TemplateView):
model = Post
template_name = "admin/search.html"
def get(self, request, *args, **kwargs):
q = request.GET.get('q', '')
self.results = Post.objects.filter(text__icontains=q, desc__icontains = q, title__icontains = q)
return super().get(request, *args, **kwargs)
Urls.py:
path('dashboard/listpost/search/', SearchView.as_view(), name="search")
ListPost.html:
{% extends "admin/layout.html" %}
{% block title %}
<title>Post List</title>
{% endblock title %}
{% block content %}
<form action="{% url 'search' %}" method="GET">
<input type="text" placeholder="Cerca" name="search"> <button>Cerca</button>
</form>
<div class="postlist">
<div class="cards"> <!-- Card Container -->
{% for post in object_list %}
<div class="card"> <!-- Single Card -->
{% if post.image %}
<img src="{{post.image.url}}" alt="">
{% endif %}
<h3>{{ post.title }}</h3>
<p>
{{ post.category }}
{{ post.author }}
<data class="data"> {{ post.date|date:'d-m-Y' }} </data>
</p>
<p class="desc-list">{{ post.desc|truncatewords:10 }}</p>
edit
delate
</div>
{% endfor %}
</div>
</div>
{% endblock content %}
Search.html
{% extends "admin/layout.html" %}
{% block title %}
<title>Search</title>
{% endblock title %}
{% block content %}
{% if query %}
{{Query}}
{% else %}
<p>Nope</p>
{% endif %}
{% endblock content %}
Your are trying to display the variable query, Query (two different variables since the template language is case sensitive).
Your do not pass any of those two variables in the template context.
I don't see any query nor Query variable in your view.
It seems that your want to show the results variable, so I will assume this.
Your need to send the results from your queryset in the template results.
The get_context_data method ContextMixin (one of the TemplateView derived classes) is useful for this.
class SearchView(TemplateView):
model = Post
template_name = "admin/search.html"
def get(self, request, *args, **kwargs):
q = request.GET.get('q', '')
self.results = Post.objects.filter(text__icontains=q, desc__icontains = q, title__icontains = q)
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
"""Add context to the template"""
return super().get_context_data(results=results, **kwargs)
And in your template:
{% extends "admin/layout.html" %}
{% block title %}
<title>Search</title>
{% endblock title %}
{% block content %}
{% if results.exists %}
{% for result in results %}
{{ result }}
{% endfor %}
{% else %}
<p>Nope</p>
{% endif %}
{% endblock content %}
Iam trying to get a records which works, but it just does not want to update the record...
----forms.py----
class acroniform(forms.ModelForm):
def clean_key(self):
Key = self.cleaned_data['Key']
if Acronis.objects.filter(id_iexact=Key).exists():
raise forms.ValidationError('Dieser Key ist bereits vergeben')
return Key
class Meta:
model = Acronis
fields = ('KN', 'Key', 'Release')
labels = {
'KN': 'Kundennummer',
'Key': 'Key',
'Release': 'Release',
}
----urls.py----
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('EditAcronis/<int:id>', views.edit_acronis, name='edit_acronis'),
]
----Views.py----
#login_required()
def edit_acronis(request, id=None):
item = get_object_or_404(Acronis, id=id)
acroniform_form = acroniform(request.POST or None, instance=item)
if acroniform_form.is_valid():
item = acroniform_form.save(commit=False)
item.save(force_update=True)
return redirect('/Verwaltung/Acronis')
else:
form = acroniform(instance=item)
return render(request, 'blog/editacronis.html', {'acroniform_form': acroniform_form})
----editacronis.html----
{% extends 'blog/base.html' %}
{% load bootstrap4 %}
<html lang="en">
<meta charset="UTF-8">
<title>{% block supertitle %} Home {% endblock %}</title>
{% block Content %}
<P></P>
<form class="form-inline, form-row" action="{% url 'blog:acr' %}" method="post">
{% csrf_token %}
{% bootstrap_form acroniform_form %}
<button type="submit" class="btn btn-success">Update</button>
</form>
<p>Acronis</p>
<P></P>
{% endblock %}
What's wrong with my code?
item.save() is not saving or updating the databaserecord...
{% extends 'blog/base.html' %}
{% load bootstrap4 %}
<html lang="en">
<meta charset="UTF-8">
<title>{% block supertitle %} Home {% endblock %}</title>
{% block Content %}
<P></P>
<form class="form-inline, form-row" action="" method="post">
{% csrf_token %}
{% bootstrap_form acroniform_form %}
<button type="submit" class="btn btn-success">Update</button>
</form>
<p>Acronis</p>
<P></P>
{% endblock %}
Try this.
class acroniform(forms.ModelForm):
def clean_key(self):
Key = self.cleaned_data['Key']
if Acronis.objects.filter(key_iexact=Key).exists():
raise forms.ValidationError('Dieser Key ist bereits vergeben')
return Key
class Meta:
model = Acronis
fields = ('KN', 'Key', 'Release')
labels = {
'KN': 'Kundennummer',
'Key': 'Key',
'Release': 'Release',
}
#login_required()
def edit_acronis(request, id):
item = get_object_or_404(Acronis, id=id)
form = acroniform(request.POST or None, instance=item)
if form.is_valid():
form.save()
return redirect('/Verwaltung/Acronis')
else:
form = acroniform(instance=item)
return render(request, 'blog/editacronis.html', {'acroniform_form': acroniform_form})
or
#login_required()
def edit_acronis(request, id):
item = get_object_or_404(Acronis, id=id)
form = acroniform(request.POST, instance=item)
if form.is_valid():
form = acroniform.save(commit=True)
form.save()
return redirect('/Verwaltung/Acronis')
else:
form = acroniform(instance=item)
return render(request, 'blog/editacronis.html', {'acroniform_form': acroniform_form})
I am getting an error with a view that i have and i was wondering if anyone can help me figure out where it is coming from. I am pretty sure it is something small that I am not seeing where it is coming from...
Within the view there will be a form that is displayed for the user to input informaiton, once the form is submitted, it is processed and then redirect to the users home...
Here is the error:
ValueError at /transfer/
The view tab.views.transfers didn't return an HttpResponse object. It returned None instead.
Request Method: POST
Request URL: http://localhost:8000/transfer/
Django Version: 1.8.6
Exception Type: ValueError
Exception Value:
The view tab.views.transfers didn't return an HttpResponse object. It returned None instead.
Here is the views.py
def transfers(request):
if 'username' not in request.session:
return redirect('login')
else:
username = request.session['username']
currentUser = User.objects.get(username = username)
if request.method == 'POST':
form = TransferForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
from_acct = cd['from_acct']
to_acct = cd['to_acct']
amount = cd['amount']
memo = cd['memo']
new_transfer = Transfers.objects.create(
user = currentUser,
from_acct = from_acct,
to_acct = to_acct,
amount = amount,
memo = memo,
frequency = 1,
status = 1,
)
return redirect('home_page')
else:
form = TransferForm()
form.fields['from_acct'].queryset = Accounts.objects.filter(user = currentUser).all()
message = 'please fill out the below form'
parameters = {
'form':form,
'currentUser':currentUser,
'message':message,
}
return render(request, 'tabs/user_balance.html', parameters)
Here is the html file:
{% extends "base.html" %}
{% block content %}
<h1>Transfer Money</h1>
{% if message %}
<p>{{message}}</p>
{% endif %}
<form action="." method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit" value="submit">
</form>
{% endblock %}
Here is the forms.py file portion
class TransferForm(forms.ModelForm):
acct_choices = (('tabz', 'Tabz - Username'),
('Wells Fargo', 'Wells Fargo - Username'))
from_acct = forms.TypedChoiceField(
choices=acct_choices, widget=forms.RadioSelect, coerce=int
)
to_acct = forms.TypedChoiceField(
choices=acct_choices, widget=forms.RadioSelect, coerce=int
)
class Meta:
model = Transfers
fields = ['from_acct', 'to_acct', 'amount', 'memo']
labels = {
'from_acct':'from',
'to_acct':'to',
}
from django.http import HttpResponse, HttpResponseRedirect
if request.method == 'POST':
form = TransferForm(request.POST)
if form.is_valid():
...
return HttpResponseRedirect(reverse_lazy('home'))
else:
form.fields['from_acct'].queryset = Accounts.objects.filter(user = currentUser).all()
message = 'please fill out the below form'
parameters = {
'form':form,
'currentUser':currentUser,
'message':message,
}
return render(request, 'tabs/user_balance.html', parameters)
html add form.errors
{% extends "base.html" %}
{% block content %}
<h1>Transfer Money</h1>
{% if message %}
<p>{{message}}</p>
{% endif %}
<form action='your_url/' method="POST">
{% csrf_token %}
{{ field.errors }}
{{ form.as_p }}
<input type="submit" name="submit" value="submit">
</form>
{% endblock %}
Well, this error should be thrown simply because you are giving an invalid form to your view. If you look at the logic of the view, if it is a POST and form is not valid the view does not return anything... well None for python. That's the error you are getting right?
Try to put an else statement with return after return redirect('home_page') and see if this fixes this part.