Django: show value of dictionary in dropdown - python

In my template, the dropdown box is populated with a dictionary instead of the value of the dictionary. How can I make that only the value is shown?
This is my collectionPoint
class CollectionPoint(models.Model):
addressID = models.AutoField(primary_key=True)
collectionPointName = models.CharField(max_length=50, null=False)
street = models.CharField(max_length=50, null=False)
streetnumber = models.CharField(max_length=20, null=False)
city = models.CharField(max_length=50, null=False)
postalcode = models.CharField(max_length=30, null=True)
gps_latitude = models.FloatField(blank=True, null=True)
gps_longitude = models.FloatField(blank=True, null=True)
country = models.ForeignKey(Country)
company = models.ForeignKey(Company)
#only the name is returned to the user
def __str__(self):
template = '{collectionPointName}'
return template.format(collectionPointName=self.collectionPointName)
I want to display all the distinct city of the collectionpoints
class RentalSelectCityForm(forms.Form):
city = forms.ModelChoiceField(queryset=CollectionPoint.objects.order_by().values('city').distinct(),initial=0)
My view
#login_required
def rentalselectcity(request):
# Get the context from the request.
context = RequestContext(request)
# A HTTP POST?
if request.method == 'POST':
form = RentalSelectCityForm(request.POST)
# Have we been provided with a valid form?
return HttpResponseRedirect('/')
else:
# If the request was not a POST, display the form to enter details.
form = RentalSelectCityForm()
context['path'] = [{'name': 'My rentals', 'url': reverse('rentals-list')}]
context['path'] += [{'name': 'Select city', 'url': reverse('rental-select-city')}]
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render_to_response('user/rentalselectcity.html', {'form': form}, context)
And my template
{% block content %}
<div class="box box-default">
<!--<div class="box-header">
<h3 class="box-title">Title</h3>
</div>--><!-- /.box-header -->
<!-- form start -->
<form action="{% url 'rental-select-city' %}" method="post" role="form">
{% csrf_token %}
<div class="box-body">
{{ form.non_field_errors }}
<div class="form-group">
{{ form.city.errors }}
<label for="{{ form.city.id_for_label }}">Select a city</label>
{{ form.city|attr:"class:form-control" }}
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-primary">Select city</button>
</div>
</form>
</div><!-- /.box -->
{% endblock %}

You can change form field queryset to
CollectionPoint.objects.order_by().values_list('city', flat=True).distinct()
See the values_list docs for the reference

Related

I am confused while rendering my views.py "Django"

