saving multiple data like checkbox at once in django - python

I am working in ang django project onlinevoting. In my template I use
looping to loop all the positions and also the candidates. I have trouble in saving many data at once in one attribute for example in my model I have:
class Vote(models.Model):
candidate_id = models.ForeignKey('Candidate', blank=True, null=True)
election_id = models.ForeignKey('Election', blank=True, null=True)
user_id = models.ForeignKey('User', blank=True, null=True)
def __str__(self):
return "%s %s" % (user_id.first_name, election_id.year)
and in my template vote.html:
<form method="POST" class="form-horizontal" role="form">
{% if success %}
<div class="alert alert-success">
×
<strong>Success!</strong> {{ success }}
</div>
{% endif %}
{% if exist %}
<div class="alert alert-warning">
×
<strong>Warning!</strong> {{ exist }}
</div>
{% endif %}
{% csrf_token %}
<div class="form-group ">
{% for position in positions %}
<label for="cname" class="control-label col-lg-2">{{ position }}<span class="required">*</span></label>
{% for candidate in candidates %}
{% if position.pk == candidate.position_id.pk %}
<div class="col-lg-3">
<input type="checkbox" name="candidate_id" value="{{ candidate.pk }}">{{ candidate }}<br>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
<button class="btn btn-primary" type="submit">Save</button>
<button class="btn btn-default" type="button">Cancel</button>
</div>
</div>
</form>
How can I add/save all the candidates? because the user can select many candidates and I want to save them at once. This is my views.py
def vote(request):
if request.user.is_authenticated and request.user.is_admin:
candidates = Candidate.objects.all()
election = Election.objects.all().filter(is_active=True)
positions = Position.objects.all()
user = get_object_or_404(User, pk=request.user.pk)
try:
if request.method == 'POST':
candidate_id = request.POST['candidate_id']
vote = Vote.objects.create(candidate_id=candidate_id)
vote.save()
vote.election_id = election
vote.save()
vote.user_id = user
vote.save()
else:
form = VoteForm()
return render(request,'system/vote.html', {'form':form, 'candidates': candidates,
'election': election, 'user': user,
'positions': positions})
except:
exist = "ERROR!"
form = VoteForm()
return render(request,'system/vote.html', {'form':form, 'exist': exist})
elif not request.user.is_authenticated:
return redirect('system.views.user_login')

Related

How can I have a form redirect to same page after submitting in Django?

How can I set my function in views.py so that a form redirects to the same page after submitting?
For example, I want to add time slots:
In my views.py:
#login_required
def post_available_timeslots(request):
print("Check")
if not check_existing_timeslot(request):
print("Time slot does not exist")
instance = TimeSlot()
data = request.POST.copy()
data["time_slot_owner"] = request.user
# data["food_avail_id"] = FoodAvail.objects.get(author=request.user).pk
form = TimeSlotForm(data or None, instance=instance)
if request.POST and form.is_valid():
form.save()
return redirect("food_avail:view_food_avail_res")
else:
print("Time slot does not exist")
messages.info(request, "Time Slot Already Exists")
return render(request, "food_avail/view_food.html", {"time_slot": form})
in models.py
class TimeSlot(models.Model):
time_slot_owner = models.ForeignKey(User, on_delete=models.CASCADE)
# food_avail_id = models.ForeignKey(FoodAvail, on_delete=models.CASCADE)
start_time = models.TimeField()
end_time = models.TimeField()
def __str__(self):
return str(self.start_time) + "-" + str(self.end_time)
In forms.py:
class TimeSlotForm(ModelForm):
class Meta:
model = TimeSlot
fields = ["start_time", "end_time"]
In urls.py:
from django.urls import path
from food_avail import views
app_name = "food_avail"
urlpatterns = [
path("post_food_avail/", views.post_available_food, name="post_food_avail"),
# path("post_food_avail/", views.FoodAvailCreateView.as_view(), name="post_food_avail"),
# path("update_food_avail/", views.post_available_food, name="update_food_avail"),
path("food_avail_all/", views.check_food_availibility, name="view_food_avail"),
path("food_avail_res/", views.view_available_food, name="view_food_avail_res"),
# path("food_avail_res/", views.post_available_timeslots, name="create_timeslots"),
]
in my html template:
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
{{ field.label }} <strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
{{ field.label }} <strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
{% if user.is_authenticated %}
<div>
<div>
<div>
<div>
<h4>
{{ food.author.username }}<br>
</h4>
</div>
<div>
Food Available: {{ food.food_available }}<br>
Description: {{ food.description }}<br>
{% endif %}
</div>
</div>
<div>
<h4>Add Time Slot</h4>
<br><br>
</div>
<div>
<div>
<form method="post">
{{ time_slot.as_p }}
<button type="submit" class="button btn-success">Submit</button>
</form>
</div>
{% if time_slot %}
<h4> List Of Time Slots </h4>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover ">
<thead>
<tr>
<th>Start Time</th>
<th>End Time</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for x in time_slot %}
<tr>
<td>{{x.start_time | time:'H:i:s'}}</td>
<td>{{x.end_time | time:'H:i:s'}}</td>
<td>
{% endfor %}
{% endif %}
I have been stuck on this problem for a minute now so any help would be much appreciated. This is how it currently shows up on my HTML template:

