Change pending status to submitted after uploading of file in django - python

I am creating an assignment management system where students are uploading their assignments and the status of assignments are pending before uploading. I want to change the status when the assignment is saved at backend and change the status to submitted.
template code
<tr>
<td>{{assignment.assignment_date}}</td>
<td>{{assignment.assignment_creator}}</td>
<td>{{assignment.assignment_title}} </td>
<td>
<form enctype="multipart/form-data" action="{% url 'assignment' %}" method="POST">
{% csrf_token %}
<input required type="file" name="inputFile" id="" placeholder="upload">
<button>Upload</button>
{{s.assignment_status}}
</form>
</td>
<td> <span class="bg-success text-white">Pending </span></td>
</tr>
views.py
print('file uploaded')
if request.method == "POST":
print('file uploaded Post')
uploaded_file = request.FILES['inputFile']
print(uploaded_file)
student = Student.objects.get(student_username=request.user)
std_instance = student
document = Submissions.objects.create(submitted_by=std_instance,
submission_file=uploaded_file)
document.save()
print('saved')
models.py
class Assignment(models.Model):
assignment_creator = models.ForeignKey(Teacher, on_delete=models.CASCADE)
assignment_title = models.CharField(max_length=30)
assignment_details = models.TextField()
assignment_date = models.DateField(auto_now_add=True)
assignment_status = models.BooleanField(default=False)
class Submissions(models.Model):
submitted_by = models.ForeignKey(Student, on_delete=models.CASCADE)
submission_file = models.FileField(null=False)
submitted_to = models.ForeignKey(
Teacher, on_delete=models.CASCADE, null=True)

I would have assignment_title as a foreign key and assignment_status in the submission model. Then you just changed assignment_status to true right before document save.
I’m assuming multiple students will be getting the same assignments.

Related

How can I get a Field Id from a Related Django Model

I am working on a Django project where and I want to get an ID of a Related model with a OneToOne attributed so I can edit the profile of the user with his related Profile but all I get in return is Field 'id' expected a number but got 'GANDE1'.
Here are my Models:
class Profile(models.Model):
customer = models.OneToOneField(User, on_delete=models.CASCADE, null = True)
surname = models.CharField(max_length=20, null=True)
othernames = models.CharField(max_length=40, null=True)
gender = models.CharField(max_length=6, choices=GENDER, blank=True, null=True)
address = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=11, null=True)
image = models.ImageField(default='avatar.jpg', blank=False, null=False, upload_to ='profile_images',
)
#Method to save Image
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
#Check for Image Height and Width then resize it then save
if img.height > 200 or img.width > 150:
output_size = (150, 250)
img.thumbnail(output_size)
img.save(self.image.path)
def __str__(self):
return f'{self.customer.username}-Profile'
class Account(models.Model):
customer = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
account_number = models.CharField(max_length=10, null=True)
date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return f' {self.customer} - Account No: {self.account_number}'
Here is my Views:
def create_account(request):
#Search Customer
if searchForm.is_valid():
#Value of search form
value = searchForm.cleaned_data['value']
#Filter Customer by Surname, Othernames , Account Number using Q Objects
user_filter = Q(customer__exact = value) | Q(account_number__exact = value)
#Apply the Customer Object Filter
list_customers = Account.objects.filter(user_filter)
else:
list_customers = Account.objects.all()
context = {
'customers':paged_list_customers,
}
return render(request, 'dashboard/customers.html', context)
Here is how I displayed list of accounts in my Template:
{% for customer in customers %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ customer.account_number }}</td>
{% if customer.customer.profile.surname == None %}
<td> <a class="btn btn-danger" href=" {% url 'update-customer' customer.customer.id %} ">Click to Enter Customer Personal Details.</a> </td>
{% else %}
<td>{{ customer.customer.profile.surname }} {{ customer.customer.profile.othernames }}</td>
<td>{{ customer.customer.profile.phone }}</td>
<td><a class="btn btn-success btn-sm" href="{% url 'account-statement' customer.id %}">Statement</a></td>
<td><a class="btn btn-danger btn-sm" href="{% url 'dashboard-witdrawal' customer.id %}">Withdraw</a></td>
<th scope="row"><a class="btn btn-success btn-sm" href="{% url 'create-deposit' customer.id %}">Deposit</a></th>
{% endif %}
</tr>
{% endfor %}
Here is my Customer Update View where I am having issues:
def update_customer_profile(request, pk):
#get logged in user
user = request.user
#check if logged in user is staff
try:
customer_user = User.objects.get(id=pk)
except User.DoesNotExist:
return redirect('user-register')
else:
count_users = User.objects.count()
#Get the Customer User's Profile from the User above
user_profile = Profile.objects.get(customer=customer_user.username)
Please, understand that I want to get the ID of a User and MATCH it with the one in his profile record so I can be able to edit his profile record. And also note that the customer profile is automatically created using signals upon user registration.
If you already have the User object, then simply use the relation between them:
try:
customer_user = User.objects.get(id=pk)
except User.DoesNotExist:
...
else:
...
user_profile = customer_user.profile
You don't need to query database separately. It's exaclty what relations are for.

