I try to create a Form to create new players. Opening the url works well and when i clic on submit button, i get no error but redirected to the home project.
When i check in the admin part, i can not see the data i posted in the form before. Moreover, i can not see the picture i send before in the media directory.
The database is not updated when informations are posted with forms in Django 2.1
I don't know if i set right the POST request.
Maybe a bug or i miss something?
template.py
<h1>Add a new player</h1>
{% if saved %}
<p>Player has been saved</p>
{% endif %}
<p>
<form method="post" enctype="multipart/form-data" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" />
</form>
</p>
view.py
from game.models import Scenario, Player
from .forms import ScenarioForm, NewPlayerForm
def newplayer(request):
saved = False
form = NewPlayerForm(request.POST or None, request.FILES)
if form.is_valid():
player = Player()
player.pseudo = form.cleaned_data['pseudo']
player.gender = form.cleaned_data['gender']
player.picture = form.cleaned_data['picture']
player.save()
saved = True
return render(request, 'game/newplayer.html', {
'form': form,
'saved': saved
})
model.py
class Player(models.Model):
pseudo = models.CharField(max_length=100)
GENDER_CHOICES = (
('M', 'Homme'),
('F', 'Femme'),
('O','Other'),
)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
picture = models.ImageField(upload_to="images/")
class Meta:
verbose_name = "player"
ordering = ['pseudo']
def __str__(self):
"""
Cette méthode que nous définirons dans tous les modèles
nous permettra de reconnaître facilement les différents objets que
nous traiterons plus tard dans l'administration
"""
return self.pseudo
Form.py
from django import forms
from .models import Scenario, Player
class NewPlayerForm(forms.Form):
pseudo = forms.CharField(required=True)
GENDER_CHOICES = (
('M', 'Homme'),
('F', 'Femme'),
('O', 'Other'),
)
gender = forms.ChoiceField(choices=GENDER_CHOICES, required=True)
picture = forms.ImageField()
I would put a comment but I can't do that until I have 50 reputation, but...
In your view, at the <form> element, you have action=".", which means if you submit it, that will run through the function at the current url. Is your urlpattern for newplayer() pointing to that same page? Because you said you're being redirected to your home project, but your function doesn't have a return redirect(). And the return render() you have doesn't say it goes to something like index.html, which is the typical home directory as far as I'm used to.
Mind putting your url patterns in here?
Also, because your view has a saved variable, and because of your control flow, no matter what you do, you will always get the page returning with <p>Player has been saved</p> because your current setup makes it always exist. If you did something like the following, then it would show you the update on that page properly (but I still need to see the url patterns):
views.py
def newplayer(request):
# You might have to change some of the parameters in the form object below.
# Example: I know if you made your own validation instead of django's,
# object.photo = request.FILES.get('uploadphoto', False) would get the picture fine,
# but I'm not sure about django forms.
form = NewPlayerForm(request.POST or None, request.FILES)
if request.method == 'POST' and form.is_valid():
player = Player()
player.pseudo = form.cleaned_data['pseudo']
player.gender = form.cleaned_data['gender']
player.picture = form.cleaned_data['picture']
player.save()
saved = 'Player has been saved!'
return render(request, 'success.html', {'saved': saved})
else:
return render(request, 'create_player.html', {'form': form})
template.html
{% if saved %}
<p>{{ saved }}</p>
{% else %)
<form method="post" enctype="multipart/form-data" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" />
</form>
{% endif %}
Related
I'm about to finish a Django based project, and the last step of this project is to build a followers/following feature. I can unfollow someone I've followed manually from the admin, but I can't follow someone from my html view. It misses me just one tiny thing to add into my html code but I'm really stuck. My code
My Model:
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
CREATOR = "CREATOR"
SUBSCRIBER = "SUBSCRIBER"
ROLE_CHOICES = (
(CREATOR, "Créateur"),
(SUBSCRIBER, "Abonné"),
)
profile_photo = models.ImageField(upload_to='profile_photos/', default='profile_photos/default.png', blank=True, null=True)
role = models.CharField(max_length=10, choices=ROLE_CHOICES, default=SUBSCRIBER)
follows = models.ManyToManyField('self', related_name='followers', symmetrical=False)
My Views:
#login_required
def abonnements(request):
user = request.user
followers = user.followers.all()
follows = user.follows.all()
if request.method == 'POST':
if request.POST.get('follow'):
if request.POST.get('follow') == user.username:
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows, "error": "You can't follow yourself!"})
try:
followed_user = User.objects.get(request.POST.get('follow'))
except User.DoesNotExist:
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows, "error": "User does not exist"})
else:
print(followed_user)
elif request.POST.get('unfollow'):
user.follows.remove(User.objects.get(pk=request.POST.get('unfollow')))
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows, "success": "You are no longer following " + request.POST.get('unfollow')})
return render(request, 'blog/abonnements.html', {'followers': followers, 'follows': follows})
My HTML
{% extends 'base.html' %}
<title>{% block title %}Abonnements{% endblock %}</title>
{% block content %} {% include 'partials/_navbar.html' %}
<main class="corps_abonnements">
<section class="suivre">
<p class="suivre_utilisateurs_titre">Suivre d'autres utilisateurs</p>
<form method="post">
{% csrf_token %}
<input type="text" name="follow" value="">
<input type="submit" value="Envoyer">
</form>
</section>
<section class="abonnements">
<p color="red">{{ error }}</p>
{% if success %}<p color="green">{{ success }}</p>{% endif %}
<p class="abonnements_titre">Abonnements</p>
{% for user in follows %}
<div class="utilisateur_desabonner_container">
<p class="nom_utilisateur_desabonner">{{ user.username }}</p>
<form method="post">
{% csrf_token %}
{% if user in follows %}
<input type="hidden" name="unfollow" value="{{ user.id }}">
<button style="background-color:red;" type="submit" class="creer_critique_demande">
Se désabonner
</button>
{% endif %}
</form>
</div>
{% endfor %}
</section>
<section class="abonnes">
<p class="abonnes_titre">Abonnés</p>
{% for user in followers %}
<div class="utilisateur_abonne_container">
<p class="nom_utilisateur_abonne">{{ user.username }}</p>
</div>
{% endfor %}
</section>
</main>
{% endblock %}
So when I put the connected user name in the input, it returns me the error "you can't follow yourself", it means that my code is good
the message
but If I try to put the username of another user I want to follow, it raises me an error. Can someone help me please ?
ValueError at /abonnements/
too many values to unpack (expected 2)
Request Method: POST
Request URL: http://127.0.0.1:8000/abonnements/
views.py, line 155, in abonnements
followed_user = User.objects.get(request.POST.get('follow'))
i am trying to update content with form but in my html is does not load up whenn i click on the link any idea what causing the error
my views.py
def edit_address(request, id):
address = Address.objects.filter(id=id)
form = Addressform(request.POST)
if form.is_valid():
form.user = request.user
form.save()
else:
form = Addressform()
template_name = "address_edit.html"
context = {
"form": Addressform,
"Address":Address.objects.get(id=id),
}
return render(request,template_name,context)
i think the issue is in views.py that's why i only add this file tell me if you want to see any else file
my html
<div class="card col-10">
<div class="form-group form-control-sm">
<h1 class="text-center">Edit Address</h1>
<a class='back' style="float: right;" href="{% url 'accounts:home' %}">Back to site</a> <br>
{% for Address in address %}
<form method="POST">
{% csrf_token %}
<div class="col-5">{{ form.reciever_name|as_crispy_field }}</div>
<div class="col-5">{{ form.phone_no|as_crispy_field }}</div>
<div class="col-5">{{ form.alt_phone_no|as_crispy_field }}</div>
<div class="col-5">{{ form.state|as_crispy_field }}</div>
<div class="col-5">{{ form.city|as_crispy_field }}</div>
<div class="col-5">{{ form.pincode|as_crispy_field }}</div>
<div class="col-5">{{ form.address|as_crispy_field }}</div>
<div class="col-5">{{ form.locality|as_crispy_field }}</div>
<div class="col-5">{{ form.eighteen|as_crispy_field }}</div>
<br>
<button type="submit" class="btn btn-outline-success">Add Address</button>
</form>
{% endfor %}
</div>
You need to obtain the instance of the address to edit, and pass it as instance=… to the AddressForm:
from django.shortcuts import get_object_or_404, redirect
def edit_address(request, id):
address = get_object_or_404(Address, id=id)
if request.method == 'POST':
form = Addressform(request.POST, instance=address)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('name-of-some-view')
else:
form = AddressForm(instance=address)
template_name = 'address_edit.html'
context = {
'form': form,
'Address': address,
}
return render(request, template_name, context)
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: It might be better to use the #login_required decorator
[Django-doc]
as a decorator, and thus wrap the function in it like:
from django.contrib.auth.decorators import login_required
#login_required
def edit_address(request, id):
# …
Note: You should not create a new form in case the form was not valid. A form
that is not valid will store the problems with the input in the
form.errors dictionary, and if you render the form (automatically),
it will show the errors next to the fields where these errors occur.
I want to add checkboxes in my Django form for different NGOs(say NGO1, NGO2, and so on...). I want the user to select those checkboxes and that data should be saved in the database.
Please, Suggest me the necessary changes in the code. I'm using Django 1.9.
models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfileInfo(models.Model):
user=models.OneToOneField(User)
def __str__(self):
return self.user.first_name
return self.user.last_name
return self.user.email
forms.py
from django import forms
from django.contrib.auth.models import User
from volunteer.models import UserProfileInfo
class UserForm(forms.ModelForm):
class Meta():
model = User
fields = ('email','first_name','last_name','username')
views.py
from django.shortcuts import render
from volunteer.forms import UserForm
def register(request):
registered = False
if request.method =="POST" :
user_form = UserForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
user.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserForm()
return render(request, 'volunteer/volunteer.html',
{'user_form':user_form,
'registered':registered})
admin.py
from django.contrib import admin
from volunteer.models import UserProfileInfo
# Register your models here.
admin.site.register(UserProfileInfo)
urls.py
from django.conf.urls import url
from . import views
app_name = 'volunteer'
urlpatterns = [
url(r'^', views.register, name='register'),
]
volunteer.html(which has the form)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content = "width=device-width, initial-scale=1.0">
</head>
<body>
<div class="jumbotron">
{% if registered %}
<p>Thank you <p>
{% else %}
<h1>Register yourself for Volunteering</h1>
<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
<input type="submit" name="" value="Register as a Volunteer">
{% endif %}
</div>
</form>
</body>
</html>
NOTE - I haven't included bootstrap, ajax and JQuery libraries in the above html code due to the formatting issues, I think it has nothing to do with the problem, so.
Thanks in advance!
You can easily achieve that using checkbox widget in django forms.
Define your form class as :
NGO_CHOICES = (
('one', 'ONE'),
('two', 'TWO'),
('three', 'THREE'),)
class UserForm(forms.ModelForm):
ngo = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,
choices=NGO_CHOICES)
class Meta():
model = User
fields = ('ngo', 'email','first_name','last_name','username')
Now while saving the data, you can access the data of checkbox in
if request.method =="POST" :
user_form = UserForm(data=request.POST)
if user_form.is_valid():
# getting the list of ngos
ngo = user_form.cleaned_data['ngo']
user = user_form.save()
user.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserForm()
Hope it helps.
I am learning Django and am trying to filter names based off the database table: power_id. Is there anyway to filter based off power_id, or any variable in a database? Here is what I have so far. Note, I am using Twitter-Bootstrap
This is the Team View
<div class="accordion-inner">
<ul>
{% if User.object.power_id == 1 %}
<li>
<a href="#">
{{ user }}
</a>
</li>
{% endif %}
</ul>
</div>
Lets say, 1 is an Admin.
Here is my views.py:
# Home view
class home(generic.ListView):
template_name = 'users/home.html'
context_object_name = 'User_list'
context_object_name2 = 'Power_list'
def get_queryset(self):
return User.objects.order_by('username')
# Team view
class team(generic.ListView):
template_name = 'users/team.html'
context_object_name = 'User_list'
def get_queryset(self):
return User.objects.order_by('username')
context_object_name2 = 'Power_list'
def in_catagory(User, Admin):
return things.filter(Admin=Admin)
From what I can see, you have passed in a model that you have created called User. Now, I do not know if this is a model that you have actually created or if you are using django.contrib.auth.models.User. But, this is an attempt to show you how to work with views in django.
from django.views.generic import View
from django.shortcuts import render
from .models import User
class TeamView(View):
def get(self, request):
Users = User.objects.filter(power_id='123')
return render(request, 'something.html', {'Users': Users, })
What I've done here may look intimidating, but is actually quite simple. From what I can understand, you have a bunch of users, with an property called power_id. And you want to get that, you need to filter all your users for the users with the power_id that you want.
That is what the first line after the get function call does. the get function call is here because when you send a request to a page, like www.google.com, you are sending a get request.
Now, the render function is a shortcut function. What it does is this: first parameter is always request, the second parameter is the html file that you want it to render, and the third parameter is the information you are sending which is a dictionary.
Now coming to your template. You can simply loop through all your users, like so:
<div class="accordion-inner">
<ul>
{% for user in Users %}
<li>
<a href="#">
{{ user }}
</a>
</li>
{% endfor %}
</ul>
</div>
You can override the get_context_data method to add that other variable.
class TeamView(ListView):
template_name = 'users/team.html'
context_object_name = 'User_list'
model = User # You never set the model
def get_queryset(self):
return super('TeamView', self).get_queryset().order_by('username') # call the parent function
def get_context_data(self, *args, **kwargs):
context = super('TeamView', self).get_context_data(*args, **kwargs)
context['Power_list'] = self.get_queryset().filter(power_id=1)
return context
Now you also have a context variable Power_list with all of the users that have power_id == 1 that you can iterate over
<div class="accordion-inner">
<ul>
{% for user in Power_list %}
<li>
<a href="#">
{{ user }}
</a>
</li>
{% endfor %}
</ul>
</div>
I have found the answer to my own question. Turns out, it was much simpler than I thought it was. What I needed was to re-arrange the code, along with getting variables right.
<div class="accordion-inner">
<ul>
{% for name in User_list %}
{% if name.power_id == 1 %}
{{ name }}<br />
{% endif %}
{% endfor %}
</ul>
</div>
The views.py file didn't need to be edited at all.
I am trying to add uploading images feature.
This class saves new entity:
class NewPost(Handler):
def render_newpost(self, title='' , content='', error = ''):
self.render("newpost.html", title = title, content = content, error = error)
def get(self):
user_cookie = self.request.cookies.get('user')
if user_cookie:
user_id = user_cookie.split('|')[0]
if hash_str(user_id) == user_cookie.split('|')[1]:
user = Users.get_by_id(int(user_id))
self.render_newpost()
else:
self.redirect('/')
def post(self):
title = self.request.get("title")
content = self.request.get("content")
image = self.request.get("file")
if title and content:
p = Posts(title = title, content = content)
p.image=db.Blob(image)
p.put()
self.redirect("/")
else:
error = "Enter both title and text"
self.render_newpost(title, content, error)
Here is my front page render class:
class Main(Handler):
def get(self):
posts = db.GqlQuery("SELECT * FROM Posts Order by created DESC LIMIT 10")
user_cookie = self.request.cookies.get('user')
if user_cookie:
user_id = user_cookie.split('|')[0]
if hash_str(user_id) == user_cookie.split('|')[1]:
user = Users.get_by_id(int(user_id))
self.render("front.html", posts = posts, user=user)
else:
self.response.headers['Content-Type'] = "image/jpeg"
self.render("front.html", posts = posts)
form to enter data:
<form method="post" enctype="multipart/form-data">
<div class="newpost">
<label>Image:</label>
<input type="file" name="file"/>
<div class="label">Title:
<input type="text" name="title" value="{{title}}"/>
</div>
<hr>
<div class="label">Content:
<textarea name="content">{{content}}</textarea>
</div>
</div>
<input type="submit"/>
<div class="error">{{error}}</div>
</form>
and here is my home page template: (The problem appears here!)
{% for post in posts %}
{% if post.image %}
<li><img src="/static/images/{{post.image}}"/>
{% endif %}
<h4>{{post.title}}</h4>
<p class="zoom">{{post.content}}</p>
{% endfor %}
App successfully stores image, but when it returns to the front page trying to render image it gives this error:
File "/home/wanhrust/google_appengine/newsite/templates/front.html", line 54, in top-level template code
{{post.image}}
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)
I've been googling for several hours but without results. Any help?
The problem is that you are trying to embed an image in an html document which is not possible. Post.image is storing the bytes representing the image.
If you want to include the image in your html, you need to add something like this
{% if post.image_id %}
<li><img src="/image/{{post.image_id}}" />
{% endif %}
Where /image/ is a handler that returns the content of the image (setting the apprpriate content-type).
I also would recommend you to use the Blobstore API.