Cannot resolve keyword 'field_object' into field - django

I have a field object that I want to do filtering with
Since the filter field will change dynamically.
only_user=User.objects.first()
field_object = only_user._meta.get_field(field)
field_object2 = only_user._meta.get_field(field2)
QuerySet = User.objects.filter(Q(field_object="xxx")|Q(field_object2="yyy"))
But I couldn't do it, it said
Cannot resolve keyword 'field_object' into field. Choices are: .....
EDIT:
I figure it out, Thank You:
sub_filter = {field: field_value}
sub_filter = {field2: field_value}
q_list=[Q(**sub_filter),Q(**sub_filter2)]
QuerySet = User.objects.filter(
reduce(operator.or_, q_list)
)

You can't pass field_object directly in filter. Because you can't pass a variable as key of keyword argument.
Try like this:
field_object = only_candidate._meta.get_field(field)
query1 = { field_object : 'xxx' }
query2 = { field_object2 : 'yyy' }
QuerySet = MyModel.objects.filter(Q(**query1)|Q(**query2))
Basically here I am creating a dictionary using field_object, and key is field_object and value is the actual value you want to query. Then using **query I am converting the dictionary to key=value and passing it through filter.

Related

Set default values for One2many field

I have a class student_student which have a one2many fieldresult_ids defined like the following:
result_ids = fields.One2many("schoolresults.detail", "student_id", "School Results", default="_get_subjects")
and
def _get_subjects(self):
cr = self.pool.cursor()
self.env
return self.pool.get('schoolresults.subject').search(cr, self.env.uid, [])
in the other side I have a class schoolresults_subject:
class schoolresults_subject(models.Model):
_name = "schoolresults.subject"
_description = "Student's subjects."
name = fields.Char("Subject")
class schoolresults_detail(models.Model):
_name = "schoolresults.detail"
_description = "Student's results."
student_id = fields.Many2one("student.student", "Student", ondelete="cascade")
subject_id = fields.Many2one("schoolresults.subject", "Subject")
result = fields.Float("Result", compute='_compute_value', store=True)
What I'm trying to do is to fill the result_ids with a subjects list from the last class, whenever the user trying to create a new student profile, using the the default parameter in the one2many field.
But whenever I try to create a student profile I get this error Wrong values for student.student.result_ids.
Please is there anyway to achieve that?
PS. I'm using Odoo 9
I don't get your requirements here fully, but try something like the following:
def _get_subjects(self):
subjects = self.env['schoolresults.subject'].search([])
details = self.env['schoolresults.detail']
for subject in subjects:
details |= details.new({'subject_id': subject.id})
return details
But explaining the error message: you're returning a RecordSet of schoolresults.subject but your field result_ids has the comodel schoolresults.detail. That's just wrong ;-)
I could do this by overriding the default_get method:
def default_get(self, fields):
res = super(student_student, self).default_get(fields)
srd = self.env['schoolresults.detail']
ids=[]
school_result={'subject_id':1,'result':0} #dict for fields and their values
sr = srd.create(school_result)
ids.append(sr.id)
res['result_ids'] = ids
return res
This is how to override default_get for one2many field.
Credit goes to:Default values for one2many
Please read this If you want to set the default values of one2many field from action, you can create a list of tuple with the same format we use for create or write one2many field and then you can pass it to context.
You can copy your context-
context = self.env.context.copy()
Prepare one2many values like this--
pr_lines = []
for pr_line in pr_obj.line_ids: #loop for multiple lines.
pr_lines.append((0,0, {
'purchase_request_id' : pr_obj.id,
'product_id' : pr_line.product_id.id,
'description' : pr_line.name,
'qty_transfer' : pr_line.product_qty,
'uom_id' : pr_line.product_uom_id.id,
}))
You can update your context like this-
context.update({
'default_warehouse_id': self.approving_matrix_id.warehouse.id,
'default_internal_transfer_receipt': pr_lines,
})
in the action you can pass context like
'context' : context,
result_ids = fields.Many2many("schoolresults.detail", "student_id", "School Results", default="_get_subjects")
def get_default_lines(self):
obj = self.env['your.class.name'].search([])
return obj
Try adding many2many field to your class.