django does not show value form db

I have problem. My template don't show my value from db.
I think that I don't have defined model UserProduct in views.py in function product.
wievs.py
def index(request):
context = {
'products': Product.objects.order_by('category').filter(is_published=True)
}
return render(request, 'offers/products.html', context)
def userproduct(request):
context = {
'userproduct': UserProduct.objects.filter(user_id=request.user.id),
}
return render(request, 'offers/userproducts.html', context)
def product(request, product_id):
product = get_object_or_404(Product, pk=product_id)
context = {
'product': product,
}
return render(request, 'offers/product.html', context)
models.py
class Product(models.Model):
product_name = models.CharField(max_length=100)
category = models.CharField(max_length=50)
weight = models.FloatField()
description = models.TextField(blank=True)
photo = models.ImageField(upload_to='photos/%Y/%m/%d/')
is_published = models.BooleanField(default=True)
list_date = models.DateField(default=datetime.now, blank=True)
def __str__(self):
return self.product_name
class UserProduct(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
product_name = models.ForeignKey(Product, on_delete=models.CASCADE)
price = models.FloatField()
is_published = models.BooleanField(default=True)
list_date = models.DateField(default=datetime.now, blank=True)
def __str__(self):
return str(self.user.username) if self.user.username else ''
offers/product.html
<div class="p-4">
<p class="lead">
{% if user.is_authenticated %}
<span class="mr-1">
<p>Price</p></span>
<p class="colores lead font-weight-bold">{{ product.price }} £</p>
{% endif %}
<p >Description</p>
<p class="colores lead font-weight">{{ product.description }}</p>
<p class="colores lead font-weight-bold">Weight: {{ product.weight }}kg</p> </p>
{% if user.is_authenticated %}
<form class="d-flex justify-content-left">
<!-- Default input -->
<input type="number" value="1" aria-label="Search" class="form-control" style="width: 100px">
<button class="btn send-click btn-md my-0 p" type="submit">Add to cart
<i class="fas fa-shopping-cart ml-1"></i>
</button>
</form>
{% endif %}
</div>
Value product.price does not show.
The idea is that each user will have a different product price.
That's because your Product model has no price field; What you have is userproduct_set as a reverse foreign key relationship from the UserProduct model.
So you may have multiple price for one Product instance.
You can use the following code to show all the available prices for your product:
<div class="p-4">
<p class="lead">
{% if user.is_authenticated %}
<span class="mr-1">
<p>Price</p></span>
{% for userproduct in product.userproduct_set.all %}
<p class="colores lead font-weight-bold">{{ userproduct.price }} £</p>
{% endfor %}
{% endif %}
<p>Description</p>
<p class="colores lead font-weight">{{ product.description }}</p>
<p class="colores lead font-weight-bold">Weight: {{ product.weight }}kg</p> </p>
{% if user.is_authenticated %}
<form class="d-flex justify-content-left">
<!-- Default input -->
<input type="number" value="1" aria-label="Search" class="form-control" style="width: 100px">
<button class="btn send-click btn-md my-0 p" type="submit">Add to cart
<i class="fas fa-shopping-cart ml-1"></i>
</button>
</form>
{% endif %}
</div>
Read more about them in the docs.
Edit
As you mentioned in the comments, you want to find out the price assigned to the current logged in user, if the user is logged in and show weight and description even if the user is not logged in. So you need:
def product(request, product_id):
product = get_object_or_404(Product, pk=product_id)
user_product = None
if request.user.is_authenticated:
user_product = UserProduct.objects.filter(product_name_id=product_id, user=request.user)
if user_product:
user_product = user_product.first()
context = {
'product': product,
'user_product': user_product,
}
return render(request, 'offers/product.html', context)
and your template as well:
<div class="p-4">
<p class="lead">
{% if user.is_authenticated and user_product %}
<span class="mr-1">
<p>Price</p></span>
<p class="colores lead font-weight-bold">{{ user_product.price }} £</p>
{% endif %}
<p>Description</p>
<p class="colores lead font-weight">{{ product.description }}</p>
<p class="colores lead font-weight-bold">Weight: {{ product.weight }}kg</p> </p>
{% if user.is_authenticated and user_product %}
<form class="d-flex justify-content-left">
<!-- Default input -->
<input type="number" value="1" aria-label="Search" class="form-control" style="width: 100px">
<button class="btn send-click btn-md my-0 p" type="submit">Add to cart
<i class="fas fa-shopping-cart ml-1"></i>
</button>
</form>
{% endif %}
</div>

How do i access the properties of a many-to-many with Membership in Django

How can i set only mine membership, instead of all in for-loop ?
template.html:
{% for g in gr %}
<div class="jumbotron">
<div class="jumbo2">
<form method="POST" class="post-form"> {% csrf_token %}
<p id="name"><b>Groups name:</b> {{g.name}}</p><br>
{% for membership in g.membership_set.all %}
<p><b>Member:</b> {{ membership.person }} - {{ membership.role }}</p>
{% endfor %}
<br>
<span class="desc2">Groups description:</span>
<p id="desc">{{g.description}}</p><br>
{% for membership in g.membership_set.all %}
{% if membership.leader == False %}
<button style="float: right" type="submit" name = "leave" value = "{{g.name}}" class="save btn btn-default">Leave</button>
{% elif membership.leader == True %}
<button style="float: right" type="submit" name = "delete" value = "{{g.name}}" class="save btn btn-default">Delete</button>
{% endif %}
{% endfor %}
</form>
<br><br>
<p></p>
</div>
</div>
{% endfor %}
models.py:
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self): # __unicode__ on Python 2
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
description = models.TextField(max_length=350)
def __str__(self): # __unicode__ on Python 2
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
leader = models.BooleanField(default=False)
group = models.ForeignKey(Group)
role = models.CharField(max_length=50)
My buttons are displeyed as many as i have users in some group.
I want to display only 1 button, and i need to precise ForLoop only for my membership in this group. How can i do this?
I don't think you can do this just by using standard template code. You would need to get your Membership object by filtering the memberships like so:
membership = my_person.membership_set.get(group=my_group)
To do this in the template, you would have to write your own template filter that works on the my_person object and takes the my_group object as parameter. The filter could then apply the above query and return the membership object.
{% with membership=my_person|get_group_membership:g %}
{% if membership.leader == False %}
<button style="float: right" type="submit" name = "leave" value = "{{g.name}}" class="save btn btn-default">Leave</button>
{% elif membership.leader == True %}
<button style="float: right" type="submit" name = "delete" value = "{{g.name}}" class="save btn btn-default">Delete</button>
{% endif %}
{% endwith %}