Python Django: Insert dynamic form records to db

It is a Medical Lab Software solution. A user makes lab investigation request that is unique to a patient’s encounter, I.e., a patient can have 1 or more request per encounter. This uniqueness is denoted by the encounter_id.
The challenge now is the ability to send the results back to the requester.
I am able to display all requests per encounter_id on a template but unable to return the result since each result is tied to a particular investigation. This is largely because I have a limited knowledge on JS. My current approach can only submit one record, usually the last record
Here’s the URL that displays the result template: https://smart-care.herokuapp.com/labs/lab_results/1/
Here’s the django template:
<div class="container">
<form id="myForm" method="POST" action="">{% csrf_token %}
{% for request in lab_request %}
{{ request.test }}: <input type="text" class="result" id="{{ request.test.id }}" name="test_id"> <br>
{% endfor %}
<br><br>
<button>Send Result</button>
</form>
</div>
# Here’s my view:
def lab_results_view(request, enc_id):
lab_request = LabRequest.objects.filter(encounter_id=enc_id, done=False, decline=False)
if request.POST.get('test_id'):
for req_id in request.POST:
results = request.POST.get(req_id, False)
print("results = ",results)
template = "labs/lab_results.html"
context = {"lab_request":lab_request}
return render(request, template, context)
The models:
class LabRequest(models.Model):
encounter = models.ForeignKey(PatientEncounter, on_delete=models.CASCADE, blank=True, null=True)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE, blank=True, null=True)
test = models.ForeignKey(LabTest, on_delete=models.CASCADE)
accepted = models.BooleanField(default=False)
decline = models.BooleanField(default=False)
done = models.BooleanField(default=False)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return str(self.patient.id)
class LabResult(models.Model):
lab_request = models.ForeignKey(LabRequest, on_delete=models.CASCADE, blank=True, null=True)
result = models.CharField(max_length=225)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return str(self.result)
Thanks as I anticipate your kind response.
The problem that Django handles form elements based on name attribute and not the id attribute so this means you need to change name per request and on the view side you loop on all keys in request.POST like
for req_id in request.POST:
result = Request.POST[req_id]
Edit: for the template
<div class="container">
<form id="myForm" method="POST" action="">{% csrf_token %}
{% for request in lab_request %}
{{ request.test }}: <input type="text" class="result" id="{{ request.test.id }}" name="{{ request.test.id }}">
<br> {% endfor %} <br><br>
<button>Send Result</button>
</form> </div>
Edit2: The view shall be like this
def lab_results_view(request, enc_id):
lab_request = LabRequest.objects.filter(encounter_id=enc_id, done=False, decline=False)
if request.method == "POST":
for req_id in request.POST:
results = request.POST.get(req_id)
print("results = ",results)
template = "labs/lab_results.html"
context = {"lab_request":lab_request}
return render(request, template, context)

