Perform update query after delete in django cbv - python

I'm trying to update other table after successful delete of of data. Below is my
views.py
class AttendeeDeleteView(DeleteView):
model = Attendee
success_url = reverse_lazy('index')
def get_form_kwargs(self):
id = self.kwargs['id'] # get value of enr
Payment.objects.filter(pk=id).update(registered=0)
In my urls.py
url(r'^delete/(?P<pk>\d+)$', AttendeeDeleteView.as_view(template_name="includes/attendee_delete.html"), name='attendee_delete',),
My Current code successfully delete the item but failed to update the other table.
my model
class Payment(models.Model):
id = models.AutoField(primary_key=True)
payee = models.CharField(max_length=200, blank=True, null=True)
contact = models.CharField(max_length=200,blank=True, null=True)
batch = models.CharField(max_length=200, null=True, blank=True)
ticketNumber = models.CharField(max_length=200)
ticketType = models.CharField(max_length=200, choices=TICKET_CHOICES, default='paid')
date = models.DateField('Date Paid (MM/DD/YYYY)', max_length=200, null=True, blank=True)
remarks = models.CharField(max_length=200 ,blank=True, null=True)
registered = models.BooleanField(default=False)
def __str__(self):
return self.payee
class Attendee(models.Model):
id = models.AutoField(primary_key=True)
payment = models.OneToOneField(Payment, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200)
batch = models.CharField(max_length=200, blank=True, null=True)
department = models.CharField(max_length=200, choices=DEPT_CHOICES, default='')
remarks = models.CharField(max_length=200, blank=True, null=True)
UPDATE 1:
I followed this came up with
def get(self, request, *args, **kwargs):
id = kwargs['pk'] # get value of enr
context = Payment.objects.filter(pk=id).update(registered=0)
return self.render_to_response(context)
but it returned context must be a dict rather than int.

I think def get_form_kwargs(self): doesn't executed, because it used for FormMixin. But, you can also handle it inside get() function.
def get(self, request, *args, **kwargs):
attendee = self.get_object()
Payment.objects.filter(pk=attendee.payment.pk).update(registered=0)
context = self.get_context_data(object=attendee)
return self.render_to_response(context)
See this https://ccbv.co.uk/projects/Django/1.11/django.views.generic.edit/DeleteView/ for more..
Edit:
This solution below if still getting a problem when using get() method.
from django.http import HttpResponseRedirect
....
def delete(self, request, *args, **kwargs):
"""
Calls the delete() method on the fetched object and then
redirects to the success URL.
"""
self.object = self.get_object()
success_url = self.get_success_url()
Payment.objects.filter(pk=self.object.payment.pk).update(registered=0)
self.object.delete()
return HttpResponseRedirect(success_url)

Related

RESOLVED: Django Admin: How to display currently logged in user's ID on the display list?

