I am trying to delete an entity from the Datastore using a link in html. I understand that in order to do this, I need to have the entity's key so that I know which entity to "pair" the delete link with, so to speak. I can't for the life of me figure out how to do this...
Here is my html file that shows all of the cars in the database:
{% if cars|length > 0 %}
{% for c in cars %}
<tr>
<td>{{ c.make }}</td>
<td>{{ c.model }}</td>
<td>{{ c.year }}</td>
<td>
{% for i in c.color %}
{{ i }}
{% endfor %}
</td>
<td>{{ c.condition }}</td>
<td>{{ c.date }}</td>
<td>
Delete Car
</td>
</tr>
{% endfor %}
{% endif %}
Here is the python file:
class AddCarHandler(webapp2.RequestHandler):
template_variables = {}
def get(self):
template = JINJA_ENVIRONMENT.get_template('index.html')
self.response.write(template.render(self.template_variables))
action = self.request.get('action')
#if the user adds a car
if action == 'add_car':
c = car_database.Car()
c.make = self.request.get('car-make')
c.model = self.request.get('car-model')
c.year = self.request.get('car-year')
c.color = self.request.get_all('car-color')
c.condition = self.request.get('car-condition')
c.date = self.request.get('car-date')
car_key = c.put()
class ViewCarHandler(webapp2.RequestHandler):
template_variables = {}
def get(self):
car = car_database.Car()
#ndb query
self.template_variables['cars'] = [{'make':x.make, 'model':x.model, 'year':x.year, 'color':x.color, 'condition':x.condition, 'date':x.date} for x in car_database.Car.query().fetch()]
template = JINJA_ENVIRONMENT.get_template('/view_cars.html')
self.response.write(template.render(self.template_variables))
You can get the key of an entity (which, say, is obtained through a query) like this:
entity_key = entity.key
Note: this only works after the entity was saved into the DB, not before (i.e. entity.put() was called at least once).
To pass the key between the python code and URLs or HTML code, from the documentation, you can use a key's url string or a pre-computed deletion url based on that string, passed, for example, in self.template_variables['cars']:
You can also use an entity's key to obtain an encoded string suitable
for embedding in a URL:
url_string = sandy_key.urlsafe()
This produces a result like agVoZWxsb3IPCxIHQWNjb3VudBiZiwIM which can
later be used to reconstruct the key and retrieve the original entity:
sandy_key = ndb.Key(urlsafe=url_string)
sandy = sandy_key.get()
You'll need to add a handler for such deletion url, in which you'd reconstruct the key as quoted above, then call:
entity_key.delete()
Related
For the starters, I would like to have something like this,
Array 1 Array 2 Array 3 Array 4
Arr1val1 Arr2val1 Arr3val1 Arr4val1
Arr1val2 Arr2val2 Arr3val2 Arr4val2
Arr1val3 Arr3val3 Arr4val3
Arr1val4 Arr4val4
Arr4val5
I have already solved the issue in the crudest way possible,a solution that won't scale to other data types and if number of variable increase to lets say 10 columns it will fail in the most glorious way which makes me cringe and ask for suggestions of improvement.
My naive approach is here in a fiddle.
As the code is simple I would like to explain what I did.
Step 1 : Calculate the highest number of elements in all arrays and the array from which it is coming.
Step 2 : Make the number of elements in all array same as the number of elements in the highest number of element possible by filling in blanks.
Step 3 : Iterate over one in the HTML and print all.
Would like to know what can be done to make this solution better and more scalable?
Instead of finding max length of arrays, push all the values to the specific array.
Draw a table inside the td. So here the data are drawn vertically.
Using this scenario, you can add any number of data to any array, since
this is generating vertically.
Please see the working code
https://jsfiddle.net/yaxmjpkp/7/
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
//Test case 1
$scope.arr1 = ["Arr1val1", "Arr1val2", "Arr1val3", "Arr1val4"];
$scope.arr2 = ["Arr2val1", "Arr2val2"];
$scope.arr3 = ["Arr3val1", "Arr3val2", "Arr3val3"];
$scope.arr4 = ["Arr4val1", "Arr4val2", "Arr4val3", "Arr4val4", "Arr4val5","Arrayval6"];
$scope.tableValues=[];
$scope.tableValues.push($scope.arr1);
$scope.tableValues.push($scope.arr2);
$scope.tableValues.push($scope.arr3);
$scope.tableValues.push($scope.arr4);
debugger
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myController">
<table>
<thead>
<td>
Header 1
</td>
<td>
Header 2
</td>
<td>
Header 3
</td>
<td>
Header 4
</td>
</thead>
<tbody>
<tr>
<td ng-repeat="val in tableValues" valign = "top">
<table>
<tr ng-repeat="val2 in val">
<td>{{val2}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
As far as I know you don't need to do the first two steps. As javascript is loosely typed language and so is angular (although its not a language but its built over JS). So when you access some value like
<tr ng-repeat="val in arr1 track by $index">
<td>{{arr1[$index]}}</td>
<td>{{arr2[$index]}}</td>
<td>{{arr3[$index]}}</td>
<td>{{arr4[$index]}}</td>
</tr>
Angular won't find any element on that index (Because of the unequal size of that array). So you won't have any issue regarding the access of the value on that particular index. And an empty <td> will be added in that place.
Btw, you can store array elements in associative array and you can check max length in a more generic way.
$scope.arrs = {
arr1: ["Arr1val1", "Arr1val2", "Arr1val3", "Arr1val4"],
arr2: ["Arr2val1", "Arr2val2"],
arr3: ["Arr3val1", "Arr3val2", "Arr3val3"],
arr4: ["Arr4val1", "Arr4val2", "Arr4val3", "Arr4val4", "Arr4val5"]
};
var maxLength = 0;
for(var arrKey in $scope.arrs){
maxLength = Math.max($scope.arrs[arrKey].length, maxLength);
});
Here is complete solution: https://plnkr.co/edit/p6EcXeiRKHY2wQA3xCi4?p=preview
i have this model
class Social(db.Model):
__tablename__ = 'social_auth_usersocialauth'
id = db.Column('id',db.Integer, primary_key=True)
provider = db.Column('provider',db.String(32))
extra_data = db.Column('extra_data',db.String())
uid = db.Column('uid',db.String(255))
def __init__(self,id=None, provider=None, extra_data=None, uid=None):
self.id = id
self.provider = provider
self.extra_data = extra_data
self.uid = uid
def __repr__(self):
return '<Social %r>' % self.uid
then here is my function
test = Social.query.filter(Social.uid == current_user)
and when i get in on view like this {{ test }}
i get it's query, i want to get the result , how can i do this ?
here is the result on my view now:
SELECT social_auth_usersocialauth.id AS social_auth_usersocialauth_id, social_auth_usersocialauth.provider AS social_auth_usersocialauth_provider, social_auth_usersocialauth.extra_data AS social_auth_usersocialauth_extra_data, social_auth_usersocialauth.uid AS social_auth_usersocialauth_uid FROM social_auth_usersocialauth WHERE social_auth_usersocialauth.uid = :uid_1
You have two problems. Let's start with the error.
In your query, you compare the uid field to the current user. Assuming Social is your user model, your query should include
Social.query.filter(Social.uid == current_user.uid)
Your other problem is how to access the results of your query. Methods like filter and filter_by return a BaseQuery(http://flask-sqlalchemy.pocoo.org/2.1/api/#flask.ext.sqlalchemy.BaseQuery). BaseQuery objects have several methods that expose the results depending on your needs. In this case it sounds like you want all(http://flask-sqlalchemy.pocoo.org/2.1/api/#flask.ext.sqlalchemy.BaseQuery.all).
Putting this all together you get
test = Social.query.filter(Social.uid == current_user.uid).all()
Once in your template, you'll probably want to iterate over test rather than just echoing it directly.
{% for user in test %}
{{ user }}
{% endfor %}
If you haven't defined Social.__str__, the output won't be very useful, but this should be enough to get you moving in the right direction.
I'm trying to prove that in a table we have the following table labels. Date, amount, comment.
<table class="grid-table-body">
<thead>
<tr>
<th>Date</th>
<th>Amount (£)</th>
<th>Description</th>
</tr>
</thead>
<tbody>
.....
.....
.....
</tbody>
</table>
I've got as far as proving the table is present!
var myTable = element(by.css('.grid-table-body'));
expect(myTable.isPresent()).toBeTruthy();
How can I loop through each <th> and get the text. If I was just to put them into an array I could prove they are what they should be. i.e.
expect(data.get(0).getText()).toBe("Date");
Would be enough (I think)
First locate the elements, then you can call getText():
var headers = $$(".grid-table-body thead th");
expect(headers.getText()).toEqual(["Date", "Amount (£)", "Description"]);
To check that all of the headers are visible, you can either use:
expect(headers.isDisplayed()).toEqual([true, true, true]);
Or, check if there is no false in the array:
expect(headers.isDisplayed()).not.toContain(false);
You can also map()/reduce() it to a single boolean value.
My html code is:
enter code here:
<table>
<tbody>
<tr>
<td class="item item-selected" id="gwt-uid-537" role="menuitem">Test Customer 1<br>#34</td>
</tr>
<tr>
<td class="item" id="gwt-uid-538" role="menuitem">TEST CUSTOMER 2<br>#1,9874563210</td>
</tr>
<tr>
<td class="item" id="gwt-uid-539" role="menuitem">test <br>test</td>
</tr>
</tbody>
</table>
What i want to do is just find the Customer Name (for ex: TEST CUSTOMER 2) before break-line tag and then click on that row.
I have tried as follows:
String ExpCustName = "TEST CUSTOMER 2";
Thread.sleep(1000);
WebElement FindCust = driver.findElement(By.xpath("//div[#class='customer']/table/tbody/tr/td/input[#class='gwt-SuggestBox']"));
FindCust.sendKeys("TES");
List<WebElement> CustList = driver.findElements(By.xpath("//div[#class='suggestPopupMiddleCenterInner suggestPopupContent']//table//tr"));
for(int i=0;i<CustList.size();i++){
String ActCustName = CustList.get(i).getText();
System.out.println(ActCustName);
Thread.sleep(1000);
if(ActCustName.contains(ExpCustName)){
CustList.get(i).click();
}
}
// find the customer table
WebElement table = driver.findElement(By.xpath("//div[#class='customer']/table"));
// find the row
WebElement customer = table.findElement(By.xpath("//tr/td[contains(text(), 'TEST CUSTOMER 2')]"));
// click on the row
customer.click();
You might need to tweak a bit the two xpath expressions to match your specific page.
What i understood from this question is:
List<WebElement> CustList = driver.findElements(By.xpath("//div[#class='suggestPopupMiddleCenterInner suggestPopupContent']//table//tr"));
for(int i=0;i<CustList.size();i++){
String ActCustName = CustList.get(i).getText();
System.out.println(ActCustName);
Thread.sleep(1000);
if(ActCustName.contains(ExpCustName)){
CustList.get(i).click();
}
The above part of code is to click on "TEST CUSTOMER 2"
for that you can use the below statement:
driver.findElement(By.xpath("//div[#class='suggestPopupMiddleCenterInner suggestPopupContent']//table/tbody/tr[./td[text()='TEST CUSTOMER 2']]")).click();
And i am didn't understood is:
WebElement FindCust = driver.findElement(By.xpath("//div[#class='customer']/table/tbody/tr/td/input[#class='gwt-SuggestBox']"));
FindCust.sendKeys("TES");
What is the purpose of above code?
static WebDriver driver = new FirefoxDriver();
private static WebElement findElementByTagAttr(String tagName, String attrName, String attValue)
{
List<WebElement> elements = driver.findElements(By.tagName(tagName));
WebElement elementToFind = null;
for(WebElement element : elements)
{
if(element.getAttribute(attrName).equals(attValue))
{
elementToFind = element;
break;
}
}
return elementToFind;
}
In Ruby, I have found the following to work quite well. First some background - I am using .properties files to host my element IDs and my values (URLs, text field entries, etc), so I needed to insert a value into the middle of my element ID. My solution has been to break up the xpath into two element id pointers this:
driver.find_element(:xpath, $elementIDs["FIRST_PART_OF_XPATH"] + $props["REQUIRED_VALUE"] + $elementIDs["END_OF_XPATH"]).click
It's not pretty, but it is effective. I hope this helps the next Ruby guy looking for a solution.
EDIT: Sorry, I got distracted while writing this. The xpath is //td[contains(., 'Blah')] where Blah is the text provided by $props. My pointer file looks like this:
FIRST_PART_OF_XPATH=//td[contains(., 'END_OF_XPATH=')]
I can readily change the text I'm searching for by editing the $props file with the required text. Like I said, it's not pretty code, but it works a tick.
This is the model:
class Rep(db.Model):
author = db.UserProperty()
replist = db.ListProperty(str)
unique = db.ListProperty(str)
date = db.DateTimeProperty(auto_now_add=True)
I am writing replist to datastore:
L = []
rep = Rep()
s = self.request.get('sentence')
L.append(s)
rep.replist = L
rep.put()
and retrieve
mylist = rep.all().fetch(1)
I assume that mylist is a list. How do I print its elements? When I try it I end up with the object; something like [<__main__.Rep object at 0x04593C30>]
Thanks!
EDIT
#Wooble: I use templates too. What I don't understand is that; I print the list L like this:
% for i in range(len(L)):
<tr>
<td>${L[i]}</td>
</tr>
% endfor
And this works. But the same thing for mylist does not work. And I tried to get the type of mylist with T = type(mylist) that did not work either.
If you use fetch(1), you'll get a list of 1 element (or None, if there are no entities to fetch).
Generally, to print all of the elements of each entity in a list of entities, you can do something like:
props = Rep.properties().keys()
for myentity in mylist:
for prop in props:
print "%s: %s" % (prop, getattr(myentity, prop))
Although most people would just be using a template to display the entities' data in some way.
The result of rep.all().fetch(1) is an object. You will need to iterate like this:
{% for i in mylist %}
<tr>
<td>{{i.author }}</td>
...
</tr>
{% endfor %}
If you want to print i.replist (list), you can print it using Django's template function join eg:
{% for i in mylist %}
<tr>
<td>{{i.replist|join:"</td><td>" }}</td>
</tr>
{% endfor %}