Assign request.user.id to OneToOneField in Model using form

I'm using django auth for users. Every user can create one row - based on Client model. But i have problem because I cant assign in form.is_valid to field id request.user.id.
Because id is required I exclude this field in form class Meta.
Please give me some advice how i can assign user.id to my OneToOneField field.
I'm using PyCharm and when i put form. i dont see any of fields in my Model so i thing that i make some mistake in my code :(
Model:
class Client(models.Model):
id = models.OneToOneField(User, on_delete=models.CASCADE, unique=True, primary_key=True)
name = models.CharField(max_length=256, unique=True)
vat = models.CharField(max_length=12, unique=True)
address = models.CharField(max_length=64)
zip_code = models.CharField(max_length=10, help_text='Zip Code')
city = models.CharField(max_length=64)
country = models.CharField(max_length=6, default='US')
forwarding_address = models.CharField(max_length=64, blank=True)
forwarding_zip_code = models.CharField(max_length=10, blank=True)
forwarding_city = models.CharField(max_length=64, blank=True)
forwarding_country = models.CharField(max_length=6, blank=True)
phone = models.CharField(max_length=20)
def __str__(self):
re = self.name + ' [' + str(self.id) + ']'
return re
Form:
class ClientProfileForm(forms.ModelForm):
class Meta:
model = Client
exclude = ['id']
View:
def profile_create(request):
if request.method == 'POST':
form = ClientProfileForm(request.POST)
if form.is_valid():
form.save(commit=False)
form.id = request.user.id
form.save()
return HttpResponseRedirect('/client/profile/')
dict = {}
dict['form'] = form
return render(request, 'client/profile_edit.html', dict)
else:
if Client.objects.filter(id=request.user.id).exists():
return HttpResponseRedirect('/client/profile/edit/')
else:
dict = {}
dict['form'] = ClientProfileForm()
return render(request, 'client/profile_edit.html', dict)
Template:
{% extends 'registration/base.html' %}
{% block title %} Client profile {% endblock %}
{% block content %}
{{ form.non_field_errors }}
<form role="form" action="" method="post">{% csrf_token %}
{{ form.name.errors }}
<div class="form-group login-input">
<i class="fa fa-envelope overlay"></i>
<input type="text" class="form-control text-input"
{% if form.name.value != nulls %} value="{{ form.name.value }}" {% endif %}
id="{{ form.name.name }}" name="{{ form.name.name }}">
</div>
{{ form.vat.errors }}
<div class="form-group login-input">
<i class="fa fa-envelope overlay"></i>
<input type="text" class="form-control text-input"
{% if form.vat.value != nulls %} value="{{ form.vat.value }}" {% endif %}
id="{{ form.vat.name }}" name="{{ form.vat.name }}">
</div>
{{ form.address.errors }}
<div class="form-group login-input">
<i class="fa fa-envelope overlay"></i>
<input type="text" class="form-control text-input"
{% if form.address.value != nulls %} value="{{ form.address.value }}" {% endif %}
id="{{ form.address.name }}" name="{{ form.address.name }}">
</div>
(....)
<div class="row">
<div class="col-sm-12">
<button type="submit" class="btn btn-default btn-block">Create</button>
</div>
</div>
</form>
{% endblock %}
Cheers!
That's not the right pattern. It should be:
if form.is_valid():
obj = form.save(commit=False)
obj.id = request.user.id
obj.save()