I am very new to Django and trying to make my first project. I find it difficult to display currently logged in user's ID on the list in Django admin model.
I found a solution of how to get the appriopriate ID thanks to Shang Wang (Django admin: Get logged In users id in django)
But I don't know how to display this ID on the list, right next to Patient ID, Unit and Create time (mentioned in the code below).
My admin.py looks like this :
class GeneralAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
super(GeneralAdmin, self).save_model(request, form, obj, change)
list_display = ('id_patient', 'unit', 'create_time')
search_fields = ('id_patient', 'unit', 'create_time')
readonly_fields = ('unit', 'Birth_date','create_time',)
Edit 2: my models.py file:
from django.db import models
from datetime import date, datetime
from django.contrib.auth.models import User
class Unit(models.Model):
id = models.AutoField(primary_key=True)
description = models.CharField(max_length=300)
class Patient(models.Model):
id = models.AutoField(primary_key=True, verbose_name='Patient ID')
unit = models.ForeignKey(Unit, on_delete=models.CASCADE)
Birth_date = models.DateField()
introducer = models.ForeignKey(User,
help_text = "This field will be calculated automatically",
blank=True, null=True, on_delete=models.CASCADE)
#here I try to get current user's ID
def save(self, *args, **kwargs):
self.introducer = User.username #here I get an error
super().save(*args, **kwargs)
class General(models.Model):
id = models.AutoField(primary_key=True)
id_patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
unit = models.ForeignKey(Unit, help_text = "This field will be calculated automatically", blank=True, null=True, on_delete=models.CASCADE)
Birth_date = models.DateField(blank=True, null=True, help_text = "This field will be calculated automatically")
create_time = models.DateTimeField(blank=True, null = True, default = datetime.now())
def save(self, *args, **kwargs):
self.Birth_date = self.id_patient.Birth_date
self.unit = self.id_patient.unit
super().save(*args, **kwargs)
class Primary_Treatment_EBRT(models.Model):
id = models.AutoField(primary_key=True)
unit = models.ForeignKey(Unit, help_text = "This field will be calculated automatically", blank=True, null=True, on_delete=models.CASCADE)
Birth_date = models.DateField(blank=True, null=True, help_text = "This field will be calculated automatically")
create_time = models.DateTimeField(blank=True, null = True, default = datetime.now())
id_patient = models.ForeignKey('Patient', on_delete=models.CASCADE)
def save(self,*args, **kwargs):
self.Birth_date = self.id_patient.Birth_date
self.unit = self.id_patient.unit
super().save(*args, **kwargs)
How to put obj.user's ID into list_display to display it on the list like id_patient, unit, or create_time?
Problem RESOLVED:
My admin.py change:
class PatientAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change, *args, **kwargs):
obj.user = request.user
obj.create_time = datetime.now()
super(PatientAdmin, self).save_model(request, obj, form, change, *args, **kwargs)
My models.py change:
create_time = models.DateTimeField(blank=True, null = True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True,
null=True, on_delete=models.CASCADE)

How to auto add a field in django admin model calculating age

