Django Model CharField empty string begin saved as ('',)? - python

I'm trying to save data from a facebook graph query, which returns location info in the format:
friend: {
location: {
id: "106078429431815",
name: "London, United Kingdom"
},
}
Or the location key is missing entirely if the user hasn't set that variable, or it's set to 'null'.
The location field in the Model is defined as:
location = models.CharField(max_length=255, blank=True, null=True)
I'm storing the data in the model using the following code, which caters for both the initial query to create the record as well as updates just in case values change in the future:
friend = get_facebook_friend(friend_id=friend_id)
try:
location_name = data['location'].get('name', '')
except:
location_name = ''
if friend:
friend.name = data['name']
friend.location = location_name,
friend.full_clean()
friend.save()
else:
friend = Friend(
name=data['name'],
location=location_name)
friend.full_clean()
friend.save()
This seems to work pretty well for the first insert, which stores values for the Location column in the database as:
- 'London, United Kingdom'
- ''
- NULL
However on subsequent updates, this is storing strange results in the database table, for instance:
(u'London, United Kingdom',)
('',)
(None,)
This same behavior is not observed in other CharFields storing strings from Facebook queries
I'm quite confused D:, Help!

due to the tailing comma:
friend.location = location_name,
assigns the tuple (location_name, ) (the brackets are optional)
to friend.location

Related

NDB StructuredProperty query unexpected result

I have this model:
class State(ndb.Model):
code = ndb.StringProperty(required=True)
name = ndb.StringProperty(required=True)
city_list = ndb.StructuredProperty(City, repeated=True)
country = ndb.KeyProperty(required=True)
class City(ndb.Model):
code = ndb.StringProperty(required=True)
name = ndb.StringProperty(required=True)
I implemented this query:
stateData = State.query( State.city_list.name == 'xyz', State.name=='Punjab' ).fetch()
I want to implement query on State where name is Punjab. But Punjab has many cities, so I filtered by city name xyz.
I'm expecting only the xyz city but I'm getting all the cities in the result.
How can I get just the xyz city in the result?
You're querying for State kinds, so results will be State entities, with their complete city_list property - you can't get just a subset of the city_list. So what you're getting is expected.
You could maybe do a projection query, in which case you'd get a list of State entities, each with just a single city in city_list, see Projections and multiple-valued properties. Watch out for the limitations.
Or you could redesign your models, maybe with separate City entities you can query for directly (instead of structured properties inside the State entity).
you should filter before you fetch. the below syntax is based on an older version of ndb where you use Key property
class State(ndb.Model):
code = ndb.StringProperty(required=True)
name = ndb.StringProperty(required=True)
city_list = ndb.KeyProperty(kind=City, repeated=True)
country = ndb.KeyProperty(required=True)
stateq = State.query( State.name=='Punjab' )
city=stateq.filter(State.City==citykey)
result=city.fetch()
I did not try but it will probably work for structured property as well.

How to use icontains in a key value of a DictField in Django queryset?

