django modifying database object - python

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>

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.

Change pending status to submitted after uploading of file in django

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.

Saving Django form data to a User

I'm creating a website for general education uses and one of the features is a calendar section where I would like the user to be able to store their events but then when they login they can view the events they created. This is for an academic assignment.
I can't seem to get this calendar to link to a user field. I would like each record in the calendar table to have a user_id which will be the same as the current_user. I understand that you can user the django default user auth but i have not done that due to not knowing about it and by the time I realized it was too late.
So all I really need to do is when the form is valid, I need to assign the value of the current_user id as the value for student in the calendar table. But for some reason I keep getting problems and the form isn't detected as being valid or the program just doesn't assign the value.
My main objective is to have each user view their own calendar. I don't mind changing the current student field to a foreign key field
Student.Views
def calendar(request):
student_obj = Student.objects.get(student_name=current_user)
print(student_obj)
if request.method == 'POST':
form = EventsForm(initial={'student': '3'} or request.POST)
print(form.errors)
if form.is_valid():
form.save()
all_events = Events.objects.filter(student=student_obj.id)
messages.success(request, 'Event Has Been Added')
return render(request, 'Student/calendar.html', {'all_events': all_events})
else:
messages.success(request, 'Event Has NOT Been Added')
all_events = Events.objects.filter(student=student_obj.id)
return render(request, 'Student/calendar.html', {'all_events': all_events})
Student.Models
class Student(models.Model):
student_name = models.CharField(max_length=59, default=None)
username = models.CharField(max_length=59)
password = models.CharField(max_length=59)
age = models.PositiveIntegerField()
date_of_birth = models.DateField(max_length=10)
form = models.CharField(max_length=3)
email = models.EmailField(max_length=59)
present = models.PositiveIntegerField(default=0)
late = models.PositiveIntegerField(default=0)
absent = models.PositiveIntegerField(default=0)
maths_grade = models.PositiveIntegerField(default=0)
english_grade = models.PositiveIntegerField(default=0)
science_grade = models.PositiveIntegerField(default=0)
behaviour_level = models.PositiveIntegerField(default=0)
def __str__(self):
return self.student_name
class Events(models.Model):
student = models.CharField(max_length=200)
date = models.DateField(max_length=10, default=None)
event = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
Student.forms
class EventsForm(forms.ModelForm):
class Meta:
model = Events
fields = ["event", "completed", "date", "student"]
Calendar Template
<div class="container" style="color: #fff">
<br/>
{% if messages %}
{% for message in messages %}
<div class="alert alert-warning alert-dismissible" roles="alert">
<button class="close" data-dismiss="alert">
<small>x</small>
</button>
{{ message }}
</div>
{% endfor %}
{% endif %}
{% if all_events %}
<div>
<table class="table table-dark table-bordered">
{% for things in all_events %}
{% if things.completed %}
<style>
.striker {
text-decoration: line-through;
text-color: black;
}
</style>
<tr class="table-danger striker">
<td style="color: black">{{ things.date }}</td>
<td>{{ things.event }}</td>
<td><center>Delete</center></td>
</tr>
{% else %}
<tr>
<td>{{ things.date }}</td>
<td >{{ things.event }}</td>
<td><center>Delete</center></td>
</tr>
{% endif %}
{% endfor %}
</table>
</div>
{% endif %}
Change form.save() to
event = form.save(commit=False)
event.student = request.user
event.save()
That'll do it.
Don't make it complicated, this have to be easier. If I understood what are you trying to do I would create my models as following:
#model.py
from django.db.models.signals import post_save
from django.dispatch import receiver
class Student(models.Model):
user= models.OneToOneField(User, null=True) #student is user
#Define student fields...
class Calendar(models.Model):
#Defile calender fields here along with its default values ...
user = models.OneToOneField(Student)
'''
this signal populate calender table with user_id along with its
calender fields
'''
#receiver(post_save, sender=Student)
def create_student_calender(sender, instance, created, **kwargs):
if created and not kwargs.get('raw', False):
calendar = Calender(user=instance)
calendar.save()
class Event(models.Model):
calender = models.ForeignKey(Callender, null=True)
# Define event fields here ...
With models structure like this, whenever student create account Calendar model will be populated saved with calendar fields and student's id field.
So how do student create their events? Simply create an a inlineformset_factory form to create events on each student's calendar like this:
#form.py
from django.forms import inlineformset_factory
from django import forms
class EventForm(forms.ModelForm):
#Events form fields here...
class Meta:
model = Event
fields = ["Event's field"]
EventFormSet = inlineformset_factory(Calender, Event, form=EventForm,
max_num=1, can_delete=False)
Render this formset with a view for student to create their events,the formset automatically associate student's event to calendar.
So you can add your logic to do more.

Inserting multiple related model values in template with for loop