How to Store Image File in Django from html form using Post request?

I am working on a project that require an profile pic.
I created a Model in Django UserProfile
class UserProfile(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True)
image = models.ImageField()
adress = models.CharField(default='', max_length=150, blank=True)
cnic = models.IntegerField(null=True)
contact = models.IntegerField(null=True)
city = models.CharField(max_length=50, null=True)
about = models.CharField(max_length=50, null=True)
location = models.CharField(max_length=150, null=True)
subscriptions = models.IntegerField(null=True)
rating = models.IntegerField(null=True)
I am currently fetching data from HTML
<form action="/users/profile/" method="POST" style="display: contents;">
{% csrf_token %}
<div class="col-md-3 border-right">
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
{% if profile.image %}
<img class="rounded-circle mt-5" src="/media/{{profile.image}}"
style="width: 200px;max-height: 300px;" id='image'>
{% else %}
<img class="rounded-circle mt-5"
src="https://image.shutterstock.com/image-vector/house-not-available-icon-flat-260nw-1030785001.jpg"
style="width: 200px;max-height: 300px;" id='image'>
{% endif %}
<label for="upload-photo" class="uploadImgLabel btn btn-outline-danger w-75">Browse</label>
<input type="file" name="photo" id="upload-photo" required />
<span class="font-weight-bold">{{user}}</span><span
class="text-black-50">{{user.email}}</span><span>
</span>
</div>
All the other field is working correctly and I can visualize data by printing in views.py
if request.method == 'POST':
photo = request.POST.get('photo')
fname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
contact = request.POST.get('contact')
address = request.POST.get('address')
email = request.POST.get('email')
country = request.POST.get('country')
cnic = request.POST.get('cnic')
city = request.POST.get('city')
user = User.objects.get(username=request.user)
user.first_name = fname
user.last_name = lastname
user.email = email
user.save()
obj = models.UserProfile.objects.get(user=request.user)
obj.adress = address
# obj.image = photo, <---- Here is the problem
obj.contact = contact
obj.city = city
obj.cnic = cnic
obj.subscriptions = 100
obj.rating = 4
obj.save()
I am unable to save data in obj.save() its shows an error when I try to put an image like obj.image=photo
Error AttributeError at /users/profile/
'tuple' object has no
attribute '_committed
I am swore it is because of the image if i visualize image (print(photo)) its shows file name 'Image.jpg'
'
There are two parts to an image upload.
Firstly, the encoding of the form has to be set to "multipart/form-data"
You can do this easily with
enctype="multipart/form-data"
Why do we have to do this? Here is a good place to read more about it.
Now because your data is not being sent just like a text or JSON, you cannot access it using your normal request.POST.get('photo')
You've to receive it using request.FILES.get('photo') You can read more about it in the Django docs
A bonus -
Defining your image column in the model would work a lot better if you would specify a directory, something like this.
image = models.ImageField(upload_to="%Y/%m/%d")
I believe you need to use request.FILES['photo'] to access the uploaded file from the form.
the file is not saved in the database only the path and will be uploaded to your MEDIA_ROOT directory

How to update multiple objects with one form in Django?

