I have noticed with model objects in django that I can do:
MyModel.objects.all()
I can do this without making a new MyModel object. How/why does this work?
Edited the question:
I am not asking about the base Model class, but I am talking about a model called MyModel that extends from the base Model class
What is Model.objects
Model classes, have a Manager class, you can get it like this:
YourModel.objects
The Manager is the one making SQL queries, for example, this will return a QuerySet:
YourModel.objects.all()
A QuerySet behaves mostly like a normal python list, except that it will make an SQL query when it is first evaluated.
The base model class has no manager !
So you cannot do Model.objects.all() as you said:
In [1]: from django.db.models import Model
In [2]: Model.objects
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/home/jpic/env/local/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 Model.objects
AttributeError: type object 'Model' has no attribute 'objects'
A QuerySet will fail if the table doesn't exist !
It will throw a DatabaseError:
50 def execute(self, query, args=None):
51 try:
---> 52 return self.cursor.execute(query, args)
53 except Database.IntegrityError, e:
54 raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
DatabaseError: relation "formapp_testmodel" does not exist
LINE 1: SELECT "formapp_testmodel"."id" FROM "formapp_testmodel" LIM...
If you define a model class MyModel(models.Model) and then run python manage.py syncdb, django will create a databse table yourapp_mymodel. You can run queries against that db table that return no tuples, so you can create a queryset that contains no results - eg MyModel.objects.none().
The queryset api would be pretty hopeless if it threw an exception every time you ran a query that returned no results.
(I've assumed that you meant to ask why you can do MyModel.objects.all() rather than Model.objects.all(). As jpic shows in his answer you can't do Model.objects.all().
Related
I am trying to migrate some data from one table to another, and I have the following script:
def forward_func(apps, schema_editor):
targetModel = apps.get_model("target", "some_target")
targetModel.objects.all().update(a='other__table__a')
both fields are boolean, and the data inside the original table has no problem and has correct type.
For some reason, I'm getting this message:
ValidationError: [u"'other__table__a' value must be either True or False."]
From the django doc (v1.11), I can't really find a topic talking directly about this, but I've found
However, unlike F() objects in filter and exclude clauses, you can’t introduce joins when you use F() objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F() object, a FieldError will be raised:
# This will raise a FieldError
>>> Entry.objects.update(headline=F('blog__name'))
Does that mean I simply cannot call .update using foreinkeys? Do I have to loop through every object and update this way?
I've been looking at Marty Alchin's Apress book 'ProDjango' and I've run into an issue with the last chapter (chapter 11). I'm a relative noob at Python and Django, and although I've tried searching around I can't put my finger on something similar through this and other forums. I have seen Is Pro Django book still relevant? on this site but doesn't answer any specific questions.
The problem revolves around the trying to create a mechanism to track changes - a history of additions, changes and deletions. The first step is creating a user field on models you want to track. In the example project he has created a specialised ForeignKey field hard-coded to relate to Django's built-in 'User' model:
from django.db import models
from django.contrib.auth.models import User
class CurrentUserField(models.ForeignKey):
def __init__(self, **kwargs):
super(CurrentUserField, self).__init__(User, null=True, **kwargs)
There is also a 'contrib_to_class() method later. The class is in a seperate models.py file from the models to which is to be applied.
The use, as I understand, is to add a new field referencing this new field class in your model:
e.g.
class SimpleModel(models.Model):
a_user = CurrentUserField()
But the problem is that when I syncdb the field is nowhere to be found, a 'FieldError' is the usual result trying to access it.
There are many other elements in the book's solution that I haven't tried to copy here, but this is the first and fundamental part.
I'm guessng that changes in Django and/or Python itself are responsible here. Has anyone any pointers?
Thanks.
EDIT: Given the class below in registration.py which is the current_user folder. This is also where you find the models.py holding the CurrentUserField class. The InformationRequest models has:
user = CurrentUserField()
as its last field. All imports are present and appear correct.
class FieldRegistry(object):
_registry = {}
def add_field(self, model, field):
reg = self.__class__._registry.setdefault(model, [])
reg.append(field)
def get_fields(self, model):
return self.__class__._registry.get(model, [])
def __contains__(self, model):
return model in self.__class__._registry
In [1]: from current_user.registration import FieldRegistry
In [2]: from inforequest.models import InformationRequest
In [3]: registry = FieldRegistry()
In [4]: registry.add_field(InformationRequest, InformationRequest._meta.get_field('user'))
---------------------------------------------------------------------------
FieldDoesNotExist Traceback (most recent call last)
<ipython-input-4-6fcbbdcae066> in <module>()
----> 1 registry.add_field(InformationRequest, InformationRequest._meta.get_field('user'))
/usr/local/lib/python2.7/dist-packages/django/db/models/options.pyc in get_field(self, name, many_to_many)
353 if f.name == name:
354 return f
--> 355 raise FieldDoesNotExist('%s has no field named %r' % (self.object_name, name))
356
357 def get_field_by_name(self, name):
FieldDoesNotExist: InformationRequest has no field named 'user'
Trying to look at the admin generates "Unknown field(s)..."
I think I've found an answer to my question: django-simple-history (https://django-simple-history.readthedocs.org/en/latest/), inasmuch it provides part of solution I was trying to achieve and apparently it was built on Marty Alchin's code in Pro Django.
I am writing a django-nonrel based app and using admin view functionality provided by Django.
I want a Many-to-many relationship between two models and for this, I am using ListField found inside djangotoolbox.fields
To provide a custom form field, I have overridden ListField with another class ModelListField as described in this question which overrides formfield function to return a MultipleChoiceField form widget.
The view part works fine but I am unable to save the model using sqlite3 backend.
Assume, two models (Standard Many-to-many relationship between note and tags)
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=255)
class Note(models.Model):
tags = ModelListField(db.ForeignKey(Tag))
With these change, add note page appears correctly in admin interface but when I try to save the note, I get the following exception:
InterfaceError, Error binding parameter 0 - probably unsupported type.
inside django\db\backends\sqlite3\base.py in execute, line 234
The line 234 reads as follows:
class SQLiteCursorWrapper(Database.Cursor):
"""
Django uses "format" style placeholders, but pysqlite2 uses "qmark" style.
This fixes it -- but note that if you want to use a literal "%s" in a query,
you'll need to use "%%s".
"""
def execute(self, query, params=()):
query = self.convert_query(query)
try:
234 ----> return Database.Cursor.execute(self, query, params)
except Database.IntegrityError, e:
raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
except Database.DatabaseError, e:
raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
And query & params passed to call are:
query: 'INSERT INTO "note" ("tags") VALUES (?)'
params: [1, 2, 3]
where 1, 2, 3 are pk of three tag fields in database.
When creating model, I specify the COLUMN TYPE of tags as "ListField" i.e.
CREATE table SQL query is:
CREATE TABLE "notes" (
"id" integer NOT NULL PRIMARY KEY,
"tags" ListField NOT NULL
)
Database query execute call above barfs when it sees the list [1,2,3].
Instead of list, I tried to pass the list as smart_unicode(list) or just a string "1 2 3" but then ListField throws error while validating (in get_db_prep_value) because it expects list.
I am unable to understand whether it is correct to pass the list object to Database.Cursor.execute call above or something is missing as ListField is correctly expecting list but when writing to database, someone should have converted this list into string etc..?
There's no good example of how to use ListField :-(
Thanks for reading a long & boring description..
I figured out it is the responsibility of get_db_prep_save to prepare data in correct format for saving to database.
So, in ModelListField, I override get_db_prep_save and convert it to string to fix the "Unsupported type" error.
def get_db_prep_save(self, value, connection):
retval = super(ModelListField, self).get_db_prep_save(value)
return unicode(retval)
I also faced an issue with Select Widget not showing tags with pk > 10 as selected.
Inside django-non 1.3,
I had to add eval in below function:
class Select(Widget):
def render_options(self, choices, selected_choices):
**if(type(selected_choices) != list):
selected_choices = eval(selected_choices)**
This was done because render_option was called with list as string i.e. "[1,2,3]" instead of just [1,2,3], so string was converted back to list using eval.
Not sure if these two are related or latter issue is bug with django-nonrel.
As dragonx said, maybe it's not a good idea to test with sqlite3 and django-nonrel.
I will change my backend soon.
Upon initialization of an application in django, before the postgresql database has been created, if one tries to get/all/create an object they will usually see an error like this:
>>> Model.objects.all()
{StackTrace}
...
DatabaseError: relation "model" does not exist
...
In my application I would like to be able to test for the models existence and run code if it exists, is this possible using django?
Pseudocode:
if not (table_exists(model))
return
my_models = Model.objects.all()
...
You could catch the exception that's thrown while trying to access the model:
from django.db import DatabaseError
try:
Model.objects.exists()
except DatabaseError:
print 'DB not yet initialized'
else:
print 'DB table exists'
I don't know why you would want to do this, but could you just issue raw sql to see if the table exists??
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
I am using Django 1.3 and trying to use .exists() on a model entry but get the error listed below. Exists() was included in Django 1.2 so I should have access to it. I verified my version using django.get_version and it was okay.
Querying MyModel based on pk only returns an entry but querying with .exists() throws an error. Do I need to imports something?
>>> m = MyModel.objects.get(pk=1)
>>> m
<MyModel: Model field entry 1>
>>> m = MyModel.objects.get(pk=1).exists()
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'MyModel' object has no attribute 'exists'
exists() is a method of a QuerySet.
get() returns a single model instance, and will raise an exception Entry.DoesNotExist if that instance doesn't exist. So you'll need to wrap this in a try/except block if you're not sure if an instance with that id exists.
I'm using Django 1.7 on my project and my codes like :
try:
temp_query_set = YourModelName.functionName()
except ObjectDoesNotExists:
<do something>
note that, my code (at first) using if query_set.exists()
it works fine when there is no query set returned, but raise error object does not have attribute 'exists' when there is something returned.
so pls try avoid using if <something>.exists()
CMIIW
try use .filter() instead .get(), like this:
m = MyModel.objects.filter(pk=1).exists()
y = MyModel.objects.filter(pk=2).exists()
print(m)
print(y)
output must to be a bool, exemple:
False
True
suposing that m does not exist and y exists