UnprojectedPropertyError in google app engine - python

The following is a working code in google app engine. This is used to display some records from a SentMail Model. The SentMail have a large no of fields, here i only showed the fields we now need. Since for displaying data i do not require to take the complete record. Hence i used projection. Note: This code is working
class SentMail(ndb.Model):
to_email = ndb.StringProperty()
bounced = ndb.BooleanProperty(default=False)
bounce_type = ndb.StringProperty()
bounceSubType = ndb.StringProperty()
#staticmethod
def get_bounced_emails():
db_query = SentMail.query(SentMail.bounced==True, projection=['to_email', 'bounce_type'], distinct=True).order(SentMail.bounce_type).order(SentMail.to_email).fetch()
return db_query if len(db_query) > 0 else None
class BounceCompaintRender(session_module.BaseSessionHandler):
"""docstring for BounceCompaintRender"""
def get(self):
bounced_emails = self.get_data('complete_bounced_rec')
template_values = {
'bounced_emails': bounced_emails
}
path = os.path.join(os.path.dirname(__file__), 'templates/bounce_complaint_emails.html')
self.response.out.write(template.render(path, template_values))
else:
self.redirect('/login')
def get_data(self, key):
data = memcache.get(key)
if data is not None:
for each in data:
logging.info(each)
return data
else:
data = SentMail.get_bounced_emails()
memcache.add(key="complete_bounced_rec", value=data, time=3600)
return data
Here the only change I made is in SentMail.get_bounced_emails()
#staticmethod
def get_bounced_emails():
db_query = SentMail.query(SentMail.bounced==True, projection=['to_email', 'bounceSubType'], distinct=True).order(SentMail.bounceSubType).order(SentMail.to_email).fetch()
return db_query if len(db_query) > 0 else None
I now get an error UnprojectedPropertyError: Property bounceSubType is not in the projection. I checked the logs and i found in the projection field one parameter is missing and eventhough it has a value None(None is not the only value). I tried clearing memcache but the problem still arises. The following is the log
SentMail(key=Key('SentMail', 655553213235462), bounceSubType=None, to_email=u'test#example.com', _projection=('to_email',))

This error is due to the difference in the model SentMail wrote in models.py and in datastore (i.e., properties are different in both). For this you need to update all records in datastore related to SentMail then datastore and model will have the same fields.

Related

Django-Haystack & Elasticsearch brake with queries containing special characters

So I've been trying to fix a bug that really annoys me: Django-Haystack & Elasticsearch queries are working with accents but it brakes everytime with queries containing special characters like dash - and apostrophes '.
For example let's use Baie-d'Urfé as the query.
Here's my code:
forms.py
class FacetedProductSearchForm(FacetedSearchForm):
def __init__(self, *args, **kwargs):
data = dict(kwargs.get("data", []))
self.ptag = data.get('ptags', [])
self.q_from_data = data.get('q', '')
super(FacetedProductSearchForm, self).__init__(*args, **kwargs)
def search(self):
sqs = super(FacetedProductSearchForm, self).search()
# Ideally we would tell django-haystack to only apply q to destination
# ...but we're not sure how to do that, so we'll just re-apply it ourselves here.
q = self.q_from_data
sqs = sqs.filter(destination=Exact(q))
print('should be applying q: {}'.format(q))
print(sqs)
if self.ptag:
print('filtering with tags')
print(self.ptag)
sqs = sqs.filter(ptags__in=[Exact(tag) for tag in self.ptag])
return sqs
Using FacetedSearch in View.py
class FacetedSearchView(BaseFacetedSearchView):
form_class = FacetedProductSearchForm
facet_fields = ['ptags']
template_name = 'search_result.html'
paginate_by = 30
context_object_name = 'object_list'
And my search_indexes.py
class ProductIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(
document=True, use_template=True,
template_name='search/indexes/product_text.txt')
destination = indexes.CharField(model_attr="destination") #boost=1.125
# Tags
ptags = indexes.MultiValueField(model_attr='_ptags', faceted=True)
# for auto complete
content_auto = indexes.EdgeNgramField(model_attr='destination')
# Spelling suggestions
suggestions = indexes.FacetCharField()
def get_model(self):
return Product
def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.filter(timestamp__lte=timezone.now())
Any ideas on how to fix this?
Thanks a lot!
The problem seems to be related to Elasticsearch itself, so what I did is remove all my Elasticsearch instances and reformulated my search view to simple postgresql queries.
Final observation after solving this:
50$ / month saved and a search engine working like a charm!

