Django ForeignKeys not saving - python

Currently have a problem where I will assign a both Client foreignkey to a Signin and its not saving either reference. Heres the Signin Model
#Sign-ins require just a user
class Signin(models.Model):
employee = models.ForeignKey(Employee)
sign_in_time = models.DateTimeField(null=True)
sign_out_time = models.DateTimeField(null=True)
sign_in_number = models.CharField(max_length=15, default="00000000000")
sign_out_number = models.CharField(max_length=15, default="00000000000")
client_in_obj = models.ForeignKey(Clients, related_name="client_in", null=True)
client_out_obj = models.ForeignKey(Clients, related_name="client_out", null=True)
client_in = models.CharField(max_length=100, default="Unkown")
client_out = models.CharField(max_length=100, null=True)
# Start of Sign in Function
def save(self, *args, **kwargs):
self.client_out_obj.save()
self.client_in_obj.save()
super(Signin, self).save(*args, **kwargs)
def __str__(self):
return self.employee.first_name + " " + self.employee.last_name + " : " + str(self.sign_in_time)+ " to " + str(self.sign_out_time)
Now the employee field IS saving, but the two client_in_obj,and client_out_obj are NOT saving. I will assign them and then when refreshing the page they are not set.
Here is the client Model
class Clients(models.Model):
name = models.CharField(max_length=40, blank=True, null=True)
alt_name = models.CharField(max_length=25, blank=True, null=True)
address1 = models.CharField(max_length=35, blank=True, primary_key=True)
address2 = models.CharField(max_length=35, blank=True, null=True)
rate = models.FloatField(blank=True, null=True)
contact_email = models.CharField(max_length=40, blank=True, null=True)
contact_name = models.CharField(max_length=30, blank=True, null=True)
phone = models.CharField(max_length=40, blank=True, null=True)
billing_name = models.CharField(max_length=30, blank=True, null=True)
billing_email_field = models.CharField(db_column='billing_email_', max_length=12, blank=True, null=True) # Field renamed because it ended with '_'.
def __str__(self):
return self.name + ", " + self.address1
class Meta:
managed = False
db_table = 'clients'
They client_in and client_out fields were my hackey way of trying to get by it for now.
My relations I would like to keep are as followed - An employee will have Many Sign ins, and each Sign in only needs an employee at first, each other field will be filled in over the course of a day.

I found the answer!
So the problem was followed. Im dealing with a legacy database in mySQL, the problem was that when django was assigning the client id it was thinking the primary key was an integer field, so when it tried assigning the key (which was a varchar) it ran into an integer field, so it didn't like it and didn't save. Hopefully that helps anyone who runs into this problem later!

Related

how to store user data from user model inside a database table in django

I have a Buyer table in mysql database and I want to take the username , email, password from User model ( default django model ) and store it inside Buyer table,
Buyer model in models.py:
class Buyer(models.Model):
row_id = models.AutoField(primary_key=True)
user_name = models.CharField(unique=True, max_length=50)
user_password = models.CharField(max_length=16)
first_name = models.CharField(max_length=50)
middle_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50)
email = models.CharField(unique=True, max_length=100)
home_phone = models.CharField(max_length=20, blank=True, null=True)
mobile_phone = models.CharField(unique=True, max_length=20)
personal_id = models.CharField(max_length=30, blank=True, null=True)
idtype_fk = models.ForeignKey('Idtype', models.DO_NOTHING, db_column='idType_FK', blank=True, null=True) # Field name made lowercase.
personal_id_country_fk = models.ForeignKey('Country', models.DO_NOTHING, db_column='personal_id_country_FK',related_name='personal_id_country_fk') # Field name made lowercase.
address_line_1 = models.CharField(db_column='address_Line_1', max_length=200) # Field name made lowercase.
address_line_2 = models.CharField(db_column='address_Line_2', max_length=200, blank=True, null=True) # Field name made lowercase.
p_o_box = models.CharField(max_length=20, blank=True, null=True)
city = models.CharField(max_length=50)
country_fk = models.ForeignKey('Country', models.DO_NOTHING, db_column='country_FK' , related_name='country_fk') # Field name made lowercase.
gender_fk = models.ForeignKey('Gender', models.DO_NOTHING, db_column='gender_FK') # Field name made lowercase.
bdate = models.DateField()
def __str__(self):
return 'User: ' + self.user_name
class Meta:
managed = False
db_table = 'buyer'
and after the registration User/Buyer can add more information such as first name , mobile phone etc.. in the profile page
As Willem van Onsem mentioned, use a ForeignKey in your Buyer model to reference to the user object:
class Buyer(models.Model):
#other stuff
user_fk = models.ForeignKey(User, on_delete=models.SET_NULL)
#other stuff
Or, if every Buyer is just one User and every User is just one Buyer, use a OneToOneField instead of a ForeignKey.
If you would then want to access the username/email/password you can use a query like this:
buyer = Buyer.objects.all().first()
buyer_email = buyer.user_fk.email

