I'm new to Django and at this point , I set up a very simple post article page, I hope that when I successfully save the article, it will show the message of the bootstrap modal style.
model.py
from django.db import models
from django.utils import timezone
class Article(models.Model):
title = models.CharField(max_length=100,blank=False,null=False)
slug = models.SlugField()
content = models.TextField()
cuser = models.CharField(max_length=100)
cdate = models.DateField(auto_now_add=True)
mdate = models.DateField(auto_now=True)
forms.py
from .models import Article
from django.forms import ModelForm
class ArticleModelForm(ModelForm):
class Meta:
model = Article
fields = [
'title',
'content',
]
views.py
from django.shortcuts import render
from .forms import ArticleModelForm
from django.contrib.auth.decorators import login_required
from .models import Article
#login_required
def create_view(request):
form = ArticleModelForm(request.POST or None)
context={
'form':form
}
if form.is_valid():
article_obj = Article(cuser=request.user)
form = ArticleModelForm(request.POST,instance=article_obj)
form.save()
context['saved']=True
context['form']=ArticleModelForm()
return render(request,'article/create.html',context= context)
my template > article/create.html
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<div><button data-bs-toggle="modal" data-bs-target="#saveModal" type="submit">create</button></div>
</form>
{% if saved %}
<div class="modal fade" id="saveModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3>save successfully!</h3>
<button type="button" class="btn-close" data-bs-dismiss="modal">
</button>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock content %}
I use the saved variable in views.py to determine whether the content of the article has been successfully saved, and if so, set it in the context
In the template if saved exists, the modal related code will be presented, but this way
unsuccessful.
The problem is with modal itself, whenever you are submitting the form the form gets submitted but when it comes with saved=True then also there is a need for clicking the button of modal to display the message saved successfully which is not possible. So the other alternative is to use alert classes of boostrap (you are free to apply your own styling to it but below is just an example), so try this template:
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<div><button type="submit">create</button></div>
</form>
{% if saved %}
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Saved successfully.</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
You should maintain separate conditions for GET and POST request and also do re-render the template with saved=True so try this view:
#login_required
def create_view(request):
if request.method == "POST":
article_obj = Article(cuser=request.user)
form = ArticleModelForm(request.POST, instance=article_obj)
if form.is_valid():
form.save()
context = {
"form": ArticleModelForm(),
"saved": "yes"
}
return render(request, "article/create.html", context)
else:
print("form is not valid")
else: # GET method
form = ArticleModelForm()
return render(request, 'article/create.html', {"form": form})
Related
So the goal is to get the user to upload images inside the application, and for the images to be displayed on the screen.
The problem is that the forms will not save to the models I made. I am following Django Central https://djangocentral.com/uploading-images-with-django/ for guidance for uploading my images.
What I have at the moment is where the user can type inside the form for their caption and where the user can select a file for their image, but nothing happens when they click the upload button. All that happens, is that it redirects me to the homepage for some reason, but I can fix that later. The only way for the images to be displayed on the website is if I manually go into the admin panel and upload the image there. If anyone could help I would much appreciate it.
view.py
def profile(request):
if request.method == "POST":
form = User_Profile_Form(data = request.POST, files = request.FILES)
if form.is_valid():
form.save()
obj = form.instance
return render(request, "main/profile.html", {"obj":obj})
else:
form = User_Profile_Form()
img = User_Profile.objects.all()
return render(request,"main/profile.html", {"img":img, "form":form})
models.py
class User_Profile(models.Model):
caption = models.CharField(max_length = 100)
image = models.ImageField(upload_to = "img/%y", blank=True)
def __str__(self):
return self.caption
forms.py
from django import forms
from .models import User_Profile
class User_Profile_Form(forms.ModelForm):
class Meta:
model = User_Profile
fields = ("caption", "image")
profile.html
<div class="container">
<form action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<button type="submit" class="btn btn-lg btn-success">Upload</button>
</form>
{% if obj %}
<h3>Succesfully uploaded : {{img_obj.caption}}</h3>
<img src="{{ obj.image.url}}" alt="image" class="img-thumbnail" >
{% endif %}
<hr>
{% for x in img %}
{% if forloop.first %}<div class="row ">{% endif %}
<div class="col-lg-4 col-md-4 col-12" >
<div class="text-center mt-2">
<img src="{{x.image.url}}" height="70%" width="70%" class="img-thumbnail" alt="...">
<h2 class="text-center" >{{x.caption}}</h2></div>
</div>
{% if forloop.counter|divisibleby:3 %}
</div>
<div class=row>{% endif %}
{% if forloop.last %}</div>{% endif %}
{% endfor %}
</div>
In the template change the action:
from:
<form action="." method="post" enctype="multipart/form-data">
To:
<form action="" method="post" enctype="multipart/form-data">
. redirects you to the home page.
in views.py
def profile(request):
if request.method == "POST":
form = User_Profile_Form(data = request.POST, files = request.FILES)
if form.is_valid():
form.save()
obj = form.instance
return render(request, "main/profile.html", {"obj":obj, "form":form})
else:
form = User_Profile_Form()
img = User_Profile.objects.all()
return render(request,"main/profile.html", {"img":img, "form":form})
i know what you want to do, i did it on my project, here is my code, edited for your self
views.py
pimageupdate = ProfileImageUpdate(request.POST,request.FILES, instance=request.user.userprofile)
if pimageupdate.is_valid():
pimageupdate.save()
should i note that pimageupdate is getting the form from forms.py
and you should add user in your {{}} code like this
{{user.userprofile.default_profile_picture}}
change "post" in your form tag to "POST"
hope this work, let me know if you tried them
if there's anyone who knows how can I delete images user, I made a code to do that but I cannot continue I get some stuck. so if anyone could tell me which way can I make it this method?
also, I need to know about the outputs of (userprofile) in (delete_avatar) if this code is true how can I know it? I tried using print and repr but I didn't find this useful. so, anybody can get me help?
views.py
# Update Avatar
#login_required
def add_avatar(request, user_id):
my_logo = request.user.userprofile
form = AddAvatar(instance=my_logo)
get_userid = UserProfile.objects.filter(user_id=user_id)
context = {'form': form, 'get_userid': get_userid}
if request.method == 'POST':
form = AddAvatar(request.POST, request.FILES, instance=my_logo)
if form.is_valid():
form.save()
return redirect('account:view_profile')
return render(request, 'account/change-image.html', context)
# Remove Avatar
#login_required
def delete_avatar(request, user_id):
my_request = request.POST.get('rm-img')
userprofile = UserProfile(my_request)
pdb.set_trace()
if request.method == "POST":
del_img = UserProfile.objects.get(user_id=user_id).logo.delete() # delete object
return redirect('account:view_profile')
return render(request, 'account/change-image.html')
change-image.html
{% extends 'base.html' %}
{% block title %} Add New Image {% endblock %}
{% block body %}
<!-- Add new image for user-profile -->
<div class="change-image">
<div class="add-image">
<div class="container">
<h1>This Image Is Current, <br>Choose Your Image From Your Personal Computer Or Delete</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<label>{{ user.first_name }} {{ user.last_name }}</label>
{{ form.as_p }}
<button type="submit" class="btn btn-success">Change Now</button>
<input type="submit" name="rm-img" class="btn btn-danger" value="Remove Image">
</form>
</div>
</div>
</div>
{% endblock %}
the file html above where I can make a form to update and delete the user image
urls.py
urlpatterns = [
path('new-image/<int:user_id>/', views.add_avatar, name="add_avatar"),
path('del-image/', views.delete_avatar, name="delete_avatar"),
]
forms.py
class AddAvatar(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['logo']
I am relatively new to django and i'm trying to implement some modelforms.
My page consists of two views, a Politics section and a Sports section, each one with the same form for making comments (my comment model is named Comentario). It has a field for the content and a field for the section the comment belongs to. Both views are basically the same so I'm going to showcase just the politics one:
from django.contrib import messages
from django.shortcuts import render
from django.views.generic import CreateView
from usuarios.models import Usuario
from .forms import CrearComentario
from .models import Comentario
usuarios = Usuario.objects.all()
comentarios = Comentario.objects.all()
pag = ''
def politics(request):
if request.user.is_authenticated:
if request.method == 'POST':
form = CrearComentario(request.POST, instance=request.user)
if form.is_valid():
messages.success(request, 'Publicado!')
pag = 'politics'
form.save()
form = CrearComentario()
else:
form = CrearComentario(request.POST,instance=request.user)
else:
messages.warning(request, 'Comentario no válido')
form = CrearComentario(request.POST)
return render(request, 'main/politics.html', {'usuarios': usuarios,
'comentarios': comentarios,
'form': form})
In case you're wondering, 'pag' is a control variable that is checked by my signals.py file to update the 'pagina' field
I had trouble with the submit buttons in my custom modelsforms, the form displays correctly, and when I write something in the form and submit it, it displays a success message but the comment doesn't appear in the comment section and it doesn't appear in the django shell either.
politics.html
{% extends 'main/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
<!-- Here would be the content-->
{% block comentarios %}
<h3>Comentarios</h3>
<ul class="a">
{% for comment in comentarios %}
{% if comment.pagina == 'politics' %}
<li>
<span>{{ comment.contenido }}</span>
<br>
<small>{{ comment.usuario }} , {{ comment.fecha }}</small>
<hr>
<br>
</li>
{% endif %}
{% endfor %}
</ul>
{% if user.is_authenticated %}
<form method="POST" enctype="multipart/form-data" action="http://localhost:8000/main/politics/">
{% csrf_token %}
<fieldset class="form-group">
<legend>Dejanos tu opinion</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">OK</button>
</div>
</form>
{% else %}
<legend>Inicia sesión para poner comentarios</legend>
{% endif %}
{% endblock %}
My forms.py looks like this:
from django import forms
from .models import Comentario
class CrearComentario(forms.ModelForm):
contenido = forms.CharField(max_length = 250, required=False, widget=forms.Textarea)
pagina = forms.CharField(max_length = 250, required=False, widget=forms.HiddenInput())
class Meta:
model = Comentario
fields = ['contenido', 'pagina']
The field that determines to which section the comment belongs to ('pagina') is hidden because it's meant to be set by my signals.py file:
from django.db.models.signals import pre_save
from django.dispatch import receiver
from .models import Comentario
from .views import pag
from .forms import CrearComentario
#receiver(pre_save, sender=Comentario)
def fijar_pagina(sender, instance, **kwargs)
if pag:
instance.pagina = pag
pag = ''
instance.save(update_fields['pagina'])
I'm not getting any error message, and everything behaves like it should except for the fact that comments aren't being saved
I tried too a commit==False save instead of the signals but it was just as ineffective:
def politics(request):
if request.user.is_authenticated:
if request.method == 'POST':
form = CrearComentario(request.POST, instance=request.user)
if form.is_valid():
messages.success(request, 'Publicado!')
pag = 'politics'
comentario = form.save(commit=False)
comentario.pagina = 'sonsol'
comentario.save()
form = CrearComentario()
else:
form = CrearComentario(request.POST,instance=request.user)
else:
messages.warning(request, 'Comentario no válido)
form = CrearComentario(request.POST)
return render(request, 'main/politics.html', {'usuarios': usuarios,
'comentarios': comentarios,
'form': form})
usuarios and comentarios have both been defined at the module (file) level. As such they will not update for the lifetime of the process.
You should move both of these into the view body so that the query is run on every request
usuarios = Usuario.objects.all()
comentarios = Comentario.objects.all()
return render(request, 'main/politics.html', {'usuarios': usuarios,
'comentarios': comentarios,
'form': form})
I have hard time with such a easy thing (I guess).
My aim is to create two subpages with 2 different forms yet connected with the same user model:
/account/register.html - page only to manage registration (create user with login,email,password)
/account/questionnaire.html - page for UPDATING the same user information such as age,weight,height etc.
I've got 'POST' communicates in server log but nothing appears when I'm checking up django admin site.
models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
age = models.PositiveIntegerField(blank=False)
weight = models.PositiveIntegerField(blank=False)
height = models.PositiveIntegerField(blank=False)
forms.py
from django import forms
from django.core import validators
from django.contrib.auth.models import User
from account.models import UserProfile
class RegisterUserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ('username','email','password')
class RegisterUserInfoForm(forms.ModelForm):
class Meta():
model = UserProfile
fields = ('age','weight','height')
views.py
from django.shortcuts import render
from account.forms import RegisterUserForm, RegisterUserInfoForm
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from django.contrib.auth.decorators import login_required
def register(request):
registered = False
if request.method == 'POST':
user_form = RegisterUserForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.set_password(user.password)
user.save()
registered = True
else:
print(user_form.errors)
else:
user_form = RegisterUserForm()
return render(request,'account/register.html',{
'user_form':user_form,
'registered':registered,
})
#login_required
def questionnaire(request):
if request.method == 'POST':
profile_form = RegisterUserInfoForm(request.POST, instance=request.user)
if profile_form.is_valid():
profile_form.save()
else:
print(profile_form.errors)
else:
profile_form = RegisterUserInfoForm(instance=request.user)
return render(request,'account/questionnaire.html',{
'profile_form':profile_form,
})
register.html
{% extends 'base.html' %}
{% block body_block %}
<div class="container">
<h1>Register</h1>
<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
<input type="submit" name="btn btn-primary" value="Save">
</form>
</div>
{% endblock %}
questionnaire.html
{% extends 'base.html' %}
{% block body_block %}
<div class="container">
<h1>questionnaire</h1>
<form method="post">
{% csrf_token %}
{{ profile_form.as_p }}
<input type="submit" name="" value="Save">
</form>
</div>
{% endblock %}
Your view doesn't receive a POST request because you didn't provide an action attribute to your form tag. So, your form passes your POST request nowhere. Try it like this:
<form action="" method="post">
{% csrf_token %}
{{ user_form.as_p }}
<input type="submit" name="btn btn-primary" value="Save">
</form>
Also, you should definitely check django's built-in generic views: CreateView and UpdateView. They serve exactly for such purposes and makes almost everything for you.
I am following the documentation of the Django Forms but I do not know why my form does not want to show up !
I am creating a form that will get an email en create invitation for user to sign in using this app :https://github.com/bee-keeper/django-invitations
My forms.py:
class InviteForm(forms.Form):
email1 = forms.EmailField(label='Email 1')
My Views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import InviteForm
class candidateIndex(TemplateView):
template_name= 'candidateIndex.html'
class HRIndex(TemplateView):
template_name= 'HRindex.html'
def create_invite(request):
if request.method == 'POST':
form = InviteForm(request.POST)
if form.is_valid:
email = form.cleaned_data['email1']
invite = Invitation.create('form.email1')
invite.send_invitation(request)
print("The mail was went")
else:
print("Your form is not valid")
else:
form = InviteForm()
return render(request, 'HRindex.html', {'form': form})
My HTML:
{% extends 'base.html' %}
{% block body %}
<div class="jumbotron">
<h1>Welcome to SoftScores.com</h1>
<h2>Team analytics platfom</h2>
<h3>Welcome to {{user.username}}, it is your Page</h3>
</div>
<div class="container">
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Create a new team
</a>
</p>
<div class="collapse" id="collapseExample">
<div class="card card-body">
In order to create a new team please invite new members. A link will be sent to them in order to give the access to the application
</div>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</div>
</div>
urls.py:
from django.conf.urls import url
from website import views
app_name = 'website'
urlpatterns = [
url(r'^candidateIndex/$', views.candidateIndex.as_view(), name='candidate_index'),
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
]
When it render the page I get only the button but the form does not seems to work
Do you habe any idea ?
You HR_index url is being handled by the HRIndex view, but this does not have any code to handle the form.
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
Since a TemplateView is not really suited to handling a form, it would be better to modify the URL pattern to use the create_invite view instead:
url(r'^HRIndex/$', views.create_invite, name='HR_index'),