MongoDB is using string(hash) _id field instead of integer; so, how to get classic id primary key? Increment some variable each time I create my class instance?
class Post(Document):
authors_id = ListField(IntField(required=True), required=True)
content = StringField(max_length=100000, required=True)
id = IntField(required=True, primary_key=True)
def __init__(self):
//what next?
Trying to create new user raises exception:
mongoengine.queryset.OperationError: Tried to save duplicate unique keys
(E11000 duplicate key error index: test.user.$_types_1_username_1
dup key: { : "User", : "admin" })
Code:
user = User.create_user(username='admin', email='example#mail.com',
password='pass')
user.is_superuser = True
user.save()
Why?
There is the SequenceField which you could use to provide this. But as stated incrementing id's dont scale well and are they really needed? Can't you use ObjectId or a slug instead?
If you want to use an incrementing integer ID, the method to do it is described here:
http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Field
This won't scale for a vary large DB/app but it works well for small or moderate application.
1) If you really want to do it you have to override the mongoengine method saving your documents, to make it look for one document with the highest value for your id and save the document using that id+1. This will create overhead (and one additional read every write), therefore I discourage you to follow this path. You could also have issues of duplicated IDs (if you save two records at the exactly same time, you'll read twice the last id - say 1 and save twice the id 1+1 = 2 => that's really bad - to avoid this issue you'd need to lock the entire collection at every insert, by losing performances).
2) Simply you can't save more than one user with the same username (as the error message is telling you) - and you already have a user called "admin".
Related
I want to implement this structural model to store my data on Mongodb with MongoEngine on flask:
skills = [{"asm":"Assembly",
"flag":False,
"date": datetime},
{"java":"Java",
"flag":False,
"date": datetime}]
So I don't know how I can declare and update this kind of structure.
For updating one object I used:
User.objects(skills=form.skills.data).update_one()
However, I don't know how to update more fields in one shot.
I tried with the code below but it doesn’t work.
now = datetime.now()
User.objects(skills=form.skills).update_one(set__skills = ({'ruby':'Ruby'}, {'flag':'true'},{'date':now}))
What kind of fields should I declare on forms.py?
For what I understood, you need a a nested document (skills) into another (who refers to User in this case). For doing something like this you don't have to update atomically a field but append values to the subdocument and the save everything.
Tryin' to follow your example, in your case should do something like this:
user = User.objects(email=current_user.email).get()
To get the BaseQuery that refers to user X through a certain query filter, in my example the email of the current logged user
user.kskills.append(SubDocumentClass(skillName="name_of_the_skill", status=True, date=datetime.now()))
For append a collection to the subdocument list. (I've appended your field)
user.save()
To save everything
I want to maintain a Django model with a unique id for every combination of choices within the model. I would then like to be able to update the model with a new field and not have the previous unique id's change.
The id's can be a hash or integer or anything.
What's the best way to achieve this?
class MyModel(models.Model):
WINDOW_MIN = 5
WINDOW_MAX = 7
WINDOW_CHOICES = [(i,i) for i in range(WINDOW_MIN - 1, WINDOW_MAX - 1)]
window = models.PositiveIntegerField('Window', editable=True, default=WINDOW_MIN, choices=WINDOW_CHOICES)
is_live = models.BooleanField('Live', editable=True, default=False)
unique_id = ....
Given the above example there will be 3 * 2 == 6 unique id's. If I add another editable boolean field, I don't want to change the previous unique id's but I want the new unique id's to be generated for the new boolean field.
The thought process behind this is the parameters in MyModel define the inputs to a function who's results are stored in another Django model MyResultModel by unique_id and the name of the model. The reasoning behind this is there are multiple variants of MyModel each with it's own set unique combination's that get updated regularly but the result set in MyResultModel is the same across MyModel1 to MyModelN. Ideally I would like the unique_id's to be autogenerated. In other words the key for the result set stored in MyResultModel is the model_name (MyModel) and a unique_id. I want to sanely manage this many (MyModel1,...MyModelN) to one (MyResultModel) relationship.
class MyResultModel(models.Model):
unique_id = ...
model_name = models.CharField(max_length=200, default='', blank=False) # Points to a Django Model ex MyModel
result1 = ...
result2 = ...
A common approach, given that all your options are boolean, categorical or small numbers, you could just pack them into a bigger bit field (https://en.wikipedia.org/wiki/Bit_field) and whenever you add a new option, make sure to push it to the most-significant part of your bit field and avoid having a value of 0 (that is, simple add 1 to whatever). Not only would every single unique_id represent a different configuration, you could even do without the model and just use bit operations to extract all your values from the bit field.
I have 2 thing:
First, if you just want to create unique hash for all the combinations
# Just set it all together like
uniq= cb1+cb2+cb3... (a string key is ok =) )
# If it is very very long string ~> we think about using hash to short it (and have same size for all value).
And next:
For your question above:
i can't understand why do you make the model into a complicate thing (like a mess) but still have to solve it:
As i read your ques: you have many variants of Models ~> want to gather it into 1 model res?
So:
it is better to set FK
map = models.ForeignKey(Model_name, null=True)
# but if you have too many model, it can't be help...
So i recomment:
~ create just 1 model, because if you have too many model, you can't even call it to get data (As you did) but when you add more FIELD, unique id ~> should change.
One good way to have special unique_id:
Use the first solution i said.
Or:
Create NEW table just to store YOUR COMBO:
New table will have ALL field and you will SET value for each (or you can write script to create it). ~> You have id for each combo ~> it same as unique id
You can create ALL THE POSSIBLE combo or just check and add when the NEW combo show up
Another possible solution is to store the parameters JsonField
https://bitbucket.org/schinckel/django-jsonfield
I have a series of dictionaries that I want to save if a unique id for each dictionary doesn't already exist in the database. If it does exist it would be good to check the values for each key are the same as their corresponding value in the database and update if not.
What's the best way to do this in Django?
I was thinking something along the lines of:
if Thing.object.get(unique_id=dict1['unique_key']):
thing = Thing()
thing.unique_id = dict1['unique_key']
thing.property = dict1['other_key']
thing.save()
I'm not sure how the else block should work?
(Note can the primary key autofield id be non sequential so I can store the unique id from the dict in the default Model id field without needing an additional unique id column?)
the best way to achieve this is to use the update_or_create method in a similar way to Javier's response.
thing, created = Thing.object.update_or_create(
unique_id=dict1['unique_key'],
defaults={'property': dict1['other_key']}
)
Your best bet is to do this:
from django.forms.models import modelform_factory
# Do NOT do this in your view for every request
# add this to your <app>/forms.py and import it (this is just an example)
ThingForm = modelfor_factory(Thing, exclude=[])
# end
# in your view
thing, created = Thing.object.get_or_create(
unique_id=dict1['unique_key'],
defaults={'property': dict1['other_key']}
)
# already exist
if not created:
form = ThingForm(dict1, instance=thing)
# you can also see what changed using `form.changed_data`
if form.has_changed():
form.save()
Internally it will do exactly what you're trying to do, but its easier on the eyes.
https://github.com/django/django/blob/master/django/db/models/query.py#L454
can the primary key autofield id be non sequential so I can store the unique id from the dict in the default Model id field without needing an additional unique id column?
Yes, yes, it can. I override the hash builtin to return unique identifiers for records. A simple hash function for a dictionary follows:
def __hash__(self):
hash_value = sum([hash(v) for v in self.values()])
return hash_value
I hope that helps.
I have a model based on ndb, while saving it, I stored 'id' field with current logged-in user's user id. (Why I am doing this? Actually this model used to be based on db.Model and key_name has this user's id. Now, I am converting it to ndb)
m= Modelclass(id = str(users.get_current_user().used_id()),
--- Other fields ---
m.put()
This model's edit form sends this 'id' and I wanted to get corresponding 'key' from it. But, I got "Key id number is too long; received 'some big_number'". Tried both ways
Modelclass.get_by_id(<id>).key
OR
ndb.Key('Modelclass', <id>)
This is one case, there may be other cases where user can store some big number in 'id' field. In these scenarios, we can't extract key from 'id'. So, how to solve such a problem.
I am new to ndb. Thanks for any help.
Looks like your value is an int, not a string. But you converted it into a string when creating the entitiy. There's a simple solution:
ndb.Key('Modelclass', str(<id>))
Good luck!
Basically, I have a table with a bunch of foreign keys and I'm trying to query only the first occurrence of a particular key by the "created" field. Using the Blog/Entry example, if the Entry model has a foreign key to Blog and a foreign key to User, then how can I construct a query to select all Entries in which a particular User has written the first one for the various Blogs?
class Blog(models.Model):
...
class User(models.Model):
...
class Entry(models.Model):
blog = models.Foreignkey(Blog)
user = models.Foreignkey(User)
I assume there's some magic I'm missing to select the first entries of a blog and that I can simple filter further down to a particular user by appending:
query = Entry.objects.magicquery.filter(user=user)
But maybe there's some other more efficient way. Thanks!
query = Entry.objects.filter(user=user).order_by('id')[0]
Basically order by id (lowest to highest), and slice it to get only the first hit from the QuerySet.
I don't have a Django install available right now to test my line, so please check the documentation if somehow I have a type above:
order by
limiting querysets
By the way, interesting note on 'limiting queysets" manual section:
To retrieve a single object rather
than a list (e.g. SELECT foo FROM bar
LIMIT 1), use a simple index instead
of a slice. For example, this returns
the first Entry in the database, after
ordering entries alphabetically by
headline:
Entry.objects.order_by('headline')[0]
EDIT: Ok, this is the best I could come up so far (after yours and mine comment). It doesn't return Entry objects, but its ids as entry_id.
query = Entry.objects.values('blog').filter(user=user).annotate(Count('blog')).annotate(entry_id=Min('id'))
I'll keep looking for a better way.
Ancient question, I realise - #zalew's response is close but will likely result in the error:
ProgrammingError: SELECT DISTINCT ON expressions must match initial
ORDER BY expressions
To correct this, try aligning the ordering and distinct parts of the query:
Entry.objects.filter(user=user).distinct("blog").order_by("blog", "created")
As a bonus, in case of multiple entries being created at exactly the same time (unlikely, but you never know!), you could add determinism by including id in the order_by:
To correct this, try aligning the ordering and distinct parts of the query:
Entry.objects.filter(user=user).distinct("blog").order_by("blog", "created", "id")
Can't test it in this particular moment
Entry.objects.filter(user=user).distinct("blog").order_by("id")