UnicodeDecodeError. While rendering the blob image - google-app-engine

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.

Related

Having a following followers problem in Django "too many values.."

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'))

how to Update/Edit database content with form in django

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.

Forms do not create new entry in database with Django

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 %}

FieldError at /cart/checkout/

Exception Value:
Cannot resolve keyword 'active' into field.
Choices are: billing_profile, billing_profile_id, brand, country, default, exp_month, exp_year, id, last4, stripe_id.
When i click on checkout button it show me that error.i already have a lot of models which are related to each other,i check all of them but i did not got any error so can you please verify them.
billing models.py
from django.conf import settings
from django.db import models
from django.db.models.signals import post_save,pre_save
from accounts.models import GuestEmail
import stripe
User=settings.AUTH_USER_MODEL
STRIP_SECRET_KEY= getattr(settings,"STRIP_SECRET_KEY","sk_test_I2eGCibhrZeFd9N0ipx9ac4I")
#STRIP_PUB_KEY=getattr(settings,"STRIP_PUB_KEY","pk_test_nvw3qh6iGMtKSGHMW5MHVwQD")
stripe.api_key=STRIP_SECRET_KEY
class BillingProfileManager(models.Manager):
def new_or_get(self,request):
user=request.user
guest_email_id=request.session.get('guest_email_id')
created=False
obj=None
if user.is_authenticated:
obj,created= self.model.objects.get_or_create(
user=user, email=user.email)
elif guest_email_id is not None:
guest_email_obj = GuestEmail.objects.get(id=guest_email_id)
obj, created = self.model.objects.get_or_create(
email=guest_email_obj.email)
else:
pass
return obj,created
class BillingProfile(models.Model):
user=models.OneToOneField(User,null=True,blank=True,on_delete=models.CASCADE)
email=models.EmailField()
active=models.BooleanField(default=True)
update = models.DateTimeField(auto_now=True)
timestamp=models.DateTimeField(auto_now_add=True)
customer_id=models.CharField(max_length=120,null=True,blank=True)
objects=BillingProfileManager()
def __str__(self):
return self.email
def charge(self,order_obj,card=None):
return Charge.objects.do(self,order_obj,card)
def get_cards(self):
return self.card_set.all()
#property
def has_card(self):
card_qs=self.get_cards()
return card_qs.exists()
#property
def default_card(self):
default_cards=self.get_cards().filter(default=True)
if default_cards.exists():
return self.default_cards.first()
return None
def billing_profile_created_receiver(sender,instance,*args,**kwargs):
if not instance.customer_id and instance.email:
print("ACTUAL AIL REQUEST SEND")
customer=stripe.Customer.create(
email=instance.email
)
print (customer)
instance.customer_id=customer.id
pre_save.connect(billing_profile_created_receiver,sender=BillingProfile)
class CardManager(models.Manager):
def all(self, *args, **kwargs): # ModelKlass.objects.all() --> ModelKlass.objects.filter(active=True)
return self.get_queryset().filter(active=True)
def add_new(self, billing_profile, token):
if token:
customer = stripe.Customer.retrieve(billing_profile.customer_id)
stripe_card_response = customer.sources.create(source=token)
new_card = self.model(
billing_profile=billing_profile,
stripe_id = stripe_card_response.id,
brand = stripe_card_response.brand,
country = stripe_card_response.country,
exp_month = stripe_card_response.exp_month,
exp_year = stripe_card_response.exp_year,
last4 = stripe_card_response.last4
)
new_card.save()
return new_card
return None
def user_created_receiver(sender,instance,created,*args,**kwargs):
if created and instance.email:
BillingProfile.objects.get_or_create(user=instance,email=instance.email)
post_save.connect(user_created_receiver,sender=User)
class ChargeManager(models.Manager):
def do(self, billing_profile, order_obj, card=None): # Charge.objects.do()
card_obj = card
if card_obj is None:
cards = billing_profile.card_set.filter(default=True) # card_obj.billing_profile
if cards.exists():
card_obj = cards.first()
if card_obj is None:
return False, "No cards available"
c = stripe.Charge.create(
amount = int(order_obj.total * 100), # 39.19 --> 3919
currency = "usd",
customer = billing_profile.customer_id,
source = card_obj.stripe_id,
metadata={"order_id":order_obj.order_id},
)
new_charge_obj = self.model(
billing_profile = billing_profile,
stripe_id = c.id,
paid = c.paid,
refunded = c.refunded,
outcome = c.outcome,
outcome_type = c.outcome['type'],
seller_message = c.outcome.get('seller_message'),
risk_level = c.outcome.get('risk_level'),
)
new_charge_obj.save()
return new_charge_obj.paid, new_charge_obj.seller_message
class Charge(models.Model):
billing_profile = models.ForeignKey(BillingProfile,on_delete=models.CASCADE)
stripe_id = models.CharField(max_length=120)
paid = models.BooleanField(default=False)
refunded = models.BooleanField(default=False)
outcome = models.TextField(null=True, blank=True)
outcome_type = models.CharField(max_length=120, null=True, blank=True)
seller_message = models.CharField(max_length=120, null=True, blank=True)
risk_level = models.CharField(max_length=120, null=True, blank=True)
objects = ChargeManager()
class Card(models.Model):
billing_profile=models.ForeignKey(BillingProfile,on_delete=models.CASCADE)
stripe_id=models.CharField(max_length=120)
brand=models.CharField(max_length=120,null=True,blank=True)
country = models.CharField(max_length=12, null=True, blank=True)
exp_month=models.IntegerField(null=True,blank=True)
exp_year=models.IntegerField(null=True,blank=True)
last4=models.CharField(max_length=4,null=True,blank=True)
default=models.BooleanField(default=True)
objects = CardManager()
def __str__(self):
return "{} {}".format(self.brand, self.last4)
checkout.html
{% extends "base.html" %}
{% block content %}
{% if not billing_profile%}
<div class="row text-center">
<div class="col-12 col-md-6">
<p class="lead">Login</p>
{% include 'accounts/snippets/form.html' with form=login_form next_url=request.build_absolute_uri %}
</div>
<div class="col-12 col-md-6">
Continue as Guest
{% url "guest_register" as guest_register_url %}
{% include 'accounts/snippets/form.html' with form=guest_form next_url=request.build_absolute_uri action_url=guest_register_url %}
</div>
</div>
{% else %}
{% if not object.shipping_address %}
<div class="row">
<div class="col-12">
<p class="lead">Shipping Address</p>
<hr/>
</div>
<div class="col-6">
{% url "checkout_address_create" as checkout_address_create %}
{% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='shipping' %}'
</div>
<div class="col-6">
{% url 'checkout_address_reuse' as checkout_address_reuse %}
{% include 'addresses/prev_addresses.html' with address_qs=address_qs next_url=request.build_absolute_uri address_type='shipping' action_url=checkout_address_reuse %}
</div>
</div>
{% elif not object.billing_address %}
<div class="row">
<div class="col-12">
<p class="lead">Billing Address</p>
<hr/>
</div>
<div class="col-md-6">
{% url "checkout_address_create" as checkout_address_create %}
{% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='billing' %}
</div>
<div class="col-6">
{% url 'checkout_address_reuse' as checkout_address_reuse %}
{% include 'addresses/prev_addresses.html' with address_qs=address_qs next_url=request.build_absolute_uri address_type='billing' action_url=checkout_address_reuse %}
</div>
</div>
{% else%}
{% if not has_card %}
<!-- enter credit card here -->
<div class='stripe-payment-form' data-token='{{ publish_key }}' data-next-url='{{ request.build_absolute_uri }}' data-btn-title='Add Payment Method'></div>
{% else %}
<h1>Finalize Checkout</h1>
<p>Cart Item:{% for product in object.cart.products.all %}{{ product}}{% if not forloop.last %},{% endif %},{% endfor %}</p>
<p>Shipping Address:{{object.shipping_address.get_address}}</p>
<p>Billing Address:{{object.shipping_address.get_address}}</p>
<p>Cart Total:{{object.cart.total}}</p>
<p>Shipping Total:{{object.shipping_total}}</p>
<p>Order Total:{{object.total}}</p>
<form class="form" method="POST" action="">{% csrf_token %}
<button type="submit btn btn-success">Checkout</button>
</form>
{% endif %}
{% endif %}
{% endif %}
{% endblock %}
The problem appears to be in your CardManager declaration.
class CardManager(models.Manager):
def all(self, *args, **kwargs):
return self.get_queryset().filter(active=True)
active is not a field on the Card model, but rather on the BillingProfile FK from the Card model.
Change this to:
class CardManager(models.Manager):
def all(self, *args, **kwargs):
return self.get_queryset().filter(billing_profile__active=True)
That is likely to happen because you are trying to filter a queryset by an attribute its model does not have.
The model missing this attribute is the one having the attributes are shown to you by the traceback:
billing_profile, billing_profile_id, brand, country, default, exp_month, exp_year, id, last4, stripe_id.
that is, model Card.
Add something like:
active = models.BooleanField(default=True)
to Card model, then makemigrations, migrate, and it should work.

Filtering Django Databases

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.

Resources