Odoo: How to create many records in Transient.Model?

This code only creates one record. What is wrong?
class PartnerTagCreate(models.TransientModel):
""" Choose tags to be added to partner."""
_name = 'partner.tags.create'
_description = __doc__
market_id = fields.Many2one('partner.tags', string='Market Tag')
application_id = fields.Many2one('partner.tags', string='Application Tag')
partner_id = fields.Integer()
#api.multi
def create_contact_tag(self):
for record in self.env['sale.order.line'].browse(self._context.get('active_ids', [])):
vals = {}
vals['partner_id'] = record.order_partner_id
self.write(vals)
return True
I need this function to create one record for each order_partner_id I selected before opening the wizard...
How to achieve that?
Here my new code (function) ...
def create_contact_tag(self):
sale_order_line_ids = self.env['sale.order.line'].browse(self._context.get('active_ids', []))
for partner in sale_order_line_ids:
values = {}
values['partner_id'] = partner.order_partner_id
self.create(values)
return {}
This creates one record for marketing_id and/or application_id and dedicated records for each partner_id in the record.
You use the 'create' method to create new records; this is the same for TransientModel as for the persistent Model.
So, replace
self.write(vals)
by
self.create(vals)
and you should be fine.

HAYSTACK_SIGNAL_PROCESSOR failing to update index in realtime as None object is passed

I am using haystack and elasticsearch. I am building indexes in the following manner-->
class BookIndex(indexes.SearchIndex,indexes.Indexable):
text= indexes.CharField(document=True,use_template=True)
content_auto = indexes.EdgeNgramField(model_attr='title',boost=1.5)
isbn_13 = indexes.CharField(model_attr='isbn_13')
category = indexes.CharField()
sub_category = indexes.CharField()
def prepare_sellers(self, Book):
return [seller.name for seller in Book.sellers.all()]
def prepare_category(self, Book):
return [Book.category.name]
def prepare_sub_category(self, Book):
return [Book.sub_category.name]
And I have included the following in the settings file :-
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
But when I am going to add data to my database by doing -> http://dpaste.com/01739SW , haystack index updating is failing and I am getting the following error-->http://dpaste.com/2YGXZ8J
Can someone please help me out in fixing the issue. Thank you.

How to save a non ModelForm form to database in Django