Django: What is the smartest way connect models for two types of clients (individual and company) to the address model?

I am working on developing a CRM like application using Django and I've stumbled upon a problem. The company which will use the app has private individuals as clients but also other companies. As they have different fields I created two separate models:
class PersonAccount(models.Model):
first_name = models.CharField(max_length=100, null=False)
last_name = models.CharField(max_length=100, null=False)
personal_id_number = models.CharField(max_length=50, unique=True, null=False)
document_series = models.CharField(max_length=50)
document_number = models.CharField(max_length=50, null=False)
document_emission_date = models.DateField(null=True)
document_expiration_date = models.DateField(null=True)
birth_date = models.DateField(null=True)
sex = models.ForeignKey(Sex, on_delete=models.CASCADE, null=False)
workplace = models.CharField(max_length=100)
nationality = models.ForeignKey(Geography, on_delete=models.CASCADE)
occupation = models.CharField(max_length=100)
observations = models.CharField(max_length=500)
created = models.DateTimeField(auto_now_add=True, null=True)
updated = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return "Person account: " + self.last_name + " " + self.first_name
class CompanyAccount(models.Model):
company_name = models.CharField(max_length=100, null=False)
chamber_of_commerce_reg_number = models.CharField(max_length=50, unique=True, null=False)
company_unique_id_number = models.CharField(max_length=50, unique=True, null=False)
company_type = models.ForeignKey(CompanyType, on_delete=models.CASCADE)
company_nationality = models.ForeignKey(Geography, on_delete=models.CASCADE)
company_activity = models.CharField(max_length=100)
company_representative = models.ForeignKey(PersonAccount, on_delete=models.CASCADE)
observations = models.CharField(max_length=500)
created = models.DateTimeField(auto_now_add=True, null=True)
updated = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return "Commpany account: " + self.last_name + " " + self.first_name
I want to connect them both to an address model:
class AccountAddress(models.Model):
address_type = models.ForeignKey(AddressType, on_delete=models.CASCADE, null=False)
street = models.CharField(max_length=100)
street_number = models.CharField(max_length=100)
buliding = models.CharField(max_length=100)
entrance = models.CharField(max_length=100)
floor = models.CharField(max_length=100)
appartment_number = models.CharField(max_length=100)
postal_code = models.CharField(max_length=100)
city = models.CharField(max_length=100, null=False)
country = models.ForeignKey(Geography, on_delete=models.CASCADE, related_name='account_country')
province = models.ForeignKey(Geography, on_delete=models.CASCADE, related_name='account_province')
created = models.DateTimeField(auto_now_add=True, null=True)
updated = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return "Account address: " + str(self.account) + " - " + str(self.address_type)
The thing is I am fairly new to Django and the only solution I currently see is to connect the actual Address model to PersonAccount and then create another one to connect to CompanyAccount. I am sure there must be another way but, although I've been searching and reading for a while, I can't seem to find nothing that fits my needs.
Could you please give me a hand? Thank you!
You can either define a parent Account class for CompanyAccount and PersonAccount (allowing you to save some code by moving common fields to the parent class) and define a ForeignKey on AccountAddress:
class AccountAddress(models.Model):
account = models.ForeignKey(Account, on_delete=models.CASCADE)
Or you can define a many-to-many relationship on the individual account models instead of a foreign key in Address:
class CompanyAccount(models.Model):
addresses = models.ManyToManyField(AccountAddress)
The second solution allows sharing of addresses between accounts; in the first one only one account is associated with one address. You can have several addresses per account with both.

django - Runpython function to turn charfield into foreignkey

