could django update foreignkey use SQL? - django

I filled datas into postgreSQL without type foreignkey at first.
here is my models.py
class BeverageMenu(models.Model):
brand = models.CharField(max_length=255, null=True)
area = models.CharField(max_length=50, blank=True, null=True)
class DMenu(models.Model):
dmenu = models.ForeignKey(BeverageMenu,null=True,blank=True)
category = models.CharField(max_length=255, null=True)
product = models.CharField(max_length=255, null=True)
and I use this way to update the foreignkey:
>>> from psql.models import BeverageMenu,DMenu
>>> menu1 = BeverageMenu.objects.get(id=1)
>>>product = DMenu.objects.filter(area='North')
>>>product.update(dmenu=menu1)
And I want to know could I use SQL directly to do this ?
I try this but fail
INSERT INTO psql_dmenu(category,product,dmenu) VALUES ('hot','soup',1),
ERROR: column "dmenu" of relation "psql_dmenu" does not exist

You could, but why would you want to? Django has a model layer for a reason, which is to make the database easier to deal with and less dependent on SQL.
However, for your problem, the issue is that the underlying database column for a ForeignKey includes the prefix _id: so your field is dmenu_id.

Related

Django App Issue with ColumnName changed to lower case in the postgres DB

I have a working Django app with Postgres DB in the backend. However the coulmn names are updated and switched to lowercase name in backend database, for eg:
Earlier columnName was AccountName, now changed to accountname all lowercase. This cases the app to break since the model refers to the oldName.
I tried changing to the Model to the lowercase name but it breaks at different places like DataFrame name and have to make lot of changes to make it work.
class AccountStatus(models.Model):
AccountNumber = models.CharField(max_length=255, null=True)
AccountName = models.CharField(max_length=255, null=True)
is there any simple solution to this issue, maybe using some alias or any parameter to pass etc?
Thanks for the help.
Tried this :
class AccountStatus(models.Model):
accountnumber = models.CharField(max_length=255, null=True)
accountname = models.CharField(max_length=255, null=True)
This results in cascade of changes in Filters, DataFrame key names etc and many other places.
I am trying to figure out an easy solution for this?
You can specify a db_column=… parameter [Django-doc] to specify the name of the column at the database side:
class AccountStatus(models.Model):
AccountNumber = models.CharField(
max_length=255, db_column='accountnumber', null=True
)
AccountName = models.CharField(
max_length=255, db_column='accountname', null=True
)

Create object in model having foreigkey relation

