Change model field value after button click - python

I do really know that is a common topic but I've already checked every solution i could find and it did not work for me.
I would like to add user points using button click.
views.py
def add_points(request):
if request.GET.get('mybtn'):
profil = get_object_or_404(Profile, created_by=request.user)
profil.points += 10
profil.save(update_fields=["points"])
return render(request, 'users/profile.html')
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to="profile_pics")
points = models.PositiveIntegerField(default=0)
people = models.PositiveIntegerField(default=0)
html file
<div>
<form method="POST">
{% csrf_token %}
<input type="submit" class="btn" value="+10 pkt" name="mybtn"/>
</form>
</div>
I have tried diffrent solutons but nothing really worked out for me.

Try F function.
from django.db.models import F
def add_points(request):
if request.GET.get('mybtn'):
profil = get_object_or_404(Profile, created_by=request.user)
profil.points = F('points') + 10
profil.save(update_fields=["points"])
return render(request, 'users/profile.html')

Related

Django Handling Multiple Image Uploads

I have a simple project that has two different models. One that handles a report and one that stores the images for each report connected by a ForeignKey:
class Report(models.Model):
report_location = models.ForeignKey(Locations, on_delete=models.CASCADE)
timesheet = models.ImageField(upload_to='report_images', default='default.png')
text = models.CharField(max_length=999)
report_date = models.DateField(auto_now=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f"{self.report_location, self.report_date, self.created_by}"
class TimeSheetAndPics(models.Model):
report = models.ForeignKey(Report, on_delete=models.CASCADE)
report_images = models.ImageField(upload_to='report_images', default='default.png')
date = models.DateField(auto_now=True)
def __str__(self):
return f"{self.report} on {self.date}"
My Goal is to have a user fill out the report and then upload multiple pictures, however i cannot figure out how to handle multiple image uploads.
I have two forms for each model:
class ReportCreationForm(ModelForm):
class Meta:
model = Report
fields = [
'report_location',
'text',
]
class TimeSheetAndPicForm(ModelForm):
report_images = forms.FileField(widget=ClearableFileInput(attrs={'multiple': True}))
class Meta:
model = TimeSheetAndPics
fields = [
'report_images',
]
And this is how i try to handle my views:
class NewReport(LoginRequiredMixin, View):
def get(self, request):
context = {
'create_form': ReportCreationForm(),
'image_form': TimeSheetAndPicForm(),
}
return render(request, 'rakan/report_form.html', context)
def post(self, request):
post = request.POST
data = request.FILES or None
create_form = ReportCreationForm(post)
image_form = TimeSheetAndPicForm(post, data)
if create_form.is_valid() and image_form.is_valid():
clean_form = create_form.save(commit=False)
clean_form.created_by = request.user
clean_form.save()
clean_image_form = image_form.save(commit=False)
for images in clean_image_form:
clean_image_form.report = clean_form
clean_image_form.report = images
clean_image_form.save()
return redirect('rakan:rakan_index')
return redirect('rakan:new-report')
I have tried to solve this in different ways but i unfortunately hit a wall. I cant seem to find a solution that actually works. My best try i was able to save only 1 image in the models instead of the 3 test images.
I dont believe it makes a difference but here is also the HTML File that uses the forms:
<div class="content-section">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Create Report</legend>
{{ create_form }}
<br>
{{ image_form }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">submit</button>
</div>
</form>
</div>
Anyone dealt with this problem would like to help me achieve a solution i would be very thankful. Thank you.

How to Store the Data in Database from dropdown in Djngo

I am working on student management project and I am unable to get the branch for student as it is foreignkey of Course model to Student model and I want to get the selected option into student model in branch row
models.py:
class Course(models.Model):
id=models.AutoField(primary_key=True)
course = models.CharField(max_length=50)
course_code = models.BigIntegerField(null=True)
def __str__(self):
return self.course
class Student(models.Model):
id=models.AutoField(primary_key=True)
user=models.OneToOneField(User,on_delete=models.CASCADE)
branch=models.ForeignKey(Course,on_delete=models.CASCADE,null=True,blank=True)
middle_name=models.CharField(max_length=50,null=True)
roll_no=models.IntegerField()
mobile_no=PhoneNumberField(default='')
parents_mobile_no=PhoneNumberField(default='')
division=models.CharField(max_length=10,null=True)
batch=models.CharField(max_length=10,null=True)
def __str__(self):
return self.user.first_name + " " + self.user.last_name
views.py:
def studentregister(request):
if request.method == 'POST':
first_name = request.POST['first_name']
middle_name = request.POST['middle_name']
last_name = request.POST['last_name']
email = request.POST['email']
branch= request.POST['branch']
division = request.POST['division']
roll_no = request.POST['roll_no']
mobile_no = request.POST['mobile_no']
parents_mobile_no = request.POST['parents_mobile_no']
pass1 = request.POST['password']
pass2 = request.POST['confirmpassword']
if pass1 == pass2 :
if User.objects.filter(email=email).exists():
return HttpResponse('User already exsits')
else:
user = User.objects.create_user(email=email, password=pass1, first_name=first_name, last_name=last_name)
user.save();
studentdetails = Student ( user=user, middle_name=middle_name,roll_no=roll_no,mobile_no=mobile_no,parents_mobile_no=parents_mobile_no, branch=branch,division=division)
studentdetails.save();
return render (request, 'ms/homepage/index.html')
else:
return HttpResponse('password does not match')
else:
return HttpResponse('failed')
def staffstudent(request):
if request.user.is_authenticated and request.user.user_type==3:
courses = Course.objects.all()
return render(request, 'ms/staff/student.html',{'courses':courses})
else:
return render(request,'ms/login/login.html')
html file as student.py:
<form action="studentregister" method="POST" style = "background-color:#011B3C;">
{% csrf_token %}
<div class="form-group" name="branch">
<select >
<option selected disabled="true">Branch</option>
{% for course in courses%}
<option>{{course.course}}</option>
{%endfor%}
</select>
</div>
</form>
The error I am getting is
MultiValueDictKeyError at /staff/studentregister
'branch'
Please help me with this as soon as possible.
You haven't named that <select> (<select name="branch">) so any choice you make in it will not be transmitted to the server, and that's why you get a key error.
In addition, the <option>'s value must be the course's id:
<option value="{{ course.id }}">{{ course.course }}</option>
... so you can look it up in the view:
branch = Course.objects.get(id=request.POST['branch'])
However, please look at Django's built-in forms functionality, especially model forms – you would be done in a fraction of the HTML and Python code you have now, plus you'd actually have correct data validation.
This is not the conventional way to deal with Forms in Django although it can be done. Convention would be:
Creating a form in forms.py like so:
class MyForm(forms.Form):
dropdown_one = forms.ChoiceField(
label="Country",
widget=forms.Select(attrs={"class": "selecter form-control"}),
choices=[],
)
dropdown_two = forms.ChoiceField(
label="Category",
widget=forms.Select(attrs={"class": "selecter form-control"}),
choices=[(None, '...')],
required=True
)
Then use this form in views.py like so:
my_form = MyForm(initial={})
return render(request,{'my_form':my_form})
Then finally in html file:
{{my_form.media}}
{% for item in my_form %}
<div class="form-group col-lg-2" id="dropdown-content">
{{item.label_tag}}
{{item}}
</div>
{% endfor %}
</div>
For more refer to this:
https://docs.djangoproject.com/en/4.0/topics/forms/

How do i import single object from django to a html template

i am creating a website with django and i have 2 models in it,1:Gifi(contains .gif images) and 2:categorite! When i click one of the .gif images i want to be sent to another html template where that image shows and information about it.I have done some coding and when i click the image i get to the html page but the problem is that no data from django gets imported to that html page,except the id on the url.I know the problem is so simple but i am new to this and i dont know the code.
This is the models:
from django.db import models
class categorite(models.Model):
name = models.CharField(max_length=100)
id = models.AutoField(primary_key=True)
class Gifi(models.Model):
foto = models.ImageField(upload_to='website/static/')
emri = models.CharField(max_length=100)
Source = models.CharField(max_length=100)
Kodet = models.CharField(max_length=12)
categoryId = models.ForeignKey(categorite, on_delete=models.CASCADE)
id = models.AutoField(primary_key=True)
This is views.py:
from django.shortcuts import render,get_object_or_404
from .models import Gifi,categorite
# Create your views here.
def home(request):
return render(request, 'website/home.html')
def categories(request):
content = {
'view': categorite.objects.all()
}
return render(request, 'website/categories.html',content)
def PostaCode(request):
return render(request, 'website/PostaCode.html')
def Contact(request):
return render(request, 'website/Contact.html')
def category(request,id):
content = {
'view': Gifi.objects.filter(categoryId_id=id),
}
return render(request, 'website/category.html',content)
def code(request,id):
content = {
'view': get_object_or_404(Gifi,pk=id)
}
return render(request, 'website/code.html',content)
This is the template where i click the image:
{% for gifi in view %}
<a href="{% url 'code' gifi.id %}" class="gif">
<img src="/static/{{gifi.foto}}" id="foto" alt="" >
<p id="source">Source: {{gifi.Source}}</p>
<p id="permbatjaa">Coding: {{gifi.Kodet}}</p>
</a>
{% endfor %}
This is the template where i need to get to, and where information about image should be(code.html):
<img src="/static/{{gifi.foto}}" id="foto" alt="" >
<p>{{gifi.emri}}</p>
It is passed a few days so you might get an answer already but Django's view function and the template are so simple, and you could write:
The models.py:
from django.db import models
class Categorite(models.Model):
# id field is already exists models.Model not necessary
#id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
class Gifi(models.Model):
foto = models.ImageField(upload_to='website/static/')
emri = models.CharField(max_length=100)
source = models.CharField(max_length=100)
kodet = models.CharField(max_length=12)
category = models.ForeignKey(Categorite, on_delete=models.CASCADE, related_name='gifis')
And the views.py:
def category(request, id):
# For the foreign key fields _id field auto created also
objs = Gifi.objects.filter(category_id=id)
return render(request, 'website/category.html', {'gifis': objs})
def code(request, id):
obj = get_object_or_404(Gifi, pk=id)
return render(request, 'website/code.html', {'gifi': obj})
And the template website/category.html
{% for gifi in gifis %}
<a href="{% url 'code' gifi.id %}" class="gif">
<img src="/static/{{gifi.foto}}" id="foto" alt="" >
<p id="source">Source: {{gifi.source}}</p>
<p id="permbatjaa">Coding: {{gifi.kodet}}</p>
</a>
{% endfor %}
And the template website/code.html
<img src="/static/{{gifi.foto}}" id="foto" alt="" >
<p>{{gifi.emri}}</p>
To meet PEP 8 spec, under_score recommended for the variable names, and CamelCase is recommended for the class names.
If you are new to Django, I highly recommend the official tutorial page would help a lot.

How to Update ImageField in Django?

i am new in Django. i am having issue in updating ImageField.i have following code
in models.py
class ImageModel(models.Model):
image_name = models.CharField(max_length=50)
image_color = models.CharField(max_length=50)
image_document = models.ImageField(upload_to='product/')
-This is My forms.py
class ImageForm(forms.ModelForm):
class Meta:
model = ImageModel
fields = ['image_name', 'image_color' , 'image_document']
in Html file (editproduct.html)
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
{% csrf_token %}
<input class="form-control" type="text" name="image_name" value="{{ singleimagedata.image_name}}">
<input class="form-control" type="file" name="image_document">
<button type="submit" class="btn btn-primary">UPDATE PRODUCT</button>
</form>
-myapp is my application name. {{singleimagedata}} is a Variable Containing all fetched Data
-urls.py
urlpatterns = [
path('productlist', views.productlist, name='productlist'),
path('addproduct', views.addproduct, name='addproduct'),
path('editimage/<int:id>', views.editimage, name='editimage'),
path('updateimage/<int:id>', views.updateimage, name='updateimage'),
]
and Here is My views.py
def productlist(request):
if request.method == 'GET':
imagedata = ImageModel.objects.all()
return render(request,"product/productlist.html",{'imagedata':imagedata})
def addproduct(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.add_message(request, messages.SUCCESS, 'Image Uploaded')
return redirect('/myapp/productlist')
else:
imageform = ImageForm()
return render(request, "product/addproduct.html", {'imageform': imageform})
def editimage(request, id):
singleimagedata = ImageModel.objects.get(id=id)
return render(request, 'product/editproduct.html', {'singleimagedata': singleimagedata})
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
My image Upload is working fine.i can not Update image while updating data.rest of the data are updated.i don't know how to update image and how to remove old image and put new image into directory.
I think you missed the enctype="multipart/form-data", try to change:
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
into;
<form method="POST" enctype="multipart/form-data" action="{% url 'updateimage' id=singleimagedata.id %}">
Don't miss also to add the image_color field to your html input.
Because, in your case the image_color field model is designed as required field.
To remove & update the old image file from directory;
import os
from django.conf import settings
# your imported module...
def updateimage(request, id): #this function is called when update data
old_image = ImageModel.objects.get(id=id)
form = ImageForm(request.POST, request.FILES, instance=old_image)
if form.is_valid():
# deleting old uploaded image.
image_path = old_image.image_document.path
if os.path.exists(image_path):
os.remove(image_path)
# the `form.save` will also update your newest image & path.
form.save()
return redirect("/myapp/productlist")
else:
context = {'singleimagedata': old_image, 'form': form}
return render(request, 'demo/editproduct.html', context)
I had a similar issue while updating the profile_pic of user. I solved this with the following code I think this might help:
Models.py
class Profile(models.Model):
# setting o2o field of user with User model
user_name = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True)
first_name = models.CharField(max_length=70, null=True, blank=True)
last_name = models.CharField(max_length=70, null=True, blank=True)
profile_pic = models.ImageField(upload_to="images", blank=True, null=True,)
def __str__(self):
return str(self.user_name)
forms.py
class ProfileEditForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
# excluding user_name as it is a one_to_one relationship with User model
exclude = ['user_name']
views.py
#login_required(login_url='login')
def edit_profile(request, id):
username = get_object_or_404(Profile, id=id)
extended_pro_edit_form = ProfileEditForm(instance=username)
if request.method == "POST":
extended_pro_edit_form = ProfileEditForm(request.POST, request.FILES, instance=username)
if extended_pro_edit_form.is_valid():
extended_pro_edit_form.save()
next_ = request.POST.get('next', '/')
return HttpResponseRedirect(next_)
context = {'extended_pro_edit_form': extended_pro_edit_form}
return render(request, 'edit_profile.html', context)
edit-profile.html
<form action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{{ extended_pro_edit_form.as_p }}
{{ extended_pro_edit_form.errors }}
<!--To redirect user to prvious page after post req-->
<input type="hidden" name="next" value="{{ request.GET.next }}">
<button type="submit">UPDATE</button>
</form>
Answer from #binpy should solve your problem. In addition to your second answer, you could do:
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
data.image_document.delete() # This will delete your old image
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
Check delete() method on django docs.
some times something like cached old image is not replaced in the front-end so you might just need to forces refresh by pressing CTRL + F5 or clear your browsing history.
the answer given by #binpy is a needed update so that the files are passed to the back-end.

How to implement unique together in Django

im working on a sales team project where i'm trying to implement a function to upload their daily visit plan. While uploading i want to put a validation that, if visit for one customer is already uploaded then for same another wouldn't be uploaded and would raise a error like" Visit plan for this customer already exists on this date". I have read some where that unique together would help me to validate but im not sure how to use unique together in View. please find the below codes for your reference and help. Thanks in advance
Model:
class BeatPlan(models.Model):
beat_id = models.CharField(unique=True, max_length=15, null=True)
beat_dealer = models.ForeignKey(Dealer, null=True, on_delete=models.SET_NULL)
beat_user = models.ForeignKey('account.CustomUser', null=True, on_delete=models.SET_NULL)
beat_stake_holder = models.ForeignKey(StakeHolder, null=True, on_delete=models.SET_NULL)
beat_date = models.DateField(null=True)
create_date = models.DateField(null=True)
beat_status = models.CharField(choices=(('Not visited', 'Not visited'), ('Visited', 'Visited')),
default='Not visited', max_length=40, null=True)
beat_location = models.CharField(max_length=200, null=True)
beat_type = models.CharField(choices=(('Not planned', 'Not planned'), ('Planned', 'Planned')), max_length=50,
null=True)
beat_reason = models.CharField(max_length=200, null=True)
class Meta:
unique_together = ('beat_date', 'beat_dealer')
def __str__(self):
return str(self.beat_user) + str(self.beat_dealer) + str(self.beat_date)
View:
def upload_beat(request):
global u_beat_dealer, beat_user_id, beat_date
template = "upload_beat.html"
data = BeatPlan.objects.all()
l_beat = BeatPlan.objects.last()
l_beat_id = l_beat.id
print(l_beat_id)
current_month = datetime.datetime.now().strftime('%h')
# prompt is a context variable that can have different values depending on their context
prompt = {
'order': 'Order of the CSV should be name, email, address, phone, profile',
'profiles': data
}
# GET request returns the value of the data with the specified key.
if request.method == "GET":
return render(request, template, prompt)
csv_file = request.FILES['file']
# let's check if it is a csv file
if not csv_file.name.endswith('.csv'):
messages.error(request, 'THIS IS NOT A CSV FILE')
data_set = csv_file.read().decode('UTF-8')
# setup a stream which is when we loop through each line we are able to handle a data in a stream
io_string = io.StringIO(data_set)
next(io_string)
for column in csv.reader(io_string, delimiter=',', quotechar="|"):
u_beat_user_id = column[0]
u_beat_dealer = column[1]
beat_date = column[2]
print(u_beat_user_id)
if StakeHolder.objects.filter(unique_id=u_beat_user_id).exists():
user_id = StakeHolder.objects.get(unique_id=u_beat_user_id)
beat_user_id = user_id.id
if Dealer.objects.filter(dealer_code=u_beat_dealer).exists():
dealer_id = Dealer.objects.get(dealer_code=u_beat_dealer)
u_beat_dealer = dealer_id.id
l_beat_id += 1
u_beat_id = current_month + str(l_beat_id)
newBeatPlan = BeatPlan(beat_id=u_beat_id, beat_dealer_id=u_beat_dealer,
beat_stake_holder_id=beat_user_id,
beat_date=beat_date)
newBeatPlan.save()
messages.success(request, ' Beat added')
else:
messages.error(request, 'Dealer id does not exists')
else:
messages.error(request, "Unique ID doesn't exists")
context = {'beat_user': beat_user_id, 'dealer_code': u_beat_dealer, 'visit_date': beat_date}
return render(request, template, context)
Template:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h3 style="margin-left: 10px">Upload Beat</h3>
<div class="row" style="margin-left: 5px">
<div class="col-md-6">
<hr>
{{ order }}
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<label for="file1"> Upload a file</label>
<input type="file" id="file1" name="file" required><br><br><br><br><br>
<small>Only accepts CSV files</small>
<button class="btn btn-primary if-error-not-found" type="submit"
name="submit">Upload</button>
<a href="{% url 'beatplan' %}">
<div class="btn btn-primary back-button">Back</div>
</a>
</form>
<br>
<br>
</div>
unique_together validates the data that is saved on the database. However, you can still submit forms where those 2 fields are not unique and get an error on your backend. What you need to do is to handle that error manually. Django forms have a method add_error(field, error). However, as I see, you do not use them, so you can just add an error parameter while rendering your template. Manually check if the customer has an input for that date, and add that error without saving anything to your database. Must look like this.
context['error'] = false
if YourModel.objects.filter(fields1=field1, field2=field2).exists():
# your code that does not save anything
context['error'] = true
return render(request, template, context)
And handle the error on your template however you want.
unique_together will make sure that whatever you do, invalid data is not saved, so keep it.

Categories