How override Flask-Admin's edit_form() maintaining previous values as placeholders

I'm tryin to override Flask-Admin's edit_form() in order to dynamically populate a SelectField. I managed to do so this way
class ProductForm(Form):
order = IntegerField('order')
name = TextField('name')
category = SelectField('category', choices=[])
image = ImageUploadField(label='Optional image',
base_path=app.config['UPLOAD_FOLDER_ABS'],
relative_path=app.config['UPLOAD_FOLDER_R'],
max_size=(200, 200, True),
endpoint='images',
)
class ProductsView(MyModelView):
create_template = 'admin/create-products.html'
edit_template = 'admin/edit-products.html'
column_list = ('order', 'name', 'category', 'image')
form = ProductForm
column_default_sort = 'order'
def edit_form(self, obj):
form = self._edit_form_class(get_form_data(), obj=obj)
cats = list(db.db.categories.find())
cats.sort(key=lambda x: x['order'])
sorted_cats = [(cat['name'], cat['name']) for cat in cats]
form.category.choices = sorted_cats
form.image.data = obj['image']
return form
The problem is now the form in the /edit/ view defaults name and order fields to empty unless i add these two lines to edit_form():
form.name.data = obj['name']
form.order.data = obj['order']
But if i do so the form will ignore every change (because i set form.field_name.data already?)
How do I preserve the old form values as "placeholders" while correctly overriding edit_form()?
I had a similar problem and thanks to the answer here I solved it;
Basically you set the default for the fields, and then call the individual fields process() method, passing in the currently set value.
from wtforms.utils import unset_value
form.name.default = obj['name']
form.name.process(None, form.name.data or unset_value)
form.order.default = obj['order']
form.order.process(None, form.order.data or unset_value)

List display names from django models

I have an object:
POP_CULTURE_TYPES = (
('SG','Song'),
('MV', 'Movie'),
('GM', 'Game'),
('TV', 'TV'),
)
class Pop_Culture(models.Model):
name = models.CharField(max_length=30, unique=True)
type = models.CharField(max_length=2, choices = POP_CULTURE_TYPES, blank=True, null=True)
Then I have a function:
def choice_list(request, modelname, field_name):
mdlnm = get.model('mdb', modelname.lower())
mdlnm = mdlnm.objects.values_list(field_name, flat=True).distinct().order_by(field_name)
return render_to_response("choice_list.html", {
'model' : modelname,
'field' : field_name,
'field_list' : mdlnm })
This gives me a distinct list of all the "type" entries in the database in the "field_list" variable passed in render_to_response. But I don't want a list that shows:
SG
MV
I want a list that shows:
Song
Movie
I can do this on an individual object basis if I was in the template
object.get_type_display
But how do I get a list of all of the unique "type" entries in the database as their full names for output into a template?
I hope this question was clearly described. . .
How about something like this at the end of your choice_list()?
def choice_list(request, modelname, field_name):
# ...
pct = dict(POP_CULTURE_TYPES)
return [pct[key] for key in mdlnm]
Or in one line w/o the dict() call:
return [pct[1] for pct in POP_CULTURE_TYPES if pct in mdlnm]
Not pretty but it will work until to run across something better.
You could use:
OBJECT.get_FIELD_display()
Example:
content = Pop_Culture.objects.get(...)
ctype = content.get_type_display()
There is no need for workarounds :)

Control Query set in Django (filter,object Q)?

