By default LinkProperty() is empty. But let us say I submit a form that stores site link in the DB field with the property LinkProperty(). This works fine so far.
Next, I want to delete that link stored in the DB by resubmitting the form with empty site link. At this time, I get database error as follows:
"BadValueError: link must not be empty."
Can anyone please help with this? Code below.
###Database
class MyDatabase(db.Model):
site = db.LinkProperty()
###Trying to store form data in the database
mydb_obj = MyDatabase.get_or_insert('abc')
#above line works fine
mydb_obj.site = self.request.get('form_site') #works fine.
#Above form_site is read from form submission. It can be 'www.google.com' or it can be
#empty as in ''
mydb_obj.put() #I GET ERROR WHEN form_site = ''.
#"BadValueError: link must not be empty"
I have not tried to replicate this error. It could be possible that the when the link input is empty, the value requested is None. Perhaps this might work:
mydb_obj.site = self.request.get('form_site')
if mydb_obj.site is None:
mydb_obj.site = '' # value is empty string instead of None.
The following works
mydb_obj.site = self.request.get('form_site')
if not mydb_obj.site:
mydb_obj.site = None
mydb_obj.put()
Related
I've been trying to build a form to create and delete Revit print Sets.
I've 2 main issues:
1) I'm able to create a print set but I cannot access its content unless I restart the Form. I get the errors below (depending if I'm defining the view_set variable or not)
List_object_has_no_attribute_Views
Local_variable_referenced_before_assignment
This is the code of the function to display the sheets of the selected Print Set
def DisplaySheetsInSet (self, sender, args):
self.curItem = CurrentSetsListBox.SelectedItem
PrintSetForm_Load
try:
view_set=[]
for i in PrintSetForm.ViewSets:
if i.Name == str(self.curItem):
view_set = i
else:
continue
Sheets=[sheet.Name for sheet in view_set.Views]
SheetsLb.BeginUpdate()
SheetsLb.Items.Clear()
for sheet in Sheets:
SheetsLb.Items.Add(sheet)
SheetsLb.EndUpdate()
except Exception as e:
popup (str(e)
2) I'm able to delete print sets once. If I try do delete another one I get the following error and I need to restart the form ( code for the function that deletes the print sets shown below)
The_referenced_object_is_not_valid
def DelPrintSet(self, sender, args):
self.curItem = CurrentSetsListBox.SelectedItems
t = Transaction (doc, 'Delete printset')
t.Start()
for viewset in PrintSetForm.ViewSets:
if viewset.Name in [str(item) for item in self.curItem]:
doc.Delete(viewset.Id)
doc.Regenerate()
else:
continue
self.Refresh()
UpdateSetNames(CurrentSetsListBox)
t.Commit()
I've tried to build a function to restart/refresh the Form but it doesn't work (code below):
global PrintSetForm_Load
def PrintSetForm_Load(self, sender):
Application.Exit()
Application.Restart()
#self.Refresh()
#self.ResetBindings()
#self.ActiveForm.Close()
sd = PrintSetForm()
sd.ShowDialog()
This gif shows the form in action:
Manage Print Sets
Any ideas or suggestions?
Thank you.
3) If I try to populate the SheetsLb with a DataSource, just the first set clicked is shown.
Sheets=[sheet.Name for sheet in view_set.Views]
SheetNumber=[sheet.get_Parameter(BuiltInParameter.SHEET_NUMBER).AsString() for sheet in view_set.Views]
SheetsLb.BeginUpdate()
SheetsLb.DataSource = None
SheetsLb.Items.Clear()
UpdatedList=[]
for number,name in zip(SheetNumber,Sheets):
UpdatedList.append(number+" - "+ name + " [ ] ")
SheetsLb.DataSource=UpdatedList
SheetsLb.EndUpdate()
1) See if this works:
It would be worth checking that there is something selected in self.viewSetsLb. Ive added a check to the code below
The view_set variable could be initialised as a boolean instead of a list
Using break in the for loop keeps things a little snappier
Ive used the more pythonic for view in PrintSetForm.viewSets rather than for i in PrintSetForm.viewSets - keeping it nice and clear
This code works for me:
self.curItem = self.viewSetsLb.SelectedItem
if not self.viewSetsLb.SelectedItem:
print 'No Printset selected!'
return
view_set = False
for view in PrintSetForm.viewSets:
if view.Name == str(self.curItem):
view_set = view
break
else:
continue
Sheets=[sheet.Name for sheet in view_set.Views]
self.sheetsLb.BeginUpdate()
self.sheetsLb.Items.Clear()
for sheet in Sheets:
self.sheetsLb.Items.Add(sheet)
self.sheetsLb.EndUpdate()
2) Its because the data in your PrintSetForm.ViewSets list is out of date. Every time you change something (ie delete a viewset), repopulate this list:
PrintSetForm.ViewSets = FilteredElementCollector(doc).OfClass(ViewSheetSet).ToElements()
Also, you shouldnt need to build a refresh button, perhaps have a class function that repopulates the Printset list and ListBox, and clears the Sheet ListBox that you call after every action?
Sounds like youre having fun mate!
It sounds as if you have an issue with the scoping and lifetime of variables. For instance, some variables may have a lifetime limited to the form display, and therefore cannot be accessed after the form is closed. You could change the lifetime of these variables, e.g., by making them static class variables instead of local instance variables. I suggest you read up on .net static class variable scope.
I'm struggling with a KeyProperty query, and can't see what's wrong.
My model is
class MyList(ndb.Model):
user = ndb.KeyProperty(indexed=True)
status = ndb.BooleanProperty(default=True)
items = ndb.StructuredProperty(MyRef, repeated=True, indexed=False)
I create an instance of MyList with the appropriate data and can run the following properly
cls = MyList
lists = cls.query().fetch()
Returns
[MyList(key=Key('MyList', 12), status=True, items=..., user=Key('User', 11))]
But it fails when I try to filter by user, i.e. finding lists where the user equals a particular entity; even when using the one I've just used for insert, or from the previous query result.
key = lists[0].user
lists = cls.query(cls.user=key).fetch()
Returns
[]
But works fine with status=True as the filter, and I can't see what's missing?
I should add it happens in a unit testing environment with the following v3_stub
self.policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=0)
self.testbed.init_datastore_v3_stub(
require_indexes=True,
root_path="%s/../"%(os.path.dirname(__file__)),
consistency_policy=self.policy
)
user=Key('User', 11) is a key to a different class: User. Not MyList
Perhaps you meant:
user = ndb.KeyProperty(kind='User', indexed=True)
Your code looks fine, but I have noticed some data integrity issues when developing locally with NDB. I copied your model and code, and I also got the empty list at first, but then after a few more attempts, the data is there.
Try it a few times?
edit: possibly related?
google app engine ndb: put() and then query(), there is always one less item
I have a model that looks like this:
class Report(models.Model):
updater = models.CharField(max_length=15)
pub_date = models.DateTimeField(auto_add_now=True)
identifier = models.CharField(max_length=100)
... and so on...
There are some more fields but they are irrelevant to the question. Now the site has very simple functions - the users can see older reports and their data, and can edit them or add new ones.
However, the identifier field is actually an integer that symbolizes a log file that is being reported. Most of the times, each report has one log. But sometimes it has more than one. I did it as a CharField because I built the site to replace an older sharepoint 2003 website, where that field was treated as simple text. So I want that in my next version, it would be like it should be, i.e. like this:
class Report(models.Model):
updater = models.CharField(max_length=15)
pub_date = models.DateTimeField(auto_add_now=True)
... and so on...
class Log(models.Model):
report = models.ForeignKey(Report)
identifier = models.IntegerField()
The problem is, since in the old site that field was a CharField, people used this as they liked. Meaning, even if they updated various logs in the same report they just did it like this <logid1>, <logid2>. Sometimes they added some text <logid1> which is related to <logid2>.
So I want to change this, but I don't want to lose all the old data, and I can't fix all those edge cases (the DB contains around 22 thousand reports). I thought about adding this to report:
def disp_id(self):
if self.pub_date < ... #the day I'll do the update
return self.identifier
else:
return ', '.join([log.identifier for log in self.log_set.all()])
But then I'm not really getting rid of the old field now am I? I'm just adding a new one and keeping the original null from a certain date.
As far as I know, what I want to do is impossible. I'm only asking because I know that maybe I'm not the first one to deal with this sort of thing and maybe there is a solution that I'm not aware of.
Hope my explanation is clear enough, thanks in advance!
class Report(models.Model):
updater = models.CharField(max_length=15)
pub_date = models.DateTimeField(auto_add_now=True)
identifier = models.CharField(null=True)
... and so on...
logs = models.ManyToManyField(Log,null=True)
class Log(models.Model):
identifier = models.IntegerField()
Make the above model , and then make a script as follow:
ident_list = []
for reports in Report.objects.all():
identifiers = reports.identifiers.split(',')
for idents in identifiers:
if not idents in ident_list:
log = Log.create(**{'identifier' : int(idents)})
ident_list.append(int(idents))
else:
log = Log.objects.get(identifier = int(idents))
report.log.add(log)
Check the data before removing the column identifiers from the table Report.
Does it solves your purpose now ?
I keep getting the following error :
BadArgumentError: Expected an instance or iterable of (, ); received idofOne (a str).
and have tried to convert to int() but then get a different error saying :
ValueError: invalid literal for int() with base 10: ''
What is going on? I'm using Google App Engine - and retrieving the idofOne from the html template. It is the ID representation using jinja -- and it is showing a value of "1" - so it shouldn't be empty - any suggestions???
class makeHeadings3(Handler):
def get(self):
self.render('new_entries/ADMIN_make_headings3.html')
def post(self):
idofOne = self.request.get("idofOne")
type2=self.request.get("type2")
heading2name = self.request.get("headingTwo")
description2 = self.request.get("descriptionTwo")
heading3 = self.request.get("headingThree")
#getting relevant level 1 entry by id
level_1_info=Level_1_Headings.get_by_id(idofOne)
Actually - I changed the value coming from my template from the id() to the key(). However I'm discovering that in my template from which I'm retrieving the value from is coming back empty string "". why? I see the value of the key in teh template and I'm retrieving with the correct name "keyofOne" so why is it coming back empty back to my python server code???
Key for Category Level 1
DO NOT EDIT
You could first check:
level_1_info=Level_1_Headings.get_by_id("1")
Then need to add debug in your code to see what value is returned by "idofOne"
import logging
# snip
logging.info("type "+type(idofOne))
logging.info("value "+idofOne)
I hope this helps
The below should fix it. You need to get the integer value of that id
idofOne = int(self.request.get("idofOne"))
Always when parsing post or get parameters you have to convert them to the correct type before passing them to the datastore query.
I'm getting strange additional symbols (=) in text property when adding text there via POST.
For example:
The team is back with an unstoppable fury as they are being chased by the p= olice, Alonzo and Yuuma. Vinnie, Shorty and Kiro=92s skills will be put to = the test.
There shouldn't be any of = symbols in that text.
My co de is:
class FileUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
game_file = self.get_uploads()[1]
screen_file = self.get_uploads()[0]
if not users.get_current_user():
game_file.delete()
screen_file.delete()
self.redirect(users.create_login_url("/"))
return
game = Game()
game.title = self.request.get('title')
game.url_name = self.request.get('url')
if self.request.get('active') == 'active':
game.active = True
else:
game.active = False
if self.request.get('featured') == 'featured':
game.featured = True
else:
game.featured = False
query = Category.gql("WHERE url_name = :url_name", url_name=self.request.get('category'))
game.category = query.get()
game.width = int(self.request.get('width'))
game.height = int(self.request.get('height'))
game.description = db.Text(self.request.get('desc'))
game.how_to_play = db.Text(self.request.get('htp'))
game.game_file = game_file
game.game_screenshot = screen_file
db.put(game)
What am i doing wrong?
This is a known issue of blobstore handler that is breaking the data encoding.
I had the same difficulty. But, I found a fix. I'm using Python 2.5. In my model, I have a TextProperty, hooked up to an html TextArea tag. Like your situation, in the Dev server, it saved what I entered. However, in Prod, the DataStore somehow added "= " among others, every time I write the content of textarea over to the textproperty field.
Go here:
http://code.google.com/p/googleappengine/issues/detail?id=2749
Then, scroll down to Comment 21. The poster of that comment attached a file, named appengine_config.py Download it, and put it on the root folder of your app. Then Deploy it to Prod and try it out in Prod.
I did that, and my "= " problem went away.