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
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)
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
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)
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
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.