I've been strugglin to relate a csv imported data model with a spatial data model based on a CharField.
I've created both models and now im trying to transfer the data from one field to a new one to be the ForeignKey field. I made a Runpython funtion to apply on the migration but it goives the an error:
ValueError: Cannot assign "'921-5'":
"D2015ccccccc.rol_fk" must be a "D_Base_Roles" instance.
Here are the models:
class D_Base_Roles(models.Model):
predio = models.CharField(max_length=254)
dest = models.CharField(max_length=254)
dir = models.CharField(max_length=254)
rol = models.CharField(primary_key=True, max_length=254)
vlr_tot = models.FloatField()
ub_x2 = models.FloatField()
ub_y2 = models.FloatField()
instrum = models.CharField(max_length=254)
codzona = models.CharField(max_length=254)
nomzona = models.CharField(max_length=254)
geom = models.MultiPointField(srid=32719)
def __str__(self):
return str(self.rol)
class Meta():
verbose_name_plural = "Roles"
class D2015ccccccc(models.Model):
id = models.CharField(primary_key=True, max_length=80)
nombre_archivo = models.CharField(max_length=180, blank=True, null=True)
derechos = models.CharField(max_length=120, blank=True, null=True)
dir_calle = models.CharField(max_length=120, blank=True, null=True)
dir_numero = models.CharField(max_length=120, blank=True, null=True)
fecha_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_solicitud = models.CharField(max_length=50, blank=True, null=True)
rol_sii = models.CharField(max_length=50, blank=True, null=True)
zona_prc = models.CharField(max_length=120, blank=True, null=True)
##NEW EMPTY FOREIGNKEY FIELD
rol_fk = models.ForeignKey(D_Base_Roles, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return str(self.numero_certificado)
class Meta:
managed = True
#db_table = 'domperm2015cip'
verbose_name_plural = "2015 Certificados Informaciones Previas"
ordering = ['numero_certificado']
The Runpython function:
def pop_rol(apps, schema_editor):
roles = apps.get_model('b_dom_edificacion', 'D2015ccccccc')
for r in roles.objects.all():
rol = roles
r.rol_fk = r.rol_sii
r.save()
D_Base_Roles.rol values are all unique, and 921-5 is one of those values.
What am I missing?
You probably need to assign an object, not a string. Change the line
r.rol_fk = r.rol_sii
to
r.rol_fk = D_Base_Roles.objects.get(rol=r.rol_sii)
Maybe adjust to whatever the correct field for looking up D_Base_Roles instances is.
Note: this will make a database query for every iteration of the for-loop

Django model query

I have question about Django query models. I know how to write simple query, but Im not familiar with LEFT JOIN on two tables. So can you give me some advice on his query for better understanding DJango ORM.
query
select
count(ips.category_id_id) as how_many,
ic.name
from
izibizi_category ic
left join
izibizi_product_service ips
on
ips.category_id_id = ic.id
where ic.type_id_id = 1
group by ic.name, ips.category_id_id
From this query I get results:
How many | name
0;"fghjjh"
0;"Papir"
0;"asdasdas"
0;"hhhh"
0;"Boljka"
0;"ako"
0;"asd"
0;"Čokoladne pahuljice"
0;"Mobitel"
2;"Čokolada"
And I have also try with his Django query:
a = Category.objects.all().annotate(Count('id__category',distinct=True)).filter(type_id=1)
But no results.
My models:
models.py
class Category(models.Model):
id = models.AutoField(primary_key=True)
type_id = models.ForeignKey('CategoryType')
name = models.CharField(max_length=255)
def __str__(self):
return str(self.name)
class Product_service(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, blank=True, null=True)
selling_price = models.DecimalField(decimal_places=5, max_digits=255, blank=True, null=True)
purchase_price = models.DecimalField(decimal_places=5, max_digits=255, blank=True, null=True)
description = models.CharField(max_length=255, blank=True, null=True)
image = models.FileField(upload_to="/", blank=True, null=True)
product_code = models.CharField(max_length=255, blank=True, null=True)
product_code_supplier = models.CharField(max_length=255, blank=True, null=True)
product_code_buyer = models.CharField(max_length=255, blank=True, null=True)
min_unit_state = models.CharField(max_length=255, blank=True, null=True)
state = models.CharField(max_length=255, blank=True, null=True)
vat_id = models.ForeignKey('VatRate')
unit_id = models.ForeignKey('Units')
category_id = models.ForeignKey('Category')
If you culd help me on this problem.
You should add a related name on the category_id field like:
category_id = models.ForeignKey('Category', related_name="product_services")
so that in your query you can do:
a = Category.objects.all().annotate(Count('product_services',distinct=True)).filter(type_id=1)
and then you can access the individual counts as:
a[0].product_services__count

select object to edit

I have a simple view function that's designed to allow the user to choose from items listed in an html table (records). Clicking on a record should divert the user to the template from which he can edit that specific record. The code is as follows:
def edit_record(request):
if request.method == 'POST':
a=ProjectRecord.objects.get()
form = RecordForm(request.POST, instance=a)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
a=ProjectRecord.objects.get()
form = RecordForm(instance=a)
return render_to_response('productionModulewire.html', {'form': form})
The problem is that the function works perfectly well ONLY so long as there is only 1 record in the database. As soon as I add another, I get a multiple returned item error.
I suspect it has something to do with "objects.get()" but I don't know how to correctly structure the view?
The url is simple (perhaps too much so):
(r'^edit/', edit_record),
and the model looks like this:
class ProjectRecord(models.Model):
client = models.CharField(max_length=50, choices=CLIENT_CHOICES)
account = models.CharField(max_length=50, choices=ACCOUNT_CHOICES)
project_type = models.CharField(max_length=50, choices=TYPE_CHOICES)
market = models.CharField(max_length=50, choices=MARKET_CHOICES)
agencyID = models.CharField(max_length=30, unique=True, blank=True, null=True)
clientID = models.CharField(max_length=30, unique=True, blank=True, null=True)
prjmanager = models.CharField(max_length=64, unique=False, blank=True, null=True)
acclead = models.CharField(max_length=64, unique=False, blank=True, null=True)
artdirector = models.CharField(max_length=64, unique=False, blank=True, null=True)
prdlead = models.CharField(max_length=64, unique=False, blank=True, null=True)
intlead = models.CharField(max_length=64, unique=False, blank=True, null=True)
prjname = models.CharField(max_length=200, unique=True)
prjstatus = models.CharField(max_length=50, choices=STATUS_CHOICES)
as_of = models.DateField(auto_now_add=False)
format = models.CharField(max_length=64, unique=False, blank=True, null=True)
target_studio = models.DateField(unique=False, blank=True, null=True)
mech_return = models.DateField(unique=False, blank=True, null=True)
comp_return = models.DateField(unique=False, blank=True, null=True)
target_release = models.DateField(unique=False, blank=True, null=True)
record_added = models.DateField(auto_now_add=True)
record_modified = models.DateTimeField()
studio_name = models.CharField(max_length=64, unique=False, blank=True, null=True)
studio_process = models.CharField(max_length=64, unique=False, blank=True, null=True, choices=PROCESS_CHOICES)
to_studio = models.DateTimeField(unique=False, blank=True, null=True)
from_studio = models.DateTimeField(unique=False, blank=True, null=True)
studio_name2 = models.CharField(max_length=64, unique=False, blank=True, null=True)
studio_process2 = models.CharField(max_length=64, unique=False, blank=True, null=True, choices=PROCESS_CHOICES)
to_studio2 = models.DateTimeField(unique=False, blank=True, null=True)
from_studio2 = models.DateTimeField(unique=False, blank=True, null=True)
comments = models.TextField(max_length=500, unique=False, blank=True, null=True)
summary = models.TextField(max_length=500, unique=False, blank=True, null=True)
upload_pdf = models.CharField(max_length=50, unique=False, blank=True, null=True)
upload_achive = models.CharField(max_length=50, unique=False, blank=True, null=True)
def __unicode__(self):
return u'%s' % self.prjname
class Admin:
pass
from which the model form "RecordForm" was derived.
The important thing about get is "get what?"
When you say
a=ProjectRecord.objects.get()
you neglected to provide any selection criteria. Which row do you want from the database?
Which row? Hmmmm... How does the GET transaction know which row is going to be edited?
Usually, we put that in the URL.
So, you'll need to update your urls.py to include the record ID on the URL path. You'll need to update your view function definition to accept this record ID. Finally, you'll need to update GET and POST to use this record identification which came from the URL.
Update urls.py to include the object id. See http://docs.djangoproject.com/en/1.1/topics/http/urls/#named-groups
urlpatterns = patterns('',
(r'^class/(?P<object_id>\d+?)/$', 'app.views.edit_record'),
Update your view function
def edit_record( request, object_id = None ):
if request.method == "POST":
if object_id is None:
return Http_404
ProjectRecord.objects.get( pk = int(object_id) )
etc.
Without more information it is hard to tell what you need to change, but your guess is correct, the problem is with your ProjectRecord.objects.get() call.
You should be passing some sort of information to get in order to limit the list down to one.
In most cases, you will need:
ProjectRecord.objects.get(pk=id)
Where id is the primary key value of the ProjectRecord you are trying to edit.
Could you show the relevant code from your urls.py as well as more information on your ProjectRecord model?

Categories