How to write joins in django,i have gone through below django documentation ,but joins are not working for my model
http://docs.djangoproject.com/en/1.2/topics/db/queries/#lookups-that-span-relationships
and models/many_to_many/
and some blogs
My Model :
class Profile(models.Model):
name = models.CharField(max_length=50, primary_key=True)
assign = models.CharField(max_length=50)
doj = models.DateField()
dob = models.DateField()
class Meta:
db_table = u'profile'
def __str__(self):
return '%s %s %s %s' % ( self.name,self.assign,self.doj,self.dob)
def __unicode__(self):
return u'%s %s %s %s' % ( self.name,self.assign,self.doj,self.dob)
enter code here
class working(models.Model):
w_name =models.ForeignKey(Profile, db_column='w_name')
monday = models.IntegerField(null=True, db_column='monday', blank=True)
tuesday = models.IntegerField(null=True, db_column='tuesday', blank=True)
wednesday = models.IntegerField(null=True, db_column='wednesday', blank=True)
class Meta:
db_table = u'working'
def __str__(self):
return '%s %s %s %s' % ( self.w_name,self.monday,self.tuesday,self.wednesday)
def __unicode__(self):
return u'%s %s %s %s' % ( self.w_name,self.monday,self.tuesday,self.wednesday)
I am trying to do join between two tables profile and workingday
like m=working.objects.filter(name='sushanth').select_related()
if i run above query i'll get
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/pymodules/python2.6/django/db/models/manager.py", line 129, in filter
return self.get_query_set().filter(*args, **kwargs)
File "/usr/lib/pymodules/python2.6/django/db/models/query.py", line 498, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/lib/pymodules/python2.6/django/db/models/query.py", line 516, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/usr/lib/pymodules/python2.6/django/db/models/sql/query.py", line 1675, in add_q
can_reuse=used_aliases)
File "/usr/lib/pymodules/python2.6/django/db/models/sql/query.py", line 1569, in add_filter
negate=negate, process_extras=process_extras)
File "/usr/lib/pymodules/python2.6/django/db/models/sql/query.py", line 1737, in setup_joins
"Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'name' into field. Choices are: monday, tuesday, wednesday, w_name
I need to query where i can join working and profile.
support
select working.*,profile.assign,profile.doj from working join profile where name=w_name ;
I know django won't support joins,inner join is also okay for me.
Can any one help on this.........................?
Please format your question so that the code is readable (the {} icon) otherwise it is very hard to read.
working.objects.filter(name= will fail because your working model doesn't have a name field.
From the docs you linked to:
Django offers a powerful and intuitive
way to "follow" relationships in
lookups, taking care of the SQL JOINs
for you automatically, behind the
scenes. To span a relationship, just
use the field name of related fields
across models, separated by double
underscores, until you get to the
field you want.
That translates to:
m = working.objects.filter(w_name__name='sushanth').select_related()
Related
I'm getting ValueError: Cannot force an update in save() with no primary key. while code hitting to exception and run get_or_create code. Model has it's table in database with auto incremental id field. And also this is not an update process. I can't get why Django behaving like this.
ERROR:
Traceback (most recent call last):
File "x.py", line 1980, in <module>
getattr(a, islem)()
File "x.py", line 718, in method
Slug='undefined', Status=False)
File "~/env/local/lib/python2.7/site-packages/django/db/models/manager.py", line 135, in get_or_create
return self.get_query_set().get_or_create(**kwargs)
File "~/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 385, in get_or_create
obj.save(force_insert=True, using=self.db)
File ~/core/modules/xx/models.py", line 78, in save
super(Categories, self).save(args, kwargs)
File "~/env/local/lib/python2.7/site-packages/django/db/models/base.py", line 460, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "x/env/local/lib/python2.7/site-packages/django/db/models/base.py", line 541, in save_base
raise ValueError("Cannot force an update in save() with no primary key.")
ValueError: Cannot force an update in save() with no primary key.
CODE:
try:
category = Categories.objects.get(Code=category_code)
except ObjectDoesNotExist:
category, created = Categories.objects.get_or_create(
Name='Undefined', Code='undefined',ParentCategoryID=None, OrderID=0,
Slug='undefined', Status=False)
MODEL:
class Categories(models.Model):
Name = models.CharField(max_length=155)
Code = models.CharField(max_length=255)
ParentCategoryID = models.ForeignKey('self', related_name='SubCategory', null=True, blank=True)
Level = models.IntegerField(default=0, max_length=10, editable=False)
OrderID = models.IntegerField(blank=True, max_length=10)
Slug = models.SlugField(max_length=250)
CreateDate = models.DateTimeField(auto_now_add=True)
LastUpdateDate = models.DateTimeField(auto_now=True)
Status = models.BooleanField(default=True)
def save(self, *args, **kwargs):
if self.ParentCategoryID is not None:
parent = Categories.objects.get(id=self.ParentCategoryID.id)
self.Level = parent.Level + 1
if self.OrderID <= 0:
try:
top = Categories.objects.order_by('-OrderID')[0]
self.OrderID = top.OrderID + 1
except:
self.OrderID = 1
super(Categories, self).save(args, kwargs)
You need to use the * and ** when you call super as well:
super(Categories, self).save(*args, **kwargs)
Note there are some other strange things in this code too. Primarily this line:
parent = Categories.objects.get(id=self.ParentCategoryID.id)
is doing two identical queries for no reason; self.ParentCategoryID is already the parent object. You should just do:
parent = self.ParentCategoryID
which should lead you to the conclusion that the ParentCategoryID is badly named; it contains the actual object, not the ID.
Note also that there are quite a few style violation; Python prefers lower_case_with_underscore for attribute names, and Django prefers singular model names. The related name for the foreign key should be plural, though, as it will refer to multiple category objects. So:
class Category(models.Model):
name = models.CharField(max_length=155)
code = models.CharField(max_length=255)
parent_category = models.ForeignKey('self', related_name='sub_categories', null=True, blank=True)
...
I was using Whoosh with Haystack and everything works fine, I want to change to ElasticSearch but when I run rebuild_index I get the following error. I am not sure why the error is happening, it appears to be complaining about my Models and the data, however if I switch back to Whoosh search/indexing all work fine.
Django==1.8.4
elasticsearch==2.3.0
django-haystack==2.4.1
File
"C:\Users\user.virtualenvs\pguider\lib\site-packages\elasticsearch\serializer.py",
line 50, in dumps
raise SerializationError(data, e) elasticsearch.exceptions.SerializationError: ({u'django_id': u'1',
'created': '2016-02-13T22:19:28.037000+00:00', 'suppl ier_code':
u'BL32291', 'related_supplier_parts': [], u'django_ct':
u'products.supplierpart', 'supplier': u'Parts Town', 'text':
u'BL32291\n32291\nBlodgett\n\nParts Town\n\n\n', 'part_code':
u'32291', u'id': u'products.supplierpart.1'}, Type Error("Unable to
serialize [] (type: )",))
Here are my models:
from django.db import models
class Supplier(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return u'%s' % self.name
class Part(models.Model):
name = models.CharField(max_length=200, null=True)
code = models.CharField(max_length=30, null=True)
def __unicode__(self):
return u'%s %s' % (self.code, self.name)
class SupplierPart(models.Model):
part = models.ForeignKey(Part)
supplier = models.ForeignKey(Supplier)
supplier_code = models.CharField(max_length=30)
description = models.CharField(max_length=200)
price = models.CharField(max_length=6, null=True)
sale_price = models.CharField(max_length=6, null=True)
quantity = models.IntegerField(null=True)
photo = models.ImageField(upload_to='products', null=True)
url = models.URLField()
created = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.supplier_code
#property
def related_supplier_parts(self):
return self.part.supplierpart_set.all().exclude(pk=self.pk)
The problem lays in your property related_supplier_parts. Elastic search can't serialize it. This property returns queryset.
>>> parts = Part.objects.all()
>>> import json
>>> json.dumps({'related_supplier_parts': parts})
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/json/encoder.py", line 184, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: [] is not JSON serializable
How to solve it?
The best for any project is to not complicate your models with properties. Although we know they are widely used and easy to write. I have never used any property in my Django career. In my current project I have 153 models and not a single property. In 99% cases you don't need them because simple method get_related_supplier_parts should do same job.
class SupplierPart(models.Model):
[...]
created = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.supplier_code
def get_related_supplier_parts(self):
return self.part.supplierpart_set.all().exclude(pk=self.pk)
One more downside of #property is whenever you try to serialize object additional queries will be executed and think about serializing millions of them. You don't need to worry about it with method.
If you reject this for some reason you will need to find a way to convert this query to list. Probably in your index class defining new field:
class MyIndex(indexes.SearchIndex, indexes.Indexable):
[...]
related_supplier_parts = indexes.MultiValueField()
def prepare_related_supplier_parts(self, obj):
return [part.id for part in obj.related_supplier_parts]
my old models.py :
from django.db import models
from taggit.managers import TaggableManager
from django.utils.encoding import smart_unicode
import markdown
class PublishedManager(models.Manager):
def get_query_set(self):
return super(PublishedManager, self).get_query_set().filter\
(is_published=True)
class Category(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return u"%s" %(self.name)
class BookMarks(models.Model):
name = models.CharField(max_length=255)
url = models.URLField()
date_time = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return u"%s %s %s" %(self.name, self.url, self.date_time)
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
excerpt = models.TextField(blank=True, help_text="A small teaser of\
your content")
content = models.TextField(blank=True, null=True)
contentmarkdown = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
is_published = models.BooleanField(default=True)
objects = models.Manager()
published_objects = PublishedManager()
tags = TaggableManager()
category = models.ForeignKey(Category)
def save(self):
self.content = markdown.markdown(self.contentmarkdown)
super(Post, self).save() # Call the "real" save() method.
class Meta:
ordering = ("date_created",)
def __unicode__(self):
return smart_unicode("%s %s %s %s %s" %(self.title, self.content, self.is_published, self.category, self.tags))
def get_absolute_url(self):
return "/posts/%s/" % self.id
class Book(models.Model):
name = models.CharField(max_length=55)
author = models.CharField(max_length=55)
image = models.ImageField(upload_to="static/img/books/")
body = models.TextField(blank=True, null=True)
bodymarkdown = models.TextField()
def __unicode__(self):
return u"%s %s" %(self.name, self.author)
def get_absolute_url(self):
return "/books/%s/" % self
.id
and after add "category = models.ForeignKey(Category)" this field to Book and BookMarks table, my new models.py like this:
from django.db import models
from taggit.managers import TaggableManager
from django.utils.encoding import smart_unicode
import markdown
class PublishedManager(models.Manager):
def get_query_set(self):
return super(PublishedManager, self).get_query_set().filter\
(is_published=True)
class Category(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return u"%s" %(self.name)
class BookMarks(models.Model):
name = models.CharField(max_length=255)
url = models.URLField()
date_time = models.DateTimeField(auto_now_add=True)
category = models.ForeignKey(Category)
def __unicode__(self):
return u"%s %s %s" %(self.name, self.url, self.date_time)
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
excerpt = models.TextField(blank=True, help_text="A small teaser of\
your content")
content = models.TextField(blank=True, null=True)
contentmarkdown = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
is_published = models.BooleanField(default=True)
objects = models.Manager()
published_objects = PublishedManager()
tags = TaggableManager()
category = models.ForeignKey(Category)
def save(self):
self.content = markdown.markdown(self.contentmarkdown)
super(Post, self).save() # Call the "real" save() method.
class Meta:
ordering = ("date_created",)
def __unicode__(self):
return smart_unicode("%s %s %s %s %s" %(self.title, self.content, self.is_published, self.category, self.tags))
def get_absolute_url(self):
return "/posts/%s/" % self.id
class Book(models.Model):
name = models.CharField(max_length=55)
author = models.CharField(max_length=55)
image = models.ImageField(upload_to="static/img/books/")
body = models.TextField(blank=True, null=True)
bodymarkdown = models.TextField()
category = models.ForeignKey(Category)
def __unicode__(self):
return u"%s %s" %(self.name, self.author)
def get_absolute_url(self):
return "/books/%s/" % self.id
class Errors(models.Model):
name = models.CharField(max_length=255)
created = models.DateTimeField(auto_now_add=True)
body = models.TextField(blank=True, null=True)
bodymarkdown = models.TextField()
def __unicode__(self):
return self.name
def get_absolute_url(self):
return "/errors/%s/" % self.id
I used south. Everything was going OK but after this line:
? 1. Quit now, and add a default to the field in models.py
? 2. Specify a one-off value to use for existing columns now
? 3. Disable the backwards migration by raising an exception.
? Please select a choice: 2
? Please enter Python code for your one-off default value.
? The datetime module is available, so you can do e.g. datetime.date.today()
>>> datetime.datetime.now()
I get an error like this:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 196, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 232, in execute
output = self.handle(*args, **options)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/management/commands/migrate.py", line 108, in handle
ignore_ghosts = ignore_ghosts,
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/__init__.py", line 213, in migrate_app
success = migrator.migrate_many(target, workplan, database)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 235, in migrate_many
result = migrator.__class__.migrate_many(migrator, target, migrations, database)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 310, in migrate_many
result = self.migrate(migration, database)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 133, in migrate
result = self.run(migration)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 106, in run
dry_run.run_migration(migration)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 191, in run_migration
self._run_migration(migration)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 178, in _run_migration
raise exceptions.FailedDryRun(migration, sys.exc_info())
south.exceptions.FailedDryRun: ! Error found during dry run of '0012_auto__del_field_book_category__add_field_book_category1__del_field_boo'! Aborting.
Traceback (most recent call last):
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 175, in _run_migration
migration_function()
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/migration/migrators.py", line 57, in <lambda>
return (lambda: direction(orm))
File "/home/ada/mainproject/blog/migrations/0012_auto__del_field_book_category__add_field_book_category1__del_field_boo.py", line 17, in forwards
keep_default=False)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/db/generic.py", line 44, in _cache_clear
return func(self, table, *args, **opts)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/db/generic.py", line 402, in add_column
sql = self.column_sql(table_name, name, field)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/south/db/generic.py", line 688, in column_sql
default = field.get_db_prep_save(default, connection=self._get_connection())
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 991, in get_db_prep_save
connection=connection)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 292, in get_db_prep_save
prepared=False)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 284, in get_db_prep_value
value = self.get_prep_value(value)
File "/home/ada/virtualenv/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 537, in get_prep_value
return int(value)
TypeError: int() argument must be a string or a number, not 'datetime.datetime'
Please can you tell me Why I get this error? What must I do?
Because your new category field is mandatory (you can't create a book or bookmark without giving it a category), south asked you what to do with the existing books and bookmarks in your database - your latest changes would have made all your current books / bookmarks invalid (since they don't have a category).
Your new category field is represented in your book/bookmark tables using a primary key of the category table. This primary key will likely be an integer (or possibly a string).
South asked you to supply a default primary key. Instead of supplying the primary key of an category object in your database (which would be an integer or a string). You've supplied a datatime object.
It's crapping out when it actually runs the migration because the field doesn't hold datetime objects. It holds integers (or strings). you need to create the migration again and add a valid primary key.
I want to use contains in join query but it gives an error.
Following is my models.py:
class Profile(models.Model):
name = models.CharField(max_length=50, primary_key=True)
assign = models.CharField(max_length=50)
doj = models.DateField()
dob = models.DateField()
class Meta:
db_table = u'profile'
def __str__(self):
return '%s %s %s %s' % ( self.name,self.assign,self.doj,self.dob)
def __unicode__(self):
return u'%s %s %s %s' % ( self.name,self.assign,self.doj,self.dob)
enter code here
class working(models.Model):
w_name =models.ForeignKey(Profile, db_column='w_name')
monday = models.IntegerField(null=True, db_column='monday', blank=True)
tuesday = models.IntegerField(null=True, db_column='tuesday', blank=True)
wednesday = models.IntegerField(null=True, db_column='wednesday', blank=True)
class Meta:
db_table = u'working'
def __str__(self):
return '%s %s %s %s' % ( self.w_name,self.monday,self.tuesday,self.wednesday)
def __unicode__(self):
return u'%s %s %s %s' % ( self.w_name,self.monday,self.tuesday,self.wednesday)
I want to use something like this:
m = working.objects.filter(w_name__name__contains='sushanth')
or
m = working.objects.filter(w_name__name__startswith='sushanth')
The error that I keep getting:
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/manager.py", line 141, in filter
return self.get_query_set().filter(*args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/query.py", line 556, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/query.py", line 574, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/sql/query.py", line 1152, in add_q
can_reuse=used_aliases)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/sql/query.py", line 1092, in add_filter
connector)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/sql/where.py", line 67, in add
value = obj.prepare(lookup_type, value)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/sql/where.py", line 316, in prepare
return self.field.get_prep_lookup(lookup_type, value)
File "/usr/local/lib/python2.6/dist-packages/Django-1.2.4-py2.6.egg/django/db/models/fields/related.py", line 139, in get_prep_lookup
raise TypeError("Related Field has invalid lookup: %s" % lookup_type)
TypeError: Related Field has invalid lookup: startswith
Any suggestions??
Is there some reason why the name field is the primary key?
If there isn't then I would suggest recreating the tables with the name field NOT as the primary key. That might be throwing the filter logic out.
In the following code, I'm tyring to create the method show_pro that will show all Arguments for the Case that are pro.
I am getting this error:
>>> Case.objects.all()[0].show_pro()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/john/mysite/../mysite/cases/models.py", line 23, in show_pro
return self.objects.filter(argument__side__contains='p')
File "/usr/lib/python2.5/site-packages/django/db/models/manager.py", line 151, in __get__
raise AttributeError, "Manager isn't accessible via %s instances" % type.__name__
AttributeError: Manager isn't accessible via Case instances
here is the code:
from django.db import models
from django.contrib.auth.models import User
import datetime
SIDE_CHOICES = (
('p', 'pro'),
('c', 'con'),
('u', 'undecided'),
)
class Case(models.Model):
question = models.CharField(max_length=200)
owner = models.ForeignKey(User)
pub_date = models.DateTimeField('date published')
rating = models.IntegerField()
def __unicode__(self):
return self.question
def was_published_today(self):
return self.put_date.date() == datetime.date.today()
def show_pro(self):
return self.objects.filter(argument__side__contains='p')
class Argument(models.Model):
case = models.ForeignKey(Case)
reason = models.CharField(max_length=200)
rating = models.IntegerField()
owner = models.ForeignKey(User)
side = models.CharField(max_length=1, choices=SIDE_CHOICES)
def __unicode__(self):
return self.reason
Try:
def show_pro(self):
return self.argument_set.filter(side='p')
Basically, you need to do a reverse lookup on the ForeignKey relationship and then filter that to get the related Argument objects that have side='p'.
In the show_pro function, self is not a QuerySet—it refers to the object itself.
You can't call self.objects, objects is a class member, not an field on the instance. THink about it this way, would it make sense to do:
c0 = Case.objects.all()[0]
c1 = c0.objects.all()[1]
Not really. That's what using self does.
Instead, you need to access the instance fields. As Tyson suggested:
class Case(models.Model):
...
def show_pro(self):
return self.argument_set.filter(side='p')
...