I create a customer model and a function for assign a customer to a user. Assign function is update user field in Customer model.
This Customer model has a country field. I want to assign the customers in the same country to a user with one form. For doing that I have listing all countries and a form for assign operation? How can I do that?
Edit: Now, I can get country name and the user for assigning. How can I use these attributes and update the objects (Customer) with chosen country and user.
models.py
class Customer(models.Model):
customer_name = models.CharField(max_length=20)
country = models.ForeignKey(Country, on_delete=models.CASCADE, null=True, unique=False)
...
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, blank=True, null=True)
class Country(models.Model):
REGION = [
('Northwest Europe', 'Northwest Europe'),
('Southwest Europe', 'Southwest Europe'),
...
]
country_name = models.CharField(max_length=30)
country_code = models.CharField(max_length=5)
views.py
def country_customer_list(request):
current_user = request.user
userP = UserProfile.objects.get_or_create(username=current_user)
customer_list = Customer.objects.filter(company=userP[0].company)
countries = Customer.objects.values_list('country__country_name', flat=True).distinct()
form = CountryForm(request.POST or None)
if request.POST:
country_form = request.POST.get('country_form', None)
user = request.POST.get('user', None)
form.save()
print(country_form)
print(user)
return redirect('user:customer_countries')
context = {
'customer_list': customer_list,
'countries': countries,
'form': form
}
return render(request, 'country_customer_list.html', context)
country_customer_list.html*
<table id="multi-filter-select" class="display table table-striped table-hover grid_" >
<thead>
<tr>
<th>Country</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
{% for country in countries %}
<tr>
<td>{{country}}</td>
<td>
<button type="button" class="btn btn-info btn-block" data-toggle="collapse" data-target="#demo{{ forloop.counter }}"> Assign </button>
<div id="demo{{ forloop.counter }}" class="collapse">
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="hidden" name="country_form" value="{{ country }}">
<button type="submit" class="btn btn-primary btn-sm">Assign</button>
</form>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
forms.py
class CountryForm(forms.ModelForm):
class Meta:
model = Customer
fields = ('user',)
Populate Country models with your choise, and they will appear in the template
Change models
class Country(models.Model):
country_name = models.CharField(max_length=30)
country_code = models.CharField(max_length=5)
def __str__(self):
return str(self.country_name) + ' ' + str(self.country_code)
forms.py
class CountryForm(forms.ModelForm):
class Meta:
model = Customer
fields = ('user','country',)
in template
{{form.country}}

django modifying database object

I am working on an attendance management system. I want to modify attendance of students.
class Subject(models.Model):
subject_name = models.CharField(max_length=20)
#attendance = models.ForeignKey(Attendance, on_delete = models.DO_NOTHING)
attendance = models.IntegerField(default=0)
def __str__(self):
return self.subject_name
class Section(models.Model):
section_name = models.CharField(max_length=20)
subject = models.ManyToManyField(Subject)
def __str__(self):
return self.section_name
class Student(models.Model):
rollno = models.IntegerField()
name = models.CharField(max_length=20)
section = models.ForeignKey(Section, on_delete = models.DO_NOTHING, default=0)
def __str__(self):
return str(self.rollno) + self.name
Here is my template. (Student.html)
{% for i in data %}
<tr>
<td>{{ i.rollno }}</td>
<td>{{ i.name }}</td>
<td> <button class='btn btn-danger' id='{{i.rollno}}' on click = "{{ i.section.subject.get(subject_name='java').attendance)|add:1 }}">
</td>
</tr>
{% endfor %}
I am getting error in using .get() method in template. I want to add (+1) attendance on a button click.
I strongly suggest to go through Django Tutorial. You will learn Django MVC concepts and able to achieve what you asked easily. The below code will help you get started.
views.py
def increment_attendance(request, subject_id):
"""Increment Attendance for a Subject"""
subject = Subject.objects.get(id=subject_id)
# check if record exists
if not subject:
raise Http404("Invalid subject_id")
# can also use only get_object_or_404(Subject, pk=subject_id)
# increment attendance
subject.attendance += 1
# save / commit to database
subject.save()
# redirec to 'some' page or previous page?
return redirect('top')
add this path to your urls.py
path('subject/<int:day>/increment_attendance', views.increment_attendance, name='increment_attendance')
template
<a class="btn btn-danger" id="{{i.rollno}}" href="{% url 'increment_attendance' subject_id=subject_id" %}"></a>

Categories