I want to create an entry in this Something model in python manage.py shell using this
Someting.objects.create(discussion_title="General", user_username="admin", content="Hello")
models example
class Discussion(models.Model):
title = models.CharField(max_length=255, unique=True, blank=False,)
users = models.ManyToManyField(User, blank=True, )
class Something(models.Model):
user = models.ForeignKey(User,
on_delete=models.CASCADE)
discussion = models.ForeignKey(Discussion, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
content = models.TextField(unique=False, blank=False)
I am getting this error
TypeError: Something() got an unexpected keyword argument 'discussion_title'
First, you have to use double under bar __ to use django's model relation expression.
Someting.objects.get(discussion__title="General", user__username="admin", content="Hello")
Second, you can't use double under bar relation expression when create an object.
if you want to create an object in relation, you have to create in step by step. follow #Nicolas Appriou 's answer
Your Something model does not have a discussion_title field. You need to create a Discussion instance for this.
This model does not have a user_username model either.
discussion = Discussion.objects.create(title="Foobar")
discussion.users.add(User.objects.create(username="Ham")
Something.objects.create(
discussion=discussion,
)

Is there a way to refer to only some fields in a Django ForeignKey?

I believe this is best explained by an example. So, I am making a program for saving weightlifting results for international and national competitions. Below is a (weight)lifter model:
class Lifter(Person):
# Changed from dateTime, as we don't need time of birth
birth_date = models.DateField(null=True)
gender = models.CharField(max_length=10, choices=Gender.choices(),
null=True)
club = models.ForeignKey('Club', null=True)
I would like to connect the lifter model to the InterntionalResult model:
class InternationalResult(models.Model):
lifter = models.ForeignKey(Lifter, null=True)
body_weight = models.FloatField(verbose_name='Kroppsvekt', null=True)
# International group can be (for example) "A" or "B"
group = models.CharField(max_length=5, verbose_name='kategori')
snatch = models.IntegerField()
clean_and_jerk = models.IntegerField()
total = models.IntegerField()
However, lifter has a ForeginKey to group (club = models.ForeignKey('Club', null=True)). When I connect Lifter to InternationalResult, I would like to exclude this ForgeinKey, but still connect Result to the rest of Lifter. This is because international competitions don't have clubs in the same way.
Is there a way to do this, or should I just create a new InternationalLifter-model?
Thank you for your time!
What are you trying to do with it? Is this going to be displayed in a template? The easiest way to "exclude" a field is to just not render it, or not use it in general. Don't worry about performance, foreign-key relations are only fetched when you evaluate them.

django problem with foreign key to user model

I have a simple userprofile class in django such that
class Profile(models.Model):
user = models.OneToOneField(User,unique=True)
gender = models.IntegerField(blank=True, default=0, choices=UserGender.USER_GENDER,db_column='usr_gender')
education = models.IntegerField(blank=True, default=0, choices=UserEducation.USER_EDU,db_column='usr_education')
mail_preference = models.IntegerField(blank=True, default=1, choices=UserMailPreference.USER_MAIL_PREF,db_column='usr_mail_preference')
birthyear = models.IntegerField(blank=True, default=0,db_column='usr_birthyear')
createdate = models.DateTimeField(default=datetime.datetime.now)
updatedate = models.DateTimeField(default=datetime.datetime.now)
deletedate = models.DateTimeField(blank=True,null=True)
updatedBy = models.ForeignKey(User,unique=False,null=True, related_name='%(class)s_user_update')
deleteBy = models.ForeignKey(User,unique=False,null=True, related_name='%(class)s_user_delete')
activation_key = models.CharField(max_length=40)
key_expires = models.DateTimeField()
You can see that deletedBy and updatedBy are foreign key fields to user class. If I don't write related_name='%(class)s_user_update' it gives me error (I don't know why).
Although this works without any error, it doesn't push the user id's of deletedBy and updatedBy fields although I assign proper user to them.
Could give me any idea and explain the related_name='%(class)s_user_update' part ?
Thanks
'%(class)s_user_update' implies that it is a string awaiting formatting. You would normally see it in the context:
'%(foo)s other' % {'foo': 'BARGH'}
Which would become:
'BARGH other'
You can read more about python string formatting in the python docs. String Formatting Operations
I can't see how the code you have would ever work: perhaps you want:
class Profile(models.Model):
# other attributes here
updated_by = models.ForeignKey('auth.User', null=True, related_name='profile_user_update')
deleted_by = models.ForeignKey('auth.User', null=True, related_name='profile_user_deleted')
# other attributes here
If it does work, it is because django is doing some fancy magic behind the scenes, and replacing '%(class)s' by the class name of the current class.
Notes on the above:
The consistent use of *snake_case* for attributes. If you must use camelCase, then be consistent for all variables. Especially don't mix *snake_case*, camelCase and runwordstogethersoyoucanttellwhereonestartsandtheotherends.
Where you have two attributes that reference the same Foreign Key, you must tell the ORM which one is which for the reverse relation. It will default to 'profile_set' in this case for both, which will give you the validation error.
Use 'auth.User' instead of importing User into the models.py file. It is one less import you'll need to worry about, especially if you don't use the User class anywhere in your models.py file.
You can read more about the related_name stuff here:
https://docs.djangoproject.com/en/1.3/topics/db/queries/#following-relationships-backward

Querying across database tables

I've got Django tables like the following (I've removed non-essential fields):
class Person(models.Model):
nameidx = models.IntegerField(primary_key=True)
name = models.CharField(max_length=300, verbose_name="Name")
class Owner(models.Model):
id = models.IntegerField(primary_key=True)
nameidx = models.IntegerField(null=True, blank=True) # is Person.nameidx
structidx = models.IntegerField() # is PlaceRef.structidx
class PlaceRef(models.Model):
id = models.IntegerField(primary_key=True)
structidx = models.IntegerField() # used for many things and not equivalent to placeidx
placeidx = models.IntegerField(null=True, blank=True) # is Place.placeidx
class Place(models.Model):
placeidx = models.IntegerField(primary_key=True)
county = models.CharField(max_length=36, null=True, blank=True)
name = models.CharField(max_length=300)
My question is as follows. If in my views.py file, I have a Person referenced by name and I want to find out all the Places they own as a QuerySet, what should I do?
I can get this far:
person = Person.objects.get(name=name)
owned_relations = Owner.objects.filter(nameidx=nameidx)
How do I get from here to Place? Should I use database methods?
I'm also not sure if I should be using ForeignKey for e.g. Owner.nameidx.
Thanks and apologies for this extremely basic question. I'm not sure how to learn the basics of database queries except by trying, failing, asking SO, trying again... :)
The whole point of foreign keys is for uses like yours. If you already know that Owner.nameidx refers to a Person, why not make it a foreign key (or a OneToOne field) to the Person table? Not only do you get the advantage of referential integrity - it makes it impossible to enter a value for nameidx that isn't a valid Person - the Django ORM will give you the ability to 'follow' the relationships easily:
owned_places = Place.objects.filter(placeref__owner__person=my_person)
will give you all the places owned by my_person.
Incidentally, you don't need to define the separate primary key fields - Django will do it for you, and make them autoincrement fields, which is almost always what you want.
If u could redesign.Then
In owner nameidx can be a foreign key to Person(nameidx)
Placeref(structidx) could be a foreign key to Owner(structidx) and
Place(placeidx) could be a foreign key Place ref(placeidx)
Then u could deduce the place value easily..