My vews.py:
if you want me to share another piece of information feel free to ask!
I just have a problem with the bidding system !!, I tried the bidding but when I add the new number into the input field and click the place bid button the page just reloads which means the function doesn't work!!
I have another problem when I try to close the bid I git this Django error
ValueError at /bidding/26
The view auctions.views.bidding didn't return an HttpResponse object.
It returned None instead.
The code:
def viewList(request, id):
# check for the watchlist
listing = Post.objects.get(id=id)
user = User.objects.get(username=request.user)
if listing.watchers.filter(id=request.user.id).exists():
is_watched = True
else:
is_watched = False
if not listing.activate:
if request.POST.get('button') == "Close":
listing.activate = True
listing.save()
else:
price = request.POST.get('bid', 0)
bids = listing.bids.all()
if user.username != listing.creator.username:
if price <= listing.price:
return render(request, 'auctions/item.html', {
"listing": listing,
'form': BidForm(),
"message": "Error! Your bid must be largest than the current bid!",
'comment_form': CommentForm(),
'comments': listing.get_comments.all(),
'is_watched': is_watched,
})
form = BidForm(request.POST)
if form.is_valid():
bid = form.save(commit=False)
bid.user = user
bid.save()
listing.bids.add(bid)
listing.bid = price
listing.save()
else:
return render(request, 'acutions/item.html', {'form'})
context = {
'listing': listing,
'comment_form': CommentForm(),
'comments': listing.get_comments.all(),
'is_watched': is_watched,
'form': BidForm()}
return render(request, 'auctions/item.html', context)
models.py
class Bid(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
bid = models.DecimalField(max_digits=10, decimal_places=2)
time = models.DateTimeField(default=timezone.now)
class Post(models.Model):
# data fields
title = models.CharField(max_length=64)
textarea = models.TextField()
# bid
price = models.FloatField(default=0)
currentBid = models.FloatField(blank=True, null=True)
imageurl = models.CharField(max_length=255, null=True, blank=True)
category = models.ForeignKey(
Category, on_delete=models.CASCADE, default="No Category Yet!", null=True, blank=True)
creator = models.ForeignKey(
User, on_delete=models.PROTECT, related_name="all_creators_listings")
watchers = models.ManyToManyField(
User, blank=True, related_name='favorite')
date = models.DateTimeField(auto_now_add=True)
# for activated the Category
activate = models.BooleanField(default=False)
bids = models.ManyToManyField(Bid, )
def __str__(self):
return f"{self.title} | {self.textarea} | {self.date.strftime('%B %d %Y')}"
item.html
<div class="card-body">
<ul class="list-group">
<div class="info">
<li class="list-group-item mb-2">Description:<br>{{listing.textarea}}</li>
<li class="list-group-item mb-2">category: {{listing.category.name}}</li>
<li class="list-group-item mb-2"><h5>Start bid: {{listing.price}}$</h5></li>
</div>
<div class="newbid">
<p>{{ message }}</p>
<form action="{% url 'viewList' listing.id %}" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="bid">{{ listing.bids.count }} bid(s) so far. Your bid is the current bid</label>
</div>
<div class="form-group">
{{ form }}
</div>
<div class="form-group">
<input type="submit" name="button" class="btn btn-primary" value="Place Bid">
</div>
</form>
{% if listing.activate %}
<li><strong>Winner: </strong>{{ listing.bids.last.user.username }}</li>
{% endif %}
{% if user.username == listing.creator.username and not listing.activate %}
<form action="{% url 'viewList' listing.id %}" method="POST">
{% csrf_token %}
<button type="submit" name="button" class="btn btn-danger" value="Close">Close</button>
</form>
{% endif %}
</div>
</ul>
</div>
inside this view, I added a punch of my project requirement (comments/watchlist(bookmark)/and the last thing(that what I have a lot of problem with it) is the system of Bid) that lets users add bids on such posts and let the creator of that post the ability to close it.... please help I am sticking in this zone, I tried many times to understand!
Note I am new at Back-end Development!
There is the two problem in you code first one is hi-lighted by Husam
user = User.objects.get(username=request.user.username)
and the other one is in the return statement in the else part
render(request, 'acutions/item.html', {'form'}) instead of context object you pass the string in which is consider as set object in python and thats why you are getting None type error.
here is the refactored code :-
def viewList(request, id):
# check for the watchlist
listing = Post.objects.get(id=id)
user = User.objects.get(username=request.user.username)
form = BidForm()
is_watched = listing.watchers.filter(id=request.user.id).exists():
context = {}
if not listing.activate:
if request.POST.get('button') == "Close":
listing.activate = True
listing.save()
else:
price = request.POST.get('bid', 0)
bids = listing.bids.all()
if user.username != listing.creator.username:
if price <= listing.price:
context.update({'message':"Error! your bid must be largest than the current bid !"})
else:
form = BidForm(request.POST)
if form.is_valid():
bid = form.save(commit=False)
bid.user = user
bid.save()
listing.bids.add(bid)
listing.bid = price
listing.save()
else:
return render(request, 'acutions/item.html', {'form': form})
context.update({'listing': listing,
'comment_form': CommentForm(),
'comments': listing.get_comments.all(),
'is_watched': is_watched,
'form': form})
return render(request, 'auctions/item.html', context)
The error you face in bidding view and the view you have shared is view list, it would be better if you shared the bidding view and highlight the error line/s
Anyway I have noticed that this line has one mistake:
user = User.objects.get(username=request.user)
Which suppose to be :
user = User.objects.get(username=request.user.username)
Hope this can help you little bit

Django form field is displaying uuid of the record

I am using django 2.2 and python 3.6.
I have a django modelform. I am using crispy forms to display the form in template.
The form is not displaying the value of the records. It is displaying the uuid values of the records. I need to display the record name value instead of uuid value.
models.py :
#reversion.register()
class Staff(BaseModel):
user = models.OneToOneField(
User, on_delete=models.PROTECT, db_index=True, verbose_name=_("Kullanıcı"))
photo = models.ImageField(
upload_to="staff/", null=True, blank=True, verbose_name=_("Fotoğraf"))
staff_type = models.ManyToManyField(
StaffType, verbose_name=_("Personel Tipi"))
name = models.CharField(
max_length=100, db_index=True, verbose_name=_("İsim"))
surname = models.CharField(
max_length=100, db_index=True, verbose_name=_("Soyad"))
phone = models.CharField(max_length=100, verbose_name=_("Telefon Numarası"))
email = models.EmailField(verbose_name=_("Email"), db_index=True)
address = models.TextField(verbose_name=_("Adres"))
subject = models.ForeignKey(Subject, on_delete=models.SET(
get_unknown_subject), verbose_name=_("Branş"))
gender = models.IntegerField(
choices=GENDERS, default=None, verbose_name=_("Cinsiyet"))
nationality = models.CharField(
choices=NATIONALITIES, max_length=100, verbose_name=_("Uyruk"))
blood_type = models.CharField(
choices=BLOOD_TYPES, max_length=20, verbose_name=_("Kan Grubu"))
id_no = models.CharField(max_length=100, unique=True,
verbose_name=_("Kimlik No"))
birthdate = models.DateField(verbose_name=_("Doğum Günü"))
birthplace = models.CharField(max_length=200, verbose_name=_("Doğum Yeri"))
education = models.IntegerField(
choices=EDUCATION, default=None, verbose_name=_("Eğitim"))
marital_status = models.BooleanField(
default=True, verbose_name=_("Evlilik Durumu"))
number_of_children = models.IntegerField(
verbose_name=_("Çocuk Sayısı"))
special_notes = models.TextField(
null=True, blank=True, verbose_name=_("Özel Notlar"))
registration_date = models.DateField(verbose_name=_("Kayıt Tarihi"))
foreign_language = models.ForeignKey(Language, on_delete=models.SET(
get_default_language), null=True, blank=True, verbose_name=_("Yabancı Dil"))
class Meta:
permissions = (
("list_staff", _("List Staff")),
)
ordering = ['name', 'surname']
def __unicode__(self):
return "%s %s" % (self.name, self.surname)
def save(self, *args, **kwargs):
self.name = self.name.title()
self.surname = self.surname.upper()
groups = []
for staff_type_object in self.staff_type.all():
group = Group.objects.get_or_create(name=staff_type_object.name)[0]
groups.append(group)
self.user.groups = groups
self.user.save()
super(Staff, self).save(*args, **kwargs)
views.py:
#login_required(login_url='/accounts/login/')
def personelkayit(request):
staffs = Staff.objects.values("user__username", "name", "surname", "uuid")
if request.method == 'GET':
staff_uuid = request.GET.get("staff_uuid")
if staff_uuid:
instance = get_object_or_404(Staff, uuid=staff_uuid)
form = StaffForm(instance=instance)
form.fields['username'].initial = instance.user.username
form.fields['username'].widget.attrs['readonly'] = True
else:
form = StaffForm()
return render(request, 'personelkayit.html', {'form': form, 'staffs':
staffs, 'staff_uuid': staff_uuid})
elif request.method == 'POST':
staff_uuid = request.GET.get("staff_uuid")
if staff_uuid:
instance = get_object_or_404(Staff, uuid=staff_uuid)
form = StaffForm(request.POST or None,
request.FILES or None, instance=instance)
else:
form = StaffForm(request.POST, request.FILES or None)
if form.is_valid():
password = form.cleaned_data.get("password")
re_password = form.cleaned_data.get("re_password")
staff = form.save(commit=False)
staff.user = user
staff.save()
form.save_m2m()
staff.save()
return redirect('/')
else:
return render(request, "personelkayit.html", {'form': form, 'staffs': staffs})
personelkayit.html:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% load i18n %}
{% load staticfiles %}
{% block content %}
<br>
<table style="width: 100%">
<tr>
<td style="width: 4%"></td>
<td style="width: 92%">
<div class="block-area" id="basic">
<form role="form" method="get">
<select class="form-control input-sm m-b-10" name="staff_uuid">
<option value="" {% if not staff_uuid %} selected="selected" {% endif %} disabled="disabled">{% trans "Personel" %}</option>
{% for staff in staffs %}
<option {% if staff_uuid and staff.uuid|lower == staff_uuid|lower %}selected="selected"{% endif %} value="{{ staff.uuid }}">{{ staff.user__username }} - {{ staff.name }} {{ staff.surname }}</option>
{% endfor %}
</select>
<br />
<button type="submit" class="btn btn-sm btn-alt">{% trans "Personel Düzenle" %}</button>
<a class="btn btn-sm btn-alt" href="{% url 'personelkayit' %}">{% trans "Personel Ekle" %}</a>
<div class="modal-footer"></div>
</form>
</div>
<div class="block-area" id="basic">
<form role="form" enctype="multipart/form-data" method="post">
{% csrf_token %}
{{ form|crispy }}
<div >
<br>
<button style="background-color: #002266 !important; color: white !important" type="submit" class="btn btn-lg btn-alt"><span class="glyphicon glyphicon-floppy-disk
pull-left"></span>{% trans "Kaydet" %}</button>
</div>
</form>
<br>
</div>
</td>
<td style="width: 4%"></td>
</tr>
</table>
<script>
$( document ).ready(function() {
$( "select[name$='staff_uuid']" ).select2({
theme: "bootstrap"
});
$( "select[name$='subject']" ).select2({
theme: "bootstrap"
});
$( "select[name$='staff_type']" ).select2({
theme: "bootstrap"
});
});
</script>
{% endblock content %}
The reason this happens is because Django will render the string-representation of model objects in the form. A model is, by default rendered by the name of the type of the object, and the primary key. So a string like Subject object (...) is normal.
You can simply implement a __str__ (and for python-2.x a __unicode__) for the Subject model, to render it the way you specify:
class Subject(models.Model):
# …
def __str__(self):
return …