Next and Before Links for a django paginated query

I'm trying to make a search form for Django.
Its a typical search form and then returns a table of matches. I wish to paginate the tables returned.
The problem lies in the Previous and Next buttons.
The links for the return query goes to /records/search/?query=a (search sample is a)
The page outputs the table and its previous and next links. However the links redirect to /records/search/?page=2 and the page displays a blank table.
Any help on which links I should pass for Prev/Next?
search.html:
{% extends 'blank.html' %}
{% block content %}
<div class="row">
<form id="search-form" method="get" action=".">
{{ form.as_p }}
<input type="submit" value="Search" />
</form>
</div>
<br><br>
//display table code//
{% if is_paginated %}
<div class="pagination">
<span class="step-links">
{% if agent_list.has_previous %}
forrige
{% endif %}
<span class="current">
Page {{ agent_list.number }} of {{ agent_list.paginator.num_pages }}.
</span>
{% if agent_list.has_next %}
Next
{% endif %}
</span>
</div>
{% endif %}
{% endblock %}
and the search view:
def search_page(request):
form = SearchForm()
agents = []
show_results=False
if request.GET.has_key('query'):
show_results=True
query=request.GET['query'].strip()
if query:
form=SearchForm({'query': query})
agents = \
Agent.objects.filter(Q(name__icontains=query))
paginator = Paginator(agents, 10)
page = request.GET.get('page')
try:
agents = paginator.page(page)
except PageNotAnInteger:
agents = paginator.page(1)
except EmptyPage:
agents = paginator.page(paginator.num_pages)
variables = RequestContext(request,
{ 'form': form,
'agent_list': agents,
'show_results': show_results,
'is_paginated': True,
}
)
return render_to_response('search.html', variables)
I've seen the similar questions but I can't understand/make them work. Any help?
Edit:
For a quickfix (haven't really looked at the cons)
I added a variable in my view:
variables = RequestContext(request,
{ 'form': form,
'agent_list': agents,
'show_results': show_results,
'is_paginated': True,
**'query': query,**
}
)
Where query without the quotes is the recieved query variable.
Then simply change the URL to:
Previous
If you have a better way of answering the question, please do or appending a URL to your currently opened URL.
I would recommend putting the solution in a template tag like so:
myapp/templatetags/mytemplatetags.py:
from django import template
register = template.Library()
#register.simple_tag
def url_replace(request, field, value):
d = request.GET.copy()
d[field] = value
return d.urlencode()
#register.simple_tag
def url_delete(request, field):
d = request.GET.copy()
del d[field]
return d.urlencode()
Then from templates do:
{% load mytemplatetags %}
...
previous
you can use {{ request.get_full_path }} this tag to get current url.
Next
this worked for me
The below works before and after a search form has been submitted:
Views.py
class PostListView(ListView):
model = Post #.objects.select_related().all()
template_name = 'erf24/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts' # default >> erf24/post_list.html
ordering = ['date_posted']
paginate_by = 3
def is_valid_queryparam(param):
return param != '' and param is not None
def invalid_queryparam(param):
return param == '' and param is None
class SearchView(ListView):
model = Post #.objects.select_related().all()
template_name = 'erf24/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts' # default >> erf24/post_list.html
ordering = ['date_posted']
paginate_by = 3
def get_queryset(self): # new
key = self.request.GET.get('key')
minp = self.request.GET.get('min')
maxp = self.request.GET.get('max')
if is_valid_queryparam(key):
obj = Post.objects.filter(Q(content__icontains=key) | Q(location__icontains=key)).distinct().order_by('date_posted')
if is_valid_queryparam(minp):
obj = Post.objects.filter(Q(price__gte=minp)).distinct().order_by('date_posted')
if is_valid_queryparam(maxp):
obj = Post.objects.filter(Q(price__lte=maxp)).distinct().order_by('date_posted')
if is_valid_queryparam(minp) & is_valid_queryparam(maxp):
obj = Post.objects.filter(Q(price__gte=minp) & Q(price__lte=maxp)).distinct().order_by('date_posted')
if is_valid_queryparam(key) & is_valid_queryparam(minp) & is_valid_queryparam(maxp):
obj = Post.objects.filter(Q(content__icontains=key) | Q(location__icontains=key)).distinct()
obj = obj.filter(Q(price__gte=minp) & Q(price__lte=maxp)).order_by('date_posted')
if invalid_queryparam(key) & invalid_queryparam(minp) & invalid_queryparam(maxp):
obj = Post.objects.all()
return obj
url.py
urlpatterns = [
path('', PostListView.as_view(), name='erf24-home'),
path('search/', SearchView.as_view(), name='erf24-search'),
]
Home.html
<form action="{% url 'erf24-search' %}" method="GET">
<div class="form-group">
<label for="inputAddress">Search keyword</label>
<input type="text" class="form-control" id="key" name="key" placeholder="keyword">
</div>
<label for="">Price</label>
<div class="form-row">
<div class="form-group col-md-6">
<input type="number" class="form-control" id="min" name="min" placeholder="min price">
</div>
<div class="form-group col-md-6">
<input type="number" class="form-control" id="max" name="max" placeholder="max price">
</div>
</div>
<button type="submit" class="btn btn-primary btn-sm mt-1 mb-1">Search</button>
<button type="reset" class="btn btn-secondary btn-sm mt-1 mb-1">Clear</button>
</form>
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}" alt="">
{{ post.author }}
<small class="text-muted">{{ post.date_posted }}</small>
<!-- use |date: "specs" to filter date display -->
</div>
<h2>
{{ post.price }}
</h2>
<p class="article-content">{{ post.content }}</p>
<p class="article-content">{{ post.location }}</p>
<p><a class="like-btn" data-href="{{ post.get_api_like_url }}" href="">{{ post.likes.count }}
{% if user in post.likes.all %} Unlike
{% else %} Like
{% endif %}
</a></p>
</div>
{% for image in post.image_set.all %}
<img class="account-img" src="{{ image.image.url }}" alt="">
{% endfor %}
</article>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
First
Previous
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
{{ num }}
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
{{ num }}
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
Next
Last
{% endif %}
{% endif %}
Worked like a charm :) Enjoy!
You can use {{ request.get_full_path }} template tag
Next
you can use this, I use it because I use filters in the url itself, so all the url params are used to build the next or previous url
import re
from django import template
register = template.Library()
PAGE_NUMBER_REGEX = re.compile(r'(page=[0-9]*[\&]*)')
#register.simple_tag
def append_page_param(value,pageNumber=None):
'''
remove the param "page" using regex and add the one in the pageNumber if there is one
'''
value = re.sub(PAGE_NUMBER_REGEX,'',value)
if pageNumber:
if not '?' in value:
value += f'?page={pageNumber}'
elif value[-1] != '&':
value += f'&page={pageNumber}'
else:
value += f'page={pageNumber}'
return value
then, in your pagination nav you can call it like this:
{% append_page_param request.get_full_path page_obj.previous_page_number %}

Categories