Given the following model:
class Team(models.Model):
name = models.CharField(max_length=50)
others = DictField()
And the following code:
bahia = Team()
bahia.name = "E.C. Bahia"
bahia.others = {"title": "Ninguém nos Vence em Vibração!!!"}
bahia.save()
vicetoria = Team()
vicetoria.name = "E.C. Vicetoria"
vicetoria.others = {"title": "Vice de tudo!"}
vicetoria.save()
I want to find the object that have the word vence, (case insensitive) contained in title value of the field others.
I tried something like:
teams = Team.objects.filter(others__title__icontains="vence")
that gives me the following error:
FieldError: Join on field 'others' not permitted. Did you misspell 'title' for the lookup type?
I also already tried:
teams = Team.objects.filter(others__icontains={"title":"vence"})
that returns None and I know there is at least one collection as result.
SOLUTION:
teams = Team.objects.raw_query({"others.title": {"$regex" : "vence", "$options": "i"}})
The i option makes the search insensitive.
I believe (correct me if I'm wrong) that djangotoolbox DictField doesn't support icontain.
To filter the Dict Field you need to do something like:
Team.objects.raw_query({'title': { $regex : /vence/i } })
Check out this answer: How do I filter based on dict contents in a DictField on a model using the Django-MongoDB Engine?
This answer shows how to do case insensitive mongodb queries: How do I make case-insensitive queries on Mongodb?

Django-tables2 - can't I use [A('argument')] inside the "text" parameter?

I'm trying to make this table with a clickable field which changes the boolean for the entry to its opposite value. It works, but I want an alternative text as "False" or "True" does not look nice, and the users are mainly Norwegian.
def bool_to_norwegian(boolean):
if boolean:
return "Ja"
else:
return "Nei"
class OrderTable(tables.Table):
id = tables.LinkColumn('admin_detail', args=[A('id')])
name = tables.Column()
address = tables.Column()
order = tables.Column()
order_placed_at = tables.DateTimeColumn()
order_delivery_at = tables.DateColumn()
price = tables.Column()
comment = tables.Column()
sent = tables.LinkColumn('status_sent', args=[A('id')])
paid = tables.LinkColumn('status_paid', args=[A('id')], text=[A('paid')])
class Meta:
attrs = {'class': 'order-table'}
If you look under the "paid" entry I am testing this right now, why can't I access the data with the same accessor as I do in the args? If I change the args to args=[A('paid')] and look at the link, it does indeed have the correct data on it. The model names are the same as the ones in this table, and "paid" and "sent" are BooleanFields.
This is kind of what I ultimately want:
text=bool_to_norwegian([A('paid')])
Here is what I send to the table:
orders = Order.objects.order_by("-order_delivery_at")
orders = orders.values()
table = OrderTable(orders)
RequestConfig(request).configure(table)
The text argument expects a callable that accepts a record, and returns a text value. You are passing it a list (which it will just ignore), and your function is expecting a boolean instead of a record. There is also no need for using accessors here.
Something like this should work:
def bool_to_norwegian(record):
if record.paid:
return "Ja"
else:
return "Nei"
Then in your column:
paid = tables.LinkColumn('status_paid', text=bool_to_norwegian)
(Note, it is not clear from your question where the data is coming from - is paid a boolean? You may need to adjust this to fit).
As an aside, the way you are passing args to your columns is weird (it seems the documentation also recommends this, but I don't understand why - it's very confusing). A more standard approach would be:
id = tables.LinkColumn('admin_detail', A('id'))
or using named arguments:
id = tables.LinkColumn('admin_detail', accessor=A('id'))

appengine: convert ndb model to go lang struct

I've got a python module and a go module on app engine. The go module is fairly simple and just provides a readonly search interface to the datastore which is populated by the python module.
How do I convert the following ndb model into a go struct:
class Course(ndb.Model):
name = ndb.StringProperty()
neat_name = ndb.StringProperty(required=True)
country = ndb.KeyProperty(kind=Country, required=True)
university = ndb.KeyProperty(kind=University, required=True)
faculty = ndb.KeyProperty(kind=Faculty, required=True)
department = ndb.KeyProperty(kind=Department, required=True)
stage = ndb.KeyProperty(kind=Stage, required=True)
legacy_id = ndb.StringProperty()
course_title = ndb.StringProperty(required=True, indexed=False)
course_description = ndb.TextProperty(required=True)
course_link = ndb.StringProperty(required=True, indexed=False)
#0-5 or None or not has attribute.
course_rating_ = ndb.FloatProperty()
course_review_count_ = ndb.IntegerProperty()
To start with I'll have:
type Course struct {
Name string `datastore:"name"`
NeatName `datastore:"neat_name"`
...
}
For the ndb.KeyProperty properties - Do I just use a string in my struct? & I'll have to parse that string - is that straight forward?
Also can I just ignore the required=True & indexed=False options? Obviously since i'm not doing any writes?
Per https://cloud.google.com/appengine/docs/go/datastore/entities#Go_Properties_and_value_types , String (a short string of up to 500 characters, indexed by default) maps to Go string; Text (a long string up to 1MB, not indexed) also to Go string but always with noindex; for datastore Key there is *datastore.Key, see https://cloud.google.com/appengine/docs/go/datastore/reference#Key ; for Integer, int64; for Float, float64 (you could use shorter ints and floats but the datastore uses 64 bits for each anyway so you might as well:-).
Also can I just ignore the required=True & indexed=False options?
Yes for required, but I believe that, using https://cloud.google.com/appengine/docs/go/datastore/reference , you do have to use option noindex for Text because it's necessary to indicate strings that can be longer than 512 (unicode) characters.
Not sure which versions of go and its datastore package enforce this constraint, but even if the present one doesn't it's safer to respect it anyway -- or else your app might break with a simple Go version upgrade!-)
Here's the code - it's working in production & locally too:
type Course struct {
Name string `datastore:"name"`
NeatName string `datastore:"neat_name"`
Country *datastore.Key `datastore:"country"`
University *datastore.Key `datastore:"university"`
Faculty *datastore.Key `datastore:"faculty"`
Department *datastore.Key `datastore:"department"`
Stage *datastore.Key `datastore:"stage"`
LegacyId string `datastore:"legacy_id"`
CourseTitle string `datastore:"course_title,noindex"`
CourseDescription string `datastore:"course_description"`
CourseLink string `datastore:"course_link,noindex"`
CourseRating float64 `datastore:"course_rating_"`
CourseReviewCount int64 `datastore:"course_review_count_"`
}
and
func (ttt *EdSearchApi) Search(r *http.Request,
req *SearchQuery, resp *SearchResults) error {
c := appengine.NewContext(r)
q := datastore.NewQuery("Course").Limit(1)
var courses []Course
_, err := q.GetAll(c, &courses)
c.Infof("err %v", err)
c.Infof("courses 0: %v", courses[0])
c.Infof("!!!")
return nil
}

