how to Update/Edit database content with form in django - django-models

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.

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 use 2 models in class base View that is Home view and Detailview

I have two model Item and Women
this is the code for my 2 models
class Item(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
discount_price = models.FloatField(blank=True, null=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=2)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField()
def __str__(self):
return self.title
class Women(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
discount_price = models.FloatField(blank=True, null=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=2)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField()
def __str__(self):
return self.title
In my view.py
I have created Homeview(View) to render the homepage.html which I have used get_context_data to render the two model which is the Item and Women.
this is code for my views.py
class HomeView(ListView):
template_name='Ecommerce/home-page.html'
def get_queryset(self):
return Item.objects.all()
def get_context_data(self, **kwargs):
et =super(HomeView, self).get_context_data(**kwargs)
et['Item_qs']= Item.objects.all()
et['women_qs']= Women.objects.all()
return et
class ProductDetailView(DetailView):
model= Women,Item
template_name='Ecommerce/product-page.html'
i dont know if i am writing the ProductDetailView correctly for the 2 models
Now within the homepage my first div I used the Item model to loop through
And my second div I used the Women model to loop through
this is how i rendered the two views in my html templates
the first one is for the item model
{% for item in Item_qs %}
<div class="col-lg-3 col-md-6 mb-4">
<!--Card image-->
<div class="view overlay">
<img src="{{ item.image.url }}" class="card-img-top"
alt="">
<a href="{{item.get_absolute_url}}">
<div class="mask rgba-white-slight"></div>
</a>
</div>
<!--Card image-->
</div>
<!--Card-->
{% end%}
and this is for the Women model
{% for items in women_qs %}
<!--Grid column-->
<div class="col-lg-3 col-md-6 mb-4">
<!--Card-->
<div class="card zoom">
<!--Card image-->
<div class="view overlay">
<img src="{{ items.image.url }}" class="card-img-top"
alt="">
<a href="{{items.get_absolute_url}}">
<div class="mask rgba-white-slight"></div>
</a>
</div>
</div>
<!--Card-->
</div>
{% endfor %}
i am using get_absoulte_url as the href link to get the Productpage.html
below is the code
def get_absolute_url(self):
return reverse("Ecommerce:product", kwargs={
'slug': self.slug })
My problem is how do I create a ProductDetailpage(Detailview) to get the details of individual items that is in the Item model and the Women model?
And how do I render both in the template
Please I believe my question is clear enough and if anyone need clarification I can explain further.
Looking forward for your assistance house😊
Ok, you can't use DetailView with multiple models. You'd be better off writing a normal View and allowing the URL for it take 2 params for each of your models.
Then you can get each instance in your view.
It'd work something like this;
urlpatterns = [
path('<int:item_id>/<int:women_id>', MultiModelView.as_view()),
]
class MultiModelView(View):
def __init__(self, **kwargs):
""" Constructor """
super().__init__(**kwargs)
self.item_id = None
self.women_id = None
def dispatch(self, request, *args, **kwargs):
self.item_id = self.kwargs.get('item_id')
self.women_id = self.kwargs.get('women_id')
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'item': Item.objects.get(id=self.item_id),
'woman': Women.objects.get(id=self.women_id),
})
return context

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.

UnicodeDecodeError. While rendering the blob image

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.

Resources