I am trying to post multiple values from different models in a for loop in a template. It is not doing what I am planning. I want to display a count of LeadActions that belong to Leads in a table. I did comment the part out that is not working as well. The table should display the list of Leads and the the count of how many overdue actions(LeadActions) there are for that specific lead.
My View
class LeadListView(LoginRequiredMixin, generic.ListView):
login_url = '/scrty/login/'
template_name = "nodiso/leadslist.html"
model = models.Leads
def get_context_data(self, **kwargs):
ctx = super(LeadListView, self).get_context_data(**kwargs)
ctx['actions']= models.LeadActions.objects.all()
return ctx
def get_queryset(self):
return models.Leads.objects.filter(company=self.request.session['compid'],archive=False)
My template
<table class="table">
<thead>
<th>Name</th>
<th>Overdue Tasks</th>
<th>Total Tasks</th>
</thead>
{% for lead in leads_list %}
{# {% for action in action_list %}#}
<tr>
<td>{{lead.name}}</td>
<td><span class="badge">{{ actions.name|length }}</span></td>
<td><span class="badge">42</span></td>
</tr>
{# {% endfor %}#}
{% endfor %}
</table>
The Models
class LeadActions(models.Model):
lead = models.ForeignKey(Leads)
name = models.CharField(max_length=265)
crdate = models.DateField(auto_now_add=True)
Duedate = models.DateField()
creator = models.CharField(max_length=265)
overdue = models.IntegerField(null=True,blank=True)
def __str__(self):
return self.name
class Leads(models.Model):
company = models.ManyToManyField(Company)
user = models.ManyToManyField(settings.AUTH_USER_MODEL)
name = models.CharField(max_length=265)
email = models.EmailField(max_length=265)
tel = models.IntegerField()
archive = models.BooleanField(default=False)
dateenq = models.DateField(auto_now_add=True,null=True)
def get_absolute_url(self):
return reverse('nodisoapp:leadlist')
def __str__(self):
return self.name
You shouldn't be sending the list of actions from the view. Instead, in the template, you can access {{ lead.leadactions_set.count }} to give the count of LeadActions related to each Lead in the loop.

Django Manytomanyfield returns the same project many times

On my Django site, I have two models - one is Project, which a user can create, and one is Access, where a user can add other users for access to the project. The Access model contains a manytomanyfield where the additional users are stored. I can add users and remove users from this field and it works site-wide (ie if I add a user onto the project, then log into that user's account, I can see it) but if I add more than one collaborator, I will start to see multiple iterations of that project in my project stream. It seems to me that Django is showing me the project for each user in the access_list as opposed to just once.
Models.py:
class Project(models.Model):
project_name = models.CharField(max_length=200)
project_description = models.TextField(null=True, blank=True)
project_thumbnail = models.FileField(upload_to=get_upload_file_name, null=True, blank=True)
project_pubdate = models.DateTimeField(default=timezone.now)
created_by = models.ForeignKey(User)
def __unicode__(self):
return self.project_name
def save(self):
if not self.id and not self.project_description:
return
super(Project, self).save()
Access.objects.get_or_create(project=self)
if self.project_thumbnail:
size = 200, 200
image = Image.open(self.project_thumbnail)
image.thumbnail(size, Image.ANTIALIAS)
fh = storage.open(self.project_thumbnail.name, "w")
format = 'png' # You need to set the correct image format here
image.save(fh, format)
fh.close()
def get_project_thumbnail(self):
thumb = str(self.project_thumbnail)
if not settings.DEBUG:
thumb = thumb.replace('assets/', '')
return thumb
class Access(models.Model):
project = models.ForeignKey(Project)
access_list = models.ManyToManyField(User)
pubdate = models.DateTimeField(default=timezone.now)
Views.py:
#login_required
def projects(request):
thisuser = request.user
if Access.objects.filter(Q(access_list=thisuser) | Q(project__created_by=thisuser)).exists():
projects_by_username = Access.objects.filter(Q(access_list=thisuser) | Q(project__created_by=thisuser)).order_by('-project__project_pubdate')
else:
projects_by_username = None
return render_to_response('projects.html',
{'projects_by_username': projects_by_username,
'user': thisuser })
projects.html:
{% for project in projects_by_username %}
<table width="100%" cellpadding="5">
<tr>
<td width="25%" rowspan="3"><a href="/projects/get/{{ project.project.id }}">
{% if project.project.project_thumbnail %}
<img src="{% get_static_prefix %}{{project.project.project_thumbnail}}" width="150" /></td>
{% endif %}
</a></td>
<td width="75%" valign="top"><div class="heading16px">{{ project.project.project_name }}</div></td>
</tr>
<tr>
<td>{{ project.project.project_description }}</td>
</tr>
<tr>
<td> </td>
</tr>
</table>
{% endfor %}

Categories