is it possible to add an age field that is auto filled in the runtime based on another date of birth field at the django admin interface, i added a screenshot trying to explain more what i mean
my models.py
class FamilyMember(models.Model):
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
family_group = models.ForeignKey(FamilyGroup,
on_delete=models.CASCADE,
null=True,
blank=True)
name = models.CharField(max_length=100, null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
relationship = models.ForeignKey(Relationship, on_delete=models.PROTECT)
dependant_child_age_range = models.ForeignKey(DependantChildAgeRange,
null=True,
blank=True,
on_delete=models.PROTECT)
care_percentage = models.PositiveSmallIntegerField(
null=True, blank=True, validators=[
MaxValueValidator(100),
])
income = models.DecimalField(max_digits=6,
decimal_places=2,
null=True,
blank=True)
rent_percentage = models.PositiveSmallIntegerField(
null=True, blank=True, validators=[
MaxValueValidator(100),
])
admin.py
class FamilyMemberInline(admin.TabularInline):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
action = request.META['PATH_INFO'].strip('/').split('/')[-1]
if action == 'change':
transaction_id = request.META['PATH_INFO'].strip('/').split('/')[-2]
if db_field.name == "family_group":
kwargs["queryset"] = FamilyGroup.objects.filter(transaction=transaction_id)
return super(FamilyMemberInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
model = FamilyMember
extra = 0
def sufficient_info_provided (self, obj):
return obj.sufficient_information_provided
sufficient_info_provided.boolean = True
readonly_fields = ['sufficient_info_provided',]
Override your inline's get_queryset method to annotate the queryset with the calculation. The annotation will add an age attribute to each object in the queryset.
Then as you can see in the ModelAdmin.list_display documentation, you can include a string representing a ModelAdmin method that accepts one argument, the model instance. Inline's work in the same way but you must include the method in ModelAdmin.readonly_fields.
Putting it all together:
class FamilyMemberInline(admin.TabularInline):
...
fields = (..., 'get_age')
readonly_fields = ('get_age',)
def get_queryset(self, request):
return (
super().get_queryset(request)
.annotate(age=...)
)
def get_age(self, instance):
return instance.age

FieldError django

Please I need help, I dont know where the problem is coming from, please see the code below
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def post_feed_view(request, *args, **kwargs):
user = request.user
profiles = user.follow_user.all()
followed_users_id = []
if profiles.exists():
followed_users_id = [x.user.id for x in profiles]
followed_users_id.append(user.id)
queryset = Post.objects.filter(user__id__in=followed_users_id).order_by("-date_posted")
serializer = PostSerializer(queryset, many=True)
return Response(serializer.data, status=200)
I keep getting this error: Cannot resolve keyword 'user' into field. Choices are: author, author_id,
although, in my models, I dont have "User" what I have is "Author".
But I dont know where exactly to put in author. I think my problem is that i dont fully understand "request.user".
Please help!.
===========
This is the Profile and Follow models:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.CharField(max_length=245, null=True)
image = models.ImageField(default='default.png', upload_to='profile_pics')
interests = models.ManyToManyField(Category, related_name='interests_user')
stripe_customer_id = models.CharField(max_length=50, blank=True, null=True)
one_click_purchasing = models.BooleanField(default=False)
is_vendor = models.BooleanField(default=False)
# vendor
bvn = models.CharField(max_length=10, null=True, blank=True)
description = models.TextField(null=True, blank=True)
address = models.CharField(max_length=200, null=True, blank=True)
company = models.CharField(max_length=100, null=True, blank=True)
# follow_user = models.ManyToManyField('users.Follow')
def __str__(self):
return f'{self.user.username} Profile'
#property
def followers(self):
return Follow.objects.filter(follow_user=self.user).count()
#property
def following(self):
return Follow.objects.filter(user=self.user).count()
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
super().save()
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
class Follow(models.Model):
user = models.ForeignKey(User, related_name='user', on_delete=models.CASCADE)
follow_user = models.ForeignKey(User, related_name='follow_user', on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
old_instance = models.ForeignKey('Follow', blank=True, null=True, on_delete=models.CASCADE, editable=False)
def save(self, *args, **kwargs):
if self.pk is not None:
self.old_instance = Follow.objects.get(pk=self.pk)
super().save(*args,**kwargs)
def __str__(self):
return f"For: {self.user} // id: {self.id}"
class FollowerRelation(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile = models.ForeignKey("Profile", on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
Your Post model apparently has no user field, but an author field, so you can filter with:
queryset = Post.objects.filter(
author_id__in=followed_users_id
).order_by('-date_posted')
But that being said, you should not filter like that. Given your models you can do this in a single query and thus avoiding the N+1 problem. You can simply filter with:
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def post_feed_view(request, *args, **kwargs):
queryset = Post.objects.filter(
author__follow_user__user=request.user
).order_by('-date_posted')
serializer = PostSerializer(queryset, many=True)
return Response(serializer.data, status=200)

Matching query does not exist when update view is called in django

I have a custom user model from AbstractBaseUser and BaseUserManager. The user model is extended to a model called Employee. The employee model is related with(Foreignkey) two other model named WorkExperience and education. A single template form is designed with Employee, WorkExperience and Education modelform.
models.py:
class Employee(models.Model):
"""
Create employee attributes
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
e_id = models.IntegerField(unique=True, null=True)
first_name = models.CharField(max_length=128, null=True)
last_name = models.CharField(max_length=128, null=True)
gender_choices = (
('Male', 'Male'),
('Female', 'Female'),
)
......
#receiver(post_save, sender=UserProfile)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Employee.objects.create(employee_user=instance, email=instance.email)
instance.employee.save()
class WorkExperience(models.Model):
"""
Stores employee previous work experiences
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
employee = models.ForeignKey('Employee', related_name='we_employee', on_delete=models.CASCADE, null=True)
previous_company_name = models.CharField(max_length=128, null=True)
job_designation = models.CharField(max_length=128, null=True)
from_date = models.DateField(null=True)
to_date = models.DateField(null=True)
job_description = models.CharField(max_length=256, null=True)
class Education(models.Model):
"""
Stores employee education background
"""
employee_user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
employee = models.ForeignKey('Employee', related_name='edu_employee', on_delete=models.CASCADE, null=True)
institution_name = models.CharField(max_length=128, null=True)
degree = models.CharField(max_length=128, null=True)
passing_year = models.IntegerField(null=True)
result = models.DecimalField(max_digits=5, decimal_places=2, null=True)
I have a CreateView of this three models. I have three modelform. I implemented CRUD using this modelforms. My problem is in UpdateView. When I call UpdateView an error is showing stating WorkExperience matching query does not exist.I think the query is not correct.
views.py:
class EmployeeUpdateView(LoginRequiredMixin, UpdateView):
"""
Update a created a employee
"""
login_url = '/authentication/login/'
template_name = 'employee/employee_update_form.html'
form_class = EmployeeAddModelForm
work_form_class = WorkExperienceForm
education_form_class = EducationForm
context_object_name = 'employee'
model = Employee
queryset = Employee.objects.all()
# Override default get method
def get(self, request, *args, **kwargs):
id_ = self.kwargs.get("id")
employee_id = Employee.objects.get(id=id_)
work_info = WorkExperience.objects.get(employee=employee_id)
education_info = Education.objects.get(employee=employee_id)
form = self.form_class(instance=employee_id)
work_form = self.work_form_class(prefix='work_form', instance=work_info)
education_form = self.education_form_class(prefix='education_form',instance=education_info)
return render(request, self.template_name, {
'form': form,
'work_form': work_form,
'education_form': education_form,
'supervisor_assigned': employee_id.supervisor_select
}
)
# Override default post method
def post(self, request, *args, **kwargs):
id_ = self.kwargs.get("id")
employee_id = Employee.objects.get(id=id_)
work_info = WorkExperience.objects.get(employee=employee_id)
education_info = Education.objects.get(employee=employee_id)
form = self.form_class(request.POST, instance=employee_id)
work_form = self.work_form_class(request.POST, prefix='work_form', instance=work_info)
education_form = self.education_form_class(request.POST, prefix='education_form',instance=education_info)
# Check form validation
if form.is_valid() and work_form.is_valid() and education_form.is_valid():
instance = form.save()
work = work_form.save(commit=False)
education = education_form.save(commit=False)
work.employee = instance
education.employee = instance
work.save()
education.save()
return redirect('employee:employee-list')
return render(request, self.template_name, {
'form': form,
'work_form': work_form,
'education_form': education_form
}
)
urls.py:
urlpatterns = [
path('employee-list/', EmployeeListView.as_view(), name='employee-list'),
path('employee-add/', EmployeeAddView.as_view(), name='employee-add'),
path('employee-list/<int:id>/', EmployeeDetailView.as_view(), name='employee-detail'),
path('employee-list/<int:id>/update/', EmployeeUpdateView.as_view(), name='employee-update'),
How can I modify my query? i think my query is not correct.
you need to use foreign Key to use the employee id :
work_info = WorkExperience.objects.get(employee__id=employee_id)
I Hope it works fine

How to filter the additional model in DetailView?

class Source(models.Model):
Name = models.CharField(max_length=150)`enter code here`
Address = models.CharField(max_length=150)
Office_Phone = PhoneField(blank=True, help_text='Office phone number')
Main_Contact = models.CharField(max_length=150, blank=True, null=True)
Contact_Email = models.EmailField(max_length=254, blank=True, null=True)
Contact_Phone = PhoneField(blank=True, help_text='Main Contact phone number')
Billing_Contact = models.CharField(max_length=150, blank=True, null=True)
Billing_Email = models.EmailField(max_length=254, blank=True, null=True)
Billing_Phone = PhoneField(blank=True, help_text='Billing Contact phone number')
Notes = models.CharField(max_length=250, blank=True, null=True)
def __str__(self):
return self.Name
def get_absolute_url(self):
return reverse('sources-detail', kwargs={'pk': self.pk})
class Rate(models.Model):
Source = models.ForeignKey(Source, on_delete=models.CASCADE)
Report_Type = models.ForeignKey(ReportType, on_delete=models.CASCADE)
Amount = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = Rate.objects.all.filter(***not sure what to put here***)
return context
Would it be better to filter it in the Template or do it in the View? I am able to get results if I don't filter it and just use Rate.objects.all(), and then I filter it in my template. Just think there is a better way to do this.
You can just fetch the relation in reverse:
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = self.object.rate_set.all()
return context
That being said, here it does not make much difference to make the query in the template, since there is only one object here, so there is no N+1 problem.

Categories

Resources