how to display all the reviews for the particular product?

With the below code i am adding reviews for some particular product in the database and it is doing good but the problem is while displaying the reviews for the selected product.I get confused how can i display the all reviews of some product and which review done by which user at what time?
models.py
class Product(models.Model):
name = models.CharField(max_length=250)
description = models.TextField(blank=True)
featured = models.BooleanField(default=False)
def __str__(self):
return self.name
class Review(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
review = models.TextField()
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.review
views.py
def detail(request,pk):
product = College.objects.get(pk=pk)
form = ReviewForm()
return render(request,'products/detail.html',{'product':product,'form':form})
#login_required(login_url='products:signin')
def review(request,pk):
if request.method == "POST":
form = ReviewForm(request.POST)
if form.is_valid():
review = form.save(commit=False)
review.product = Product.objects.get(pk=pk)
review.user = request.user
review.save()
messages.success(request, "Review saved")
return redirect('products:detail',pk)
else:
messages.error(request,'error in form')
return redirect('products:detail', pk)
detail.html
<h3>All reviews(total.no. of reviews?)</h3>
# Here i want to display all reviews and which is done by which user and at what time
<div class="col-lg-6 col-md-6 mb-6">
<form method="post" action="{% url 'products:review' product.pk %}">
{% csrf_token %}
{% form.as_p %}
<input type="submit" class="btn btn-success">
</form>
</div>
You can do it like this using reverse relation:
<h3>All reviews {{ product.review_set.count }}</h3>
{% for review in product.review_set.all %}
{{ review.review }}
{{ review.date }}
{% endfor %}

The view students.views.addgrregister didn't return an HttpResponse object. It returned None instead

ValueError at /students/addgrregister/
i am trying to add students in gr_register but its giving an error due to this error the code is not working i also upload the template (addgrregister.html) kndly tell me where is the issue in these pages
models.py
class gr_register(models.Model):
Gender_Choices = (
('M', 'Male'),
('FM', 'Female'),
)
Status_Choices = (
('P', 'Present'),
('FM', 'Left'),
)
gr_no = models.IntegerField(primary_key=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
date_birth = models.DateField(null=True)
classes_A = models.ForeignKey(Classes, on_delete=models.CASCADE, related_name="classes_A", default=1, verbose_name="Class of Admission")
sections_A = models.ForeignKey(Sections, on_delete=models.CASCADE, related_name="sections_A", default=1, verbose_name="Section of Admission")
gender = models.CharField(max_length=10, choices=Gender_Choices)
classes_C = models.ForeignKey(Classes, on_delete=models.CASCADE, related_name="classes_C", verbose_name="Current Class")
sections_C = models.ForeignKey(Sections, on_delete=models.CASCADE, related_name="sections_C", verbose_name="Current Section")
address = models.CharField(max_length=100, null=True, verbose_name="Home Address")
area_code = models.ForeignKey(Area, on_delete=models.CASCADE, verbose_name="Area")
status = models.CharField(max_length=10, choices=Status_Choices, default='P')
class Meta:
ordering = ('gr_no',)
def __str__(self):
return self.first_name
views.py
from django.shortcuts import get_object_or_404, render, redirect
def addgrregister(request):
if request.method == 'POST':
form = gr_registerForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
form = gr_registerForm()
return render(request, 'students/addgrregister.html', {'form': form})
forms.py
from django import forms
from django.forms import ModelChoiceField, ModelForm
from .models import *
class gr_registerForm(ModelForm):
classes_A = forms.ModelChoiceField(queryset=Classes.objects.all())
sections_A = forms.ModelChoiceField(queryset=Sections.objects.all())
classes_C = forms.ModelChoiceField(queryset=Classes.objects.all())
sections_C = forms.ModelChoiceField(queryset=Sections.objects.all())
area_code = forms.ModelChoiceField(queryset=Area.objects.all())
class Meta:
model = gr_register
fields = '__all__'
def init(self, *args, **kwargs):
forms.ModelForm.init(self, *args, **kwargs)
addgrregister.html
{% extends 'authenticate/base.html' %}
{% block content %}
<div class="container">
<h4 class="text-center">ADD GR_REGISTER</h4>
<hr/>
<form method="POST" action="{% url 'addgrregister' %}" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="form-group row">
<label for="id_{{ field.name }}" class="col-2 col-form-label">{{ field.label }}</label>
<div class="col-10">
{{ field }}
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary" name="button">Add GR_REGISTER</button>
</form>
<br/><br/>
</div>
{% endblock %}
There is nothing returned when form is not valid. I think you try like this:
def addgrregister(request):
form = gr_registerForm(request.POST or None) # it initates a form. If the request type is POST, then there will be a dict available with posted data in request.POST. If request is not POST, then the form will initiate with empty data.
if request.method == 'POST':
if form.is_valid(): # Form valid checks if the submitted form is valid or not. If not, it will store errors in the form. When that form is passed to template, it will show errors in html
form.save() # It will store data in DB
return redirect('home')
# when for is invalid, it will show the error in the form
return render(request, 'students/addgrregister.html', {'form': form})
Update
Show form errors in template:
{% for field in form %}
<div class="form-group row">
<label for="id_{{ field.name }}" class="col-2 col-form-label">{{ field.label }}</label>
<div class="col-10">
{{ field }}
{{ field.errors }} // <-- Updated here
</div>
</div>
{% endfor %}

Django: Assign current user as foreign key to comments model

I have been working thorough the DjangoGirls tutorial and was trying to improve on the section on adding comments to an application - TutorialExtensions
I have added the comments to a simple photo blog application but what I was attempting to do was replace the author = models.CharField(max_length=200) with an alternative that would store the current/logged-in user who was commenting on the photo instance and then allow me to display on the photo_detail template.
I thought I was close using author = models.ForeignKey(User, related_name='Commenter') but this through up an error:
NOT NULL constraint failed: timeline_comment.author_id
Here is my models.py consisiting of a Photo model and Comments model:
class Photo(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
title = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
image = ProcessedImageField(upload_to=upload_location,
null=True,
blank=False,
processors=[Transpose(), ResizeToFit(1000, 1000, False)],
format='JPEG',
options={'quality': 50},
width_field="width_field",
height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
description = models.TextField(max_length=1000)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
class Comment(models.Model):
post = models.ForeignKey('timeline.Photo', related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField(max_length=1000)
created_date = models.DateTimeField(default=timezone.now)
The related view:
def photo_detail(request, slug=None):
if not request.user.is_authenticated():
return HttpResponseRedirect("/accounts/login")
instance = get_object_or_404(Photo, slug=slug)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = instance
comment.save()
return redirect('timeline:detail', slug=instance.slug)
else:
form = CommentForm()
share_string = quote_plus(instance.description)
context = {
"title": instance.title,
"instance": instance,
"share_string": share_string,
"form": form,
}
return render(request, "photo_detail.html", context)
My forms.py:
class CommentForm(forms.ModelForm):
text = forms.CharField(widget=forms.Textarea, label='Leave a comment: ')
class Meta:
model = Comment
fields = [
"text",
]
Finally the template for the photo_detail view:
<div class="row">
<div class="col-md-12" id="comments">
<p>
{% if instance.comments.count == 0 %}
No Comments
{% elif instance.comments.count == 1 %}
{{ instance.comments.count }} Comment
{% else %}
{{ instance.comments.count }} Comments
{% endif %}
</p>
<hr style="margin-top: 10px;">
{% for comment in instance.comments.all %}
<div class="comment">
<div class="date pull-right">{{ comment.created_date | timesince }} Ago</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
<hr>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
</div>
{% if user.is_superuser or user.is_authenticated %}
<div class="row">
<div class="col-md-12">
<form method="POST" class="comment-form" action=''>
{% csrf_token %}
{{ form | crispy }}
<button type="submit" class="comment-add btn btn-lg btn-purple">Add</button>
</form>
</div>
</div>
{% endif %}
Could anybody recommend the best approach for this? Any help would be very much appreciated! Thank You.
Using the ForeignKey is correct[1] - the missing piece is that you need to assign that in your view. After comment = form.save(commit=False) just add one line:
comment.author = request.user
and it will work.
[1] although you don't want the related_name as "Commenter" (because it refers to the way you access the comment from the user: the default is comment_set which makes more sense).

Categories

Resources