django filter field as a string - django

i want to change the filtering field dynamically.
i have a model named Product and fields are title and code
class Product(models.Model):
title = models.CharField(max_length=50)
code = models.CharField(max_length=50)
my filtering field will be dynamic in views like this
def filter(request):
search_choices = {
'1': 'title__icontains',
'2': 'code__icontains',
}
col_num = request.GET.get("col_num")
value = request.GET.get("value")
search_field = search_choices.get("col_num")
qs = Product.objects.filter(search_field=value)
........
here the variable search_field is always dynamic ... so how can i achieve this

You can achieve this by passing argument as dictionary:
value = request.GET.get("value")
search_field = search_choices.get("col_num")
qs = Product.objects.filter(**{search_field: value})

Related

Django how the link ManytoManyField data with FloatField data?

I have manytomanyfield inside my model.The manytomanyfield field lists the products in the products table.
I want to enter the amount for each product I choose. How can I relate manytomanyfield to floatfield field?
That's my model:
`
class TaskSources(models.Model):
id = models.AutoField(primary_key=True)
user_task_id = models.ForeignKey(UserTask,on_delete=models.CASCADE)
product_id = models.ManyToManyField(Product, verbose_name="Product",default=None)
product_amount = models.FloatField(max_length=255,verbose_name="Product Amount")
`
The form:
`
class TaskSourcesForm(forms.ModelForm):
class Meta:
model = TaskSources
fields = ['product_id', 'product_amount']
`
The views:
`
#login_required(login_url="login")
def addUserTask(request):
user_task_form = UserTaskForm(request.POST or None,initial={'user_id': request.user})
task_sources_form = TaskSourcesForm(request.POST or None)
if request.method == 'POST':
if user_task_form.is_valid():
user_task = user_task_form.save(commit=False)
user_task.author = request.user
user_task.save()
print(user_task.id)
if task_sources_form.is_valid():
task_sources = task_sources_form.save(commit=False)
task_sources.user_task_id = UserTask(id = user_task.id)
task_sources.save()
task_sources_form.save_m2m()
messages.success(request,"Task added successfully!")
return redirect(".")
context = {
"user_task_form" : user_task_form,
"task_sources_form" : task_sources_form,
}
return render(request,"user/addtask.html",context)
`
Thanks for care.
I tried associating the two fields with each other, but I could not succeed.
If I got it right I think that what you need is an intermediate table between your models. That way you can link an amount of a product to a TaskSource, something similar to this:
class Product(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class ProductAmount(models.Model):
amount = models.FloatField(max_length=255,verbose_name="Product Amount")
product = models.ManyToManyField(Product, through='TaskSources')
def __str__(self):
return self.name
class UserTask(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class TaskSources(models.Model):
id = models.AutoField(primary_key=True) # this is not really necessary
task = models.ForeignKey(UserTask,on_delete=models.CASCADE)
product_amount = models.ForeignKey(ProductAmount, on_delete=models.CASCADE)

How to get second last record in a queryset in Django?

I have a model named employees_salary and I need to get second highest salary of employee.
I know that I can filter latest(), first(), last()** and these are working, but how to filter second last? Am I missing something?
Use order_by with a reverse filter (-) and then grab the second object by using [1].
class Salaries(models.Model):
employee_name = models.CharField(max_length=255)
salary = models.IntegerField()
q = Salaries.objects.all().order_by('-salary')
second_highest_paid_name = q[1].employee_name
This way will also work
class EmployeeSalary(models.Model):
employee_name = models.CharField(max_length=255)
salary = models.IntegerField()
#code for view
q = EmployeeSalary.objects.all().order_by('-salary')[1:1]
second_paid_name = q[0].employee_name
second_paid_salary = q[0].salary
This will also work, if you try it like this:
models.py:
class Post(models.Model):
title = models.CharField()
body = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
views.py:
def postlist(request):
latest_post = Post.objects.order_by('-pub_date')[0]
secondlast_post = Post.objects.order_by('-pub_date')[1]
context = {
'latest_post' : latest_post, 'secondlast_post' : secondlast_post ,
}
return render(request, 'yourtemplate.html', context)

django: filter based on values

I need to take a set of values, in this case the foreign key liquorID in LiquorInStore obtained with values() or values_list() and use them to filter the results by ID of it's parent db, Liquor and return those to the webpage.
This is the view, I fear I may not be using the variables correctly.
def store(request, store_id=1):
a = Store.objects.get(StoreID=store_id)
b = LiquorInStore.objects.filter(storeID__exact=a).values('liquorID')
args = {}
args['liquors'] = Liquor.objects.filter(id__exact=b)
args['a'] = a
return render(request, 'store.html', args)
Here is the models file as well in case that helps.
class LiquorInStore(models.Model):
StoreLiquorID = models.AutoField(primary_key=True)
liquorID = models.ForeignKey(Liquor)
storeID = models.ForeignKey(Store)
StorePrice = models.DecimalField('Store Price', max_digits=5, decimal_places=2)
Do it like this:
b = LiquorInStore.objects.filter(storeID__id=a.id).values_list('liquorID', flat=True)
args['liquors'] = Liquor.objects.filter(id__in=b)

django custom manager with filter parameter

I would like to add a custom manager which can be called from a template, but does not affect the entire model (e.g. admin views) and which listens to a parameter set in the request (user_profile).
The following is what I have so far:
models.py:
class CurrentQuerySet(models.query.QuerySet):
def current(self):
return self.filter(id=1) ## this simplified filter test works..
class CurrentManager(models.Manager):
use_for_related_fields = True
def get_query_set(self):
return CurrentQuerySet(self.model)
def current(self, *args, **kwargs):
return self.get_query_set().current(*args, **kwargs)
For model B is defined:
objects = CurrentManager()
The template calls:
{% for b in a.b_set.current %}
But as soon as I try to pass a parameter to that filter (in this case a date stored on the user-profile) the method does not return any results.
e.g.:
models.py
class CurrentQuerySet(models.query.QuerySet):
def current(self,my_date):
return self.filter(valid_from__lte=my_date)
showA.html
{% for b in a.b_set.current(request.user.get_profile.my_date) %}
Instead of passing the parameter from the template, I have also tried to set this in the view.py
#login_required
def showA(request,a_id):
my_date = request.user.get_profile().my_date
a = A.objects.get(id=a_id)
t = loader.get_template('myapp/showA.html')
c = RequestContext(request,{'a':a,'my_date':my_date,})
return HttpResponse(t.render(c))
Which part am I missing (or misunderstanding) here?
Thanks
R
Edit
Here the models. As mentioned, in this example it's a simple 1:n relationship, but can also be m:n in other cases.
class A(models.Model):
#objects = CurrentManager()
a = models.CharField(max_length=200)
description = models.TextField(null=True,blank=True)
valid_from = models.DateField('valid from')
valid_to = models.DateField('valid to',null=True,blank=True)
def __unicode__(self):
return self.a
class B(models.Model):
#objects = models.Manager()
objects = CurrentManager()
a = models.ForeignKey(A)
b = models.CharField(max_length=200)
screenshot = models.ManyToManyField("Screenshot",through="ScreenshotToB")
description = models.TextField(null=True,blank=True)
valid_from = models.DateField('valid from')
valid_to = models.DateField('valid to',null=True,blank=True)
def __unicode__(self):
return self.b
Edit-2
The accepted answer works for at least one relationship.
In case of a more nested data model, this method seems not to deliver the expected results:
models.py
class C(models.Model):
objects = CurrentManager()
b = models.ForeignKey(A)
c = models.CharField(max_length=200)
description = models.TextField(null=True,blank=True)
valid_from = models.DateField('valid from')
valid_to = models.DateField('valid to',null=True,blank=True)
def __unicode__(self):
return self.c
views.py
#login_required
def showA(request,a_id):
a = A.objects.get(id=a_id)
my_date = request.user.get_profile().my_date
b_objects = a.b_set.current(my_date)
c_objects = b_objects.c_set.current(my_date)
t = loader.get_template('controltool2/showA.html')
c = RequestContext(request,{'a':a,'b_objects':b_objects,'c_objects':c_objects,})
return HttpResponse(t.render(c))
This returns the error: 'QuerySet' object has no attribute 'c_set'.
I'd simplify it:
class CurrentManager(models.Manager):
def current(self, my_date):
return super(CurrentManager, self).get_query_set().filter(valid_from__lte=my_date)
and then use it like this:
a = A.objects.get(id=a_id)
my_date = request.user.get_profile().my_date
b_objects = a.b_set.objects.current(my_date)
and then just pass a to the template as the filtered objects accessing them using this:
{% for b in b_objects %}
Hope this helps!
Edit (by requestor):
I had to adjust it as follows to get it working:
a = A.objects.get(id=a_id)
my_date = request.user.get_profile().my_date
b_objects = a.b_set.current(my_date)
This threw an error: "'RelatedManager' object has no attribute 'objects'"
a.b_set.objects.current(my_date)

Django how to order_by temporary field, dynamic create field

think about these:
here is a function,
def calculate(model):
model.tempfield = 1
and this function will save a temp field in this model
and you can use model.tempfield in everywhere
but if it's a queryset,after an order_by these temp filed will lost
how to order_by these temp field in queryset?
i have 2 model:
Class A(models.Model):
name = models.CharField(maxlength=100)
Class Log_Of_A(models.Model):
clicks = models.IntegerField()
a = models.ForeignKey(A)
date = models.DateField(db_index=True)
and calculate the Log of A by date
def createlog(request):
start = request.GET.get("start")
end = request.GET.get("end")
all_A = A.objects.all()
for a in all_A:
logs=Log_Of_A.objects.filter(a=a,date__gt=start,date__lt=end)
statistics = logs.aggregate(Sum("clicks"))
a.clicks = statistics["clicks__sum"]
all_A.order_by("clicks")
return all_A
how to order_by temporary field
Try this:
import operator
def createlog(request):
start = request.GET.get("start")
end = request.GET.get("end")
all_A = A.objects.all()
for a in all_A:
logs=Log_Of_A.objects.filter(a=a,date__gt=start,date__lt=end)
statistics = logs.aggregate(Sum("clicks"))
a.clicks = statistics["clicks__sum"]
sorted = sorted(all_A, key=operator.attrgetter('clicks'), reverse=True)
return sorted