In Django 1.8
class OtherModel(models.Model):
somefield = models.CharField(max_length=20)
class Orderform(models.Model):
sell_item_id = models.CharField(max_length=20)
class Selled(models.Model):
orderform = models.ForeignKey("Orderform")
sell_count = models.IntegerField()
something = OtherModel.objects.get(id=sell_item_id)
I need to use something like OtherModel.objects.get(id=sell_item_id).
How to get sell_item_id in class Selled(models.Model):?
You schema couldn't be presented in SQL.
Option #1:
class Orderform(models.Model):
sell_item_id = models.CharField(max_length=20)
othermodel = models.OneToOneField("OtherModel")
and get it
Selled.objects.get(pk=1).orderform.othermodel
Option #2:
class Selled(models.Model):
orderform = models.ForeignKey("Orderform")
sell_count = models.IntegerField()
def something(self):
return OtherModel.objects.get(id=self.sell_item_id)
and get
Selled.objects.get(pk=1).something()
But I think you should better think about you DB schema.
It looks like you have a couple of questions, for the first, to get the related
Selled.objects.filter(order_form__sell_item_id =id_to_get).select_related('order_form')
Notice the __ (double underscore) before sell_item_id. This is important because it says, selected Selleed by the sell_item_id of the OrderForm. and select_related makes sure that order form is brought back in the results with a single call to the db.
Now, if you want to do that for OtherModel, you will need to create a similar ForeignKey field in the OtherNodel and this will allow you to make the same query as above. Currently, you have no such relation.
class OtherModel(models.Model):
somefield = models.CharField(max_length=20)
orderform = models.ForeignKey("Orderform")
OtherModel.objects.filter(order_form__sell_item_id =id_to_get).select_related('order_form')
Don't forget to run:
python manage.py makemigration
python manage.py migrate
This should solve the issue.
Related
I have custom user model from AbstractUser. And in the user model i have 1 field as foreignKey to other model. So i can't make migrations because i recieve error:
no such table: app_userrate
I tired to comment this foreignKey field but it is not soulution cause i want to auto deploy app.
class UserRate(models.Model):
name = models.CharField(max_length=30, blank=False)
max_active_events_cnt = models.PositiveIntegerField(default = 5)
max_people_contacts_cnt = models.PositiveIntegerField(default = 30)
def __str__(self):
return self.name
def default_rate():
obj, created = UserRate.objects.get_or_create(name="Basic")
return obj.id
class User(AbstractUser):
rate = models.ForeignKey(UserRate, on_delete=models.PROTECT, default=default_rate)
rate_until = models.DateField(null=True, blank=True)
I want to understand what should i change to make migrations correctly
This isn't really about the user model specifically, nor about foreign keys. It's about the default attribute, which you have set to call a function which itself does a database lookup. Obviously, at the time the migrations are run, the db item does not exist.
There is a solution, but it will take a few steps. You would need to remove the default attribute at first and create the migrations without it (you may need to set null=True). Then, add a second migration to define the "Basic" UserRate object. Finally, add the default back in and create a third migration.
I would like to prefetch a model property to a queryset in Django. Is there a way do that ?
Here are the three models:
class Place(models.Model):
name = models.CharField(max_length=200, blank=True)
#property
def bestpicurl(self):
try:
return self.placebestpic.picture.file.url
except:
return None
class PlaceBestPic(models.Model):
place = models.OneToOneField(Place)
picture = models.ForeignKey(Picture, on_delete=models.CASCADE)
class Picture(models.Model):
file = ImageField(max_length=500, upload_to="/images/")
I would need something like:
qs = Place.objects.all().select_related('bestpicurl')
Any clue how to do that ?
Thanks!
prefetch_related and select_related are instructions that are compiled into the database query/ies. Passing it the name of a pure Python property doesn't work because your database cannot know about them. You would have to select/prefetch the database fields/relations that the property uses under the hood:
qs = Place.objects.select_related('placebestpic')
Now, calling the property will not hit the db:
for p in qs:
# do stuff with p.bestpicurl
Even though you are following a reverse relation here, you do not use prefetch_related. From the select_related docs:
You can also refer to the reverse direction of a OneToOneField in the list of fields passed to select_related — that is, you can traverse a OneToOneField back to the object on which the field is defined. Instead of specifying the field name, use the related_name for the field on the related object.
So, after adding or removing a GenericRelation to one of my model classes nothing happens.
I try to makemigrations and it tells me no changes were detected. So there must be something wrong, because it should be hitting the database and try to apply some changes.
I followed Django example and I can't make the relationship work.
class Person(models.Model):
identity = models.CharField(max_length=13, verbose_name="ID")
name = models.CharField(max_length=255, verbose_name="Name")
board = GenericRelation('second_app.BoardMember') #Second Try
def __unicode__(self):
return self.identity
class Meta:
verbose_name = "Person"
verbose_name_plural = "People"
class Student(Person):
class Meta:
proxy = True
class Parent(Person):
class Meta:
proxy = True
class Teacher(Person):
board = GenericRelation('second_app.BoardMember') # first try
class Meta:
proxy = True
On a different app I have the following model.
class BoardMember(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id', for_concrete_model=False)
responsabilities = models.CharField(max_length=255)
At first I tried setting the Generic Relation on a proxy model. Nothing happened, then I tried setting it on the main Person class. Nothing. This is what I did to test the relation on the shell.
>>>from first_app.models import Teacher
>>>from second_app.models import BoardMember
>>>teacher = Teacher(identity='123456', name='Fermin Arellano')
>>>teacher.save()
>>>bm = Boardmember(content_object=teacher,responsabilities='Check stuff')
>>>bm.save()
>>>teacher.board.all()
[]
Following this example: https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/#reverse-generic-relations
The expected result should be: [<Teacher: 123456>]
Am I doing something wrong? There are no errors showing anywhere. Data is saved properly, both the Teacher and BoardMemer objects were created successfully in my database.
I just removed for_concrete_model=False from the GenericForeignKey declaration. Although on Django´s documentation it clearly states that it has to be setted to false in order to use ProxyModels.
Everythings is working fine now.
EDIT.
I just realized that the problem persists. After further investigation I noticed that in order to get the generic relation to work I need to save the content_type_id of the Person model, and not the proxy one. That is why deleting the for_concrete_model parameter helped, because this way I told Django to use the parents content type, and there it worked fine. Funny thing is that if I do the following the relations still works eventhough I have the content_type_id of Person.
Teacher.objects.filter(board__isnull=False)
This returns all the teachers who are in the board.
This is really confusing, if you can shed some light on this mess I'll be very thankful.
I've got a weird problem in django admin list_display. Whenever I add a foreign key to a list_display the whole change list view goes blank showing only the total no of entries.
models.py:
class Organization(models.Model):
org_id = models.AutoField(primary_key=True)
org_name = models.CharField(max_length=288)
def __unicode__(self):
return self.org_name
class Meta:
db_table = u'organization'
class Server(models.Model):
server_id = models.AutoField(primary_key=True)
server_name = models.CharField(max_length=135,verbose_name="Server Name")
org = models.ForeignKey(Organization,verbose_name="Organization")
def __unicode__(self):
return self.server_name
class Meta:
db_table = u'server'
admin.py:
class ServerAdmin(admin.ModelAdmin):
list_display = ('server_name','org')
admin.site.register(Server,ServerAdmin)
Now I'd expect this code to show me the organization name in the ChangeList View, But instead I get this:
If I remove the org in the list_display of ServerAdmin class, I get this:
I didn't modify the template or override any ModelAdmin methods. I'm using Mysql(5.1.58) as my database that comes with ubuntu 11.10 repository.
I'll be really glad if I could a get a sloution for this problem guys. Thanks in advance.
I second Stefano on the fact that null=True, blank=True is to be added. But, I think you only need to add it to the org_name field of the Organization model. That should make your way through. It has to be done because you have run inspectdb to create models from your legacy DB. And probably the organization table in the DB has an empty string stored. So, adding the above would allow the Admin to have a blank field/column displayed.
Moreover, you can also try using callbacks in situations where you don't want to make changes to your model definition like the above.
Try adding null=True, blank=True to all your model fields.
Usually django admin will silenty fail (thus show no records in the list) if the row does not validate the model constraints.
See: https://stackoverflow.com/a/163968/1104941
Does the following work for you?
admin.py:
class ServerAdmin(admin.ModelAdmin):
list_display = ('server_name','org__org_name')
admin.site.register(Server,ServerAdmin)
I had a similar problem and solved it like this (using your example):
class ServerAdmin(admin.ModelAdmin):
list_display = ('server_name', 'get_org')
def get_org(self, obj):
return obj.org.org_name
get_org.short_description = 'Org'
admin.site.register(Server,ServerAdmin)
I have a three classes:
class Location(models.Model):
name = models.CharField(max_length = 200)
class Student(models.Model):
name = models.CharField(max_length = 200)
email = models.EmailField()
class Exam(models.Model):
place = models.ForeignKey(Location)
taker = models.ForeignKey(Student)
score = models.DecimalField(max_digits = 5, decimal_places = 2)
When I run this it complains that Student doesn't have a a ForeignKey to Exam. Why?
It sounds like your actual database is out of sync with your model. You'll want to either drop and recreate your database using manage.py syncdb (easiest, but you will lose the data unless you use something like fixtures to reload initial data) or use a migration tool like South to upgrade your existing database to reflect the new data model.
You can try this on the manage.py shell:
from bar import models
l=models.Location("here")
s=models.Student(name="fred",email="foo#bar.com")
e = models.Exam(place=l,taker=s,score=99.9)
which I can do with no errors... Looks good to me..
In the admin.py file I had inlines = [StudentsInline] setting. This tries to enforce adding multiple Students to one exam (thinking it's on the One side of a OneToMany relationship).