I'm a newbie Django user, struggling with submitting form data to the database. So that I can generate dynamic forms I am using a non-ModelForm form to capture field data.
I'm commented out validation for now but I am trying to capture the POST data from the form to the database. The latest 'draft' of my views.py code is as follows - most interested in format from form_to_save = Scenario(...):
def scenario_add(request, mode_from_url):
urlmap = {
'aviation': 'Aviation',
'maritime': 'Maritime',
'international_rail': 'International Rail',
'uk_transport_outside_london': 'UK Transport (Outside London)',
'transport_in_london': 'Transport in London',
}
target_mode = urlmap[mode_from_url]
m = Mode.objects.filter(mode=target_mode)
tl = m[0].current_tl.threat_l
scenario_form = ScenarioForm(request.POST or None, current_tl=tl, mode=target_mode)
if request.method == 'POST':
#if scenario_form.is_valid():
form_to_save = Scenario(
target = Target(descriptor = scenario_form.fields['target']),
t_type = ThreatType(t_type = scenario_form.fields['t_type']),
nra_reference = NraReference(nra_code = scenario_form.fields['nra_reference']),
subt = scenario_form.fields['subt'],
ship_t = ShipType(ship_t = scenario_form.fields['ship_t']),
likelihood = scenario_form.fields['likelihood'],
impact = scenario_form.fields['impact'],
mitigation = scenario_form.fields['mitigation'],
compliance_score = scenario_form.fields['compliance_score'],
notes = scenario_form.fields['notes']
)
form_to_save.save()
# This needs to be changed to a proper redirect or taken to
# a scenario summary page (which doesn't yet exit.)
return render(request, "ram/new_scenario_redirect.html", {
'scenario_form': scenario_form,
'mode': mode_from_url,
'mode_proper': target_mode
})
else:
# if there is no completed form then user is presented with a blank
# form
return render(request, 'ram/scenario_add.html', {
'scenario_form': scenario_form,
'current_tl': tl,
'mode': mode_from_url,
'mode_proper': target_mode
})
Any advice gratefully received. Many thanks.
You've commented out the is_valid check, for some reason. You need that: as well as checking for validity, it also populates the form's cleaned_data dictionary which is what you should be getting the data from to create your object. (And don't call that object "form_to_save": it's a model instance, not a form).
if request.method == 'POST':
if scenario_form.is_valid():
scenario = Scenario(
target = Target(descriptor=scenario_form.cleaned_data['target']),
t_type = ThreatType(t_type = scenario_form.cleaned_data['t_type'])
...etc
Plus, you should move the final "return render" call out of the else block, so that it is caught when the form is not valid, to show any errors.
However, as petkostas says, you would almost certainly be better off using an actual ModelForm in the first place.
You can add custom options by overriding the init function in your form. For example:
class SomeForm(forms.Form):
department = forms.ChoiceField(widget=forms.Select, required=True)
...
def __init__(self, *args, **kwargs):
super(SomeForm, self).__init__(*args, **kwargs)
self.fields['department'].choices = Department.objects.all().order_by('department_name).values_list('pk', 'department_name')
You can also change the queryset in the init function:
where Department is a foreign key for example
queryset = Department.objects.filter(your logic)
self.fields['department'].queryset = queryset

Separating "user-owned" from "other" data in Django template

I have an Openstack-powered, Django-modified application that shows the disk images and snapshots available for a user to launch. The user currently sees both snapshots they created and ones they did not. I would like to separate the current table into two based on whether they are owned by the user or not.
My two table definitions are as follows (note I altered row_actions accordingly):
class UserSnapshotsTable(OldSnapshotsTable):
cloud = tables.Column(get_cloud, verbose_name=_("Cloud"))
class Meta:
name = "usersnapshots"
verbose_name = _("User Snapshots")
table_actions = (DeleteSnapshot,)
row_actions = (LaunchSnapshot, LaunchCluster, EditImage, DeleteSnapshot)
pagination_param = "snapshot_marker"
row_class = UpdateRow
status_columns = ["status"]
class OtherSnapshotsTable(OldSnapshotsTable):
cloud = tables.Column(get_cloud, verbose_name=_("Cloud"))
class Meta:
name = "othersnapshots"
verbose_name = _("Other Snapshots")
table_actions = (DeleteSnapshot,)
row_actions = (LaunchSnapshot, LaunchCluster)
pagination_param = "snapshot_marker"
row_class = UpdateRow
status_columns = ["status"]
I have altered the HTML template to pull the "UserSnapshotsTable" and "OtherSnapshotsTable" tables (I copied the original table and renamed both), but both full tables still generate under the respective headings. There are two functions generating the data:
def get_usersnapshots_data(self):
req = self.request
marker = req.GET.get(UserSnapshotsTable._meta.pagination_param, None)
try:
usersnaps, self._more_snapshots = api.snapshot_list_detailed(req,
marker=marker)
except:
usersnaps = []
exceptions.handle(req, _("Unable to retrieve user-owned snapshots."))
return usersnaps
def get_othersnapshots_data(self):
req = self.request
marker = req.GET.get(OtherSnapshotsTable._meta.pagination_param, None)
try:
othersnaps, self._more_snapshots = api.snapshot_list_detailed(req,
marker=marker)
except:
othersnaps = []
exceptions.handle(req, _("Unable to retrieve non-user-owned snapshots."))
return othersnaps
There are also Edit/Delete options defined for images, and imported for snapshots, that seem to have a key comparison. Here's the "Delete" one (line 7):
class DeleteImage(tables.DeleteAction):
data_type_singular = _("Image")
data_type_plural = _("Images")
def allowed(self, request, image=None):
if image:
return image.owner == request.user.tenant_id
# Return True to allow table-level bulk delete action to appear.
return True
def delete(self, request, obj_id):
api.image_delete(request, obj_id)
How can I separate those tables out? This is my first time asking a question here, so please let me know if I can provide further information. Apologies for the length of it.
As far as I see you are using glanceclient. If that so you can use extra_filters parameter of snapshot_list_detailed() to filter only user images like this:
usersnaps, self._more_snapshots = api.snapshot_list_detailed(
req,
marker = marker,
extra_filters = {"owner": "user_name"}
)
Under cover snapshot_list_detailed uses GET images of Openstack Image Service API.

Categories