Base On URL
querydict = {customer_type:val1,tag:[], city:[],last_contact:valdate}
show/?customer_type=All&tag=2,3&city=3&last_contact=29/12/2009
I am going to filter by made the method:
def get_filter_result(customer_type, tag_selected, city_selected, last_contact_filled):
if customer_type=has value:
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type))
if tag = has value :
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type)
Q(type__name=tag))
if city = has value:
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type)
Q(type__name=tag),
Q(type__name=city))
if last_contact = has value:
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type)
Q(type__name=tag),
Q(type__name=city),
Q(type__name=last_contact))
Anybody Help give an idea to implement my method more simple and flexible than this?
if value of them are missing or equal None(No value is passed)
so if... else.... condition will control alots of time and code will be larger..
for example :
show/?customer_type=All&tag=&city=&last_contact=
show/?customer_type=All&tag=2,3&city=3&last_contact=29/12/2009
show/?customer_type=&tag=2,3&city=3&last_contact=
show/?customer_type=All&tag=2,3&city=&last_contact=29/12/2009
thanks
def get_filter_result(customer_type=None, tag_selected=None, city_selected=None, last_contact_filled=None):
qdict = {}
if customer_type is not None:
qdict['type__name'] = customer_type
if tag is not None:
<repeat as appropriate>
queryset = Customer.objects.filter(**qdict)
If you want to AND all your queries (like in your example), you can create dictionary of parameters, and then call filter method with this dictionary as an argument:
def get_filter_result(**kwargs):
params = {}
#delete items with empty strings
for key in kwargs:
if kwargs[key]:
params[key] = kwargs[key]
queryset = Customer.objects.filter(**params)

multiple filter parameters in a view

I have a basic search view. It currently queries the db for any objects from a particular client. The view code is as follows:
def search_page(request):
form = PrdSearchForm()
prdlinks = []
show_results = True
if request.GET.has_key('query'):
show_results = True
query = request.GET['query'].strip()
if query:
form = PrdSearchForm({'query' : query})
prdlinks = \
ProjectRecord.objects.filter(client__icontains=query)
if len(prdlinks) >= 1:
records = ProjectRecord.objects.filter(client__icontains=query)
t = get_template('org_list_client.html')
html = t.render(Context({'records': records}))
return HttpResponse(html)
else:
tpl = "prd_search.html"
variables = RequestContext(request, { 'form': form,
'prdlinks': prdlinks,
'show_results': show_results})
return render_to_response(tpl, variables)
I'd like for the search field to check both for objects by client AND account. This, I think, would involve altering this code:
if query:
form = PrdSearchForm({'query' : query})
prdlinks = \
ProjectRecord.objects.filter(client__icontains=query)
to include ProjectRecord.objects.filter(account__icontains=query). Can anyone help with the syntax, or is there more involved with what I'm trying to accomplish?
I think you're looking for the Q object (as refrenced by The MYYN)
from django.db.models import Q
records=ProjectRecord.objects.filter(
Q(client__icontains=query) |
Q(account__icontains=query)
)
complex-lookups-with-q-objects
You can try to chain filters, like:
>>> ProjectRecord.objects.filter(
... client__icontains=query).filter(account__icontains=query)
This will first filter the clients, which contain the query, then filter this result queryset where the account also contains query.
General form:
>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.now()
... ).filter(
... pub_date__gte=datetime(2005, 1, 1)
... )
Further useful examples are included in the documentation:
Spanning Multi-Valued Relationships
Complex lookups with Q objects
Restructured the view code to separate the client records(prdlinks) from the account records(acclinks) and handled them separately. Wasn't sure if it would work (it does) and am still not sure if this is the most efficient way to write the code (probably isn't). In any event, here is the revised code:
def search_page(request):
form = PrdSearchForm()
prdlinks = []
**acclinks = []**
show_results = True
if request.GET.has_key('query'):
show_results = True
query = request.GET['query'].strip()
if query:
form = PrdSearchForm({'query' : query})
prdlinks = \
ProjectRecord.objects.filter(client__icontains=query)
**acclinks = \
ProjectRecord.objects.filter(account__icontains=query)**
if len(prdlinks) >= 1:
records = ProjectRecord.objects.filter(client__icontains=query)
t = get_template('org_list_client.html')
html = t.render(Context({'records': records}))
return HttpResponse(html)
**elif len(acclinks) >= 1:
records = ProjectRecord.objects.filter(account__icontains=query)
t = get_template('org_list_account.html')
html = t.render(Context({'records': records}))
return HttpResponse(html)**
else:
tpl = "prd_search.html"
variables = RequestContext(request, { 'form': form,
'prdlinks': prdlinks,
'show_results': show_results})
return render_to_response(tpl, variables)