Unable to use query with Redis Object Mapper (ROM)

I am using Redis Object Mapper(ROM) here.
This is my model
class User(rom.Model):
name = rom.String(required=True, unique=True)
nickname = rom.String(required=False)
photo = rom.String(required=False)
I am trying -
user1 = User(name="Ankush", nickname="iamkhush",
photo='http://graph.facebook.com/iamkhush/picture')
user1.save()
I get the result when I do
user = User.get(1) #user is a model instance
But when I do
user_obj = User.query.filter(name='Ankush').execute()
I get [ ] (An empty result)
Cant get why is this happening?
There are two parts to this. First, you don't need to use the index if you want to get an item by a column defined with unique=True, but the query is different. Using unique=True and index=False, you can get the item by using the User.get_by() form:
>>> User.get_by(name="Ankush")
<__main__.User object at 0x87070cc>
The primary limitation being that you must pass the full column exactly as it is defined in the column. This is generally useful for keeping unique email addresses (lowercase them first!), usernames (be careful with your capitalization), and other examples.
The second part is that when enabling the index, the index has "case-insensitive unique bag-of-words" semantics for string/text columns (I come from the search engine side of the world, which has substantially different (and arguably better) semantics than typical db queries). So if you want to find entries, you need to use:
>>> class User(rom.Model):
... name = rom.String(required=True, unique=True, index=True)
... nickname = rom.String(required=False)
... photo = rom.String(required=False)
...
>>> user1 = User(name="Ankush", nickname="iamankush", photo="http://graph.facebook.com/iamkhush/picture")
>>> user1.save()
>>> User.query.filter(name="ankush").all()
[<__main__.User object at 0x870738c>]
(also note that .execute() is an alias for .all() ).
If you want to change the case-sensitivity or other behavior with columns defined with index=True, you need to pass a custom keygen argument (you can see rom.util._string_keygen() at https://github.com/josiahcarlson/rom/blob/master/rom/util.py#L149 for rom.String and rom.Text key generation semantics).
You need to pass index=True along with name to allow it to be queried by filter.
class User(rom.Model):
name = rom.Text(required=True, unique=True,index = True,keygen=text_keyge)
nickname = rom.String(required=False)
photo = rom.String(required=False)

Categories

Resources