django, table inheritance: insert data - python

I have these tables:
class OpeDatos(models.Model):
id_dato = models.IntegerField(primary_key=True)
id_usuario = models.ForeignKey(SisUsuarios, db_column='id_usuario')
id_region = models.ForeignKey(SisRegiones, db_column='id_region')
titulo = models.CharField(max_length=70, blank=True)
class Meta:
managed = False
db_table = 'ope_datos'
class OpeProductos(OpeDatos):
id_producto = models.IntegerField(primary_key=True)
iddato = models.OneToOneField(OpeDatos, primary_key=True, db_column="id_dato", parent_link=True)
id_producto_tipo = models.ForeignKey(DefProductosTipos, db_column='id_producto_tipo')
class Meta:
managed = False
db_table = 'ope_productos'
I want to insert data :
from apps.inicio.models import SisUsuarios, SisRegiones, OpeDatos
usuario = SisUsuarios.objects.get(pk=1)
region = SisRegiones.objects.get(pk=1)
datos = OpeDatos()
datos.id_usuario = usuario
datos.id_region = region
datos.save()
producto = OpeProductos()
producto.iddato = datos.id_dato
producto.save()
displays this message:
ValueError at /productos/add/
Cannot assign None: "OpeProductos.iddato" does not allow null values.
can you help me, please.

When creating an id manually you should use AutoField instead of IntegerField
id_dato = models.AutoField(primary_key=True)
https://docs.djangoproject.com/en/1.6/ref/models/fields/#autofield
What is happening is that since you are not explicitly defining the 'datos' object's id it doesnt have one, and then producto complains because the key can't have an empty value.
AutoField should fix this

I am surprised it doesn't fail at the earlier line: datos.save() because you have not supplied a value for the primary key datos.id_dato
Normally in Django you would need to use an AutoField to get an auto-incrementing primary key.
Also you should not be specifying primary_key=True on the OpeProductos.iddato field, you can only have one primary key per model.
Then the error you are seeing is due to the fact that datos.id_dato is None since you did not provide any value for it before saving the datos instance.

Related

Django: I am unable to get Django to autocreate an autofield

I am calling BORROWER.objects.create(ssn=Ssn, bname=Name, address=Address, phone=Phone) from views.py to create an entry in my sqlite database. This is my models.py file with the relevant function.
class BORROWER(models.Model):
card_id = models.AutoField(primary_key=True, max_length=7)
ssn = models.CharField(max_length=11)
bname = models.CharField(max_length=71)
address = models.CharField(max_length=79)
phone = models.CharField(max_length=15)
def __str__(self):
return str(self.card_id)
The database entry is successfully created. However, since I am not specifying a value for the card_id field, the value stays as (<django.db.models.fields.AutoField>,) instead of an actual key. When I try to specify a value for card_id it says something about unexpected argument. Am I calling the create function incorrectly?
Edit: The comma is not there in the original code, but I will try with the suggested edits
Remove comma at the end of the card_id and don't use max_length with AutoFiled ..
class BORROWER(models.Model):
card_id = models.AutoField(primary_key=True)
ssn = models.CharField(max_length=11)
bname = models.CharField(max_length=71)
address = models.CharField(max_length=79)
phone = models.CharField(max_length=15)
def __str__(self):
return str(self.card_id)

DJANGO: How can I duplicate attribute from other class?

I want to duplicate an attribute from other class.
class PedidoCliente(Pedido):
total_pagado = models.DecimalField(blank=True, max_digits=10, decimal_places=2,default = 0,verbose_name="Pagado $") # default 0 para el error for += int
barril_encargado = models.DecimalField(blank=True, default=0, max_digits=10, decimal_places=2,verbose_name="Barr. entregados")
fecha_entrega = models.DateField(verbose_name="Fecha Entrega")
class DetallePedidoCliente(DetallePedido):
comments = models.CharField(max_length=300, verbose_name="Comentarios")
precio_venta = models.DecimalField(max_digits=16, decimal_places=2, default = 0)
pedido = models.ForeignKey(PedidoCliente,on_delete=models.CASCADE)
fecha_entrega = the same from PedidoCliente
I'm new at OPP so sorry if it's a silly question.
Thanks!
One should not look to mirror fields of another model. This simply leads to extra work. One needs to update this mirrored field each time it is updated in the other table, etc.
Also it is not very useful when we have already cemented the relationship between the two tables using a Foreign Key.
To access a related fields data is very easy in Django. Suppose we have an instance of DetallePedidoCliente named instance using this we can access the fecha_entrega of the related model by the foreign key as follows:
instance.pedido.fecha_entrega
If one just wants an easy way to refer to this field one may consider adding a property to the model:
class DetallePedidoCliente(DetallePedido):
comments = models.CharField(max_length=300, verbose_name="Comentarios")
precio_venta = models.DecimalField(max_digits=16, decimal_places=2, default = 0)
pedido = models.ForeignKey(PedidoCliente,on_delete=models.CASCADE)
#property
def fecha_entrega(self):
return self.pedido.fecha_entrega
Now we can simply access the field as:
instance.fecha_entrega

Create new record with the self rererenced Foreignkey relation

Below is the my models.py and made a self reference Foreignkey relationship.
class emp_details(models.Model):
emp_id = models.AutoField(primary_key = True)
emp_first_name = models.CharField(max_length = 50,null = False)
emp_manager_id = models.ForeignKey('self')
a1 = emp_details(emp_first_name = "ramesh",emp_manager_id = 2)
a1.save()
Here I am trying to create new record. But I got the following error:
ValueError: Cannot assign "'2'": "emp_details.emp_manager_id" must be a "emp_details" instance.
How can I create a new record with the self rererenced Foreignkey relation?
In your case, emp_manager_id is the foreign key field, so you should assign the id to emp_manager_id_id.
a1 = emp_details(emp_first_name = "ramesh", emp_manager_id_id=2)
It would be better to change the field name to emp_manager. Note it's recommended to use CamelCase for your model name, so EmpDetail is better than emp_details. Putting that together, you have:
class EmpDetail(models.Model):
emp_id = models.AutoField(primary_key = True)
emp_first_name = models.CharField(max_length = 50,null = False)
emp_manager = models.ForeignKey('self')
Now that emp_manager is the foreign key, you can assign the id to emp_manager_id.
a1 = EmpDetail(emp_first_name="ramesh", emp_manager_id_id=2)
If you want to set emp_manager to the object itself, then you need to save the object to the database first, so that it gets a primary key.
a1 = EmpDetail(emp_first_name="ramesh")
a1.save()
a1.emp_manager = a1 # You could do 'a1.emp_manager_id = a1.id' instead
a1.save()
For this to work, you'll need to set null=True on the foreign key so that you can save the object without setting emp_manager.
emp_manager = models.ForeignKey('self', null=True)

Django: one-to-one field with factory_boy: UNIQUE constraint failed

I'm trying to make factories for these models with factory_boy:
class Course(models.Model):
group = models.OneToOneField(Group)
title = models.CharField(max_length=1024)
class CourseInfo(models.Model):
course = models.OneToOneField(Course, related_name='info')
starttime = models.TimeField(null=True, blank=True)
endtime = models.TimeField(null=True, blank=True)
Here are my factories:
class CourseInfoFactory(factory.DjangoModelFactory):
class Meta:
model = CourseInfo
course = factory.SubFactory('courseaffils.tests.factories.CourseFactory')
starttime = time(hour=4)
endtime = time(hour=6)
class CourseFactory(factory.DjangoModelFactory):
class Meta:
model = Course
title = factory.Sequence(lambda n: 'Example Course %d' % n)
group = factory.SubFactory(GroupFactory)
info = factory.RelatedFactory(CourseInfoFactory, 'course')
Now, when I call CourseFactory() or CourseInfoFactory() I get an IntegrityError:
IntegrityError: UNIQUE constraint failed: courseaffils_courseinfo.course_id
What's wrong with my factories? How can I fix this problem?
If I instead do course = factory.RelatedFactory('courseaffils.tests.factories.CourseFactory') on the CourseInfoFactory, I get this error, as expected:
IntegrityError: NOT NULL constraint failed: courseaffils_courseinfo.course_id
If you need more details, here's the actual code I'm working with:
https://github.com/ccnmtl/django_courseaffils/blob/master/courseaffils/models.py
Just add the django_get_or_create in the Meta class of your CourseInfoFactory:
class Meta:
django_get_or_create = ('group',)
This solution avoids the problem of a unique constraint in your field, and creates it if exists.
You could check here: https://github.com/FactoryBoy/factory_boy/blob/v2.5.2/factory/django.py#L133-L139
The problem was that CourseFactory() already creates a CourseInfo object. I've resolved this by just removing the info = factory.RelatedFactory(CourseInfoFactory, 'course') line, and now the CourseInfoFactory is unnecessary - I can test CourseInfo by getting the created object at course.info.

IntegrityError at. insert or update on table violates foreign key constraint

I have been doing my head in with this one. I am importing data in django using CSV, but that isn't my problem.
Get this error when inserting data:
IntegrityError at /import-user-profile/
insert or update on table "association_userprofile_club" violates foreign key constraint "association_userprofile_club_club_id_fkey"
DETAIL: Key (club_id)=(0) is not present in table "association_club".
Using postgreSQL, not sure if thats the reason.
Here is the relevant models:
class UserProfile(models.Model):
user = models.OneToOneField(User)
membership_number = models.CharField(max_length=30,help_text='Membership number.')
club = models.ManyToManyField(Club)
date_joined = models.DateField(blank=True)
street_address = models.CharField(max_length=100,help_text='Max 100 characters.',blank=True)
suburb = models.CharField(max_length=40,help_text='Max 40 characters.',blank=True)
postcode = models.CharField(max_length=10,help_text='Max 6 characters.',blank=True)
state = models.CharField(max_length=30,help_text='Max 4 characters.',blank=True)
home_phone = models.CharField(max_length=30,help_text='Max 30 characters.',blank=True)
mobile_phone = models.CharField(max_length=30,help_text='Max 30 characters.',blank=True)
ticketed_steward = models.CharField(max_length=1, choices=[('0', 'No'), ('1', 'Yes')],blank=True)
ticketed_time_keeper = models.CharField(max_length=1, choices=[('0', 'No'), ('1', 'Yes')],blank=True)
AFA_judge = models.CharField(max_length=1, choices=[('0', 'No'), ('1', 'Yes')],blank=True)
associate_members = models.ManyToManyField(User,blank=True, related_name='+')
def __str__(self):
return "%s's profile" % self.membership_number
and
class Club(models.Model):
club_name = models.CharField(max_length=50,help_text='Name of the club, MAX 50 characters.')
club_coordinater = models.CharField(max_length=50,blank=True)
contact_email = models.EmailField(blank=True)
contact_phone = models.CharField(max_length=30,blank=True)
contact_fax = models.CharField(max_length=30,blank=True)
address_location = models.CharField(max_length=50,blank=True)
address_suburb = models.CharField(max_length=50,blank=True)
address_postcode = models.CharField(max_length=50,blank=True)
address_state = models.CharField(max_length=4,help_text='State the club is in, MAX 4 characters.',blank=True)
incorporated = models.CharField(max_length=3, choices=[('0', 'No'), ('1', 'Yes')],blank=True)
old_id = models.CharField(max_length=20,blank=True)
website = models.URLField(blank=True)
joined = models.DateField(blank=True)
def __unicode__(self):
return self.club_name
This should be working as club is being properly returned in.
def import_user_profile(request):
if request.user.is_authenticated():
file = database_loc + "tblHandlers.csv"
data = ""
with open(file, 'rb') as f:
reader = csv.reader(f)
for row in reader:
if row[0] != "pkMemberNumber":
#0:pkMemberNumber 1:Club 2:fldContactOpen 3:fldLastName 4:fldFirstName 5:fldStreet 6:fldSuburb 7:fldState 8:fldPostcode 9:fldHome 10:fldMobile 11:fldEmail 12:fldJunior 13:fldNewsletter 14:fldNotes 15:dtejoined 16:dteExpiry 17:dateRenewed 18:fldFinMem1 19:fldFinMem2 20:fldDOB 21:fldHanderAge 22:fldStewTicket 23:fldTimeTicket 24:fldSnrTimeTicket
user = User.objects.get(username=row[0]+row[4]+row[3])
try:
club = Club.objects.get(club_name=str(row[1]))
club.save()
except:
club = Club.objects.get(club_name="No Club")
club.save()
try:
profile = UserProfile.objects.get(user=user)
except:
profile = UserProfile(user=user)
#profile.user=user
profile.membership_number=row[0]
thing = str(club.id)
profile.club=thing
profile.date_joined=date_re(row[15])
profile.street_address=row[5]
profile.suburb=row[6]
profile.postcode=row[8]
profile.state=row[7]
profile.home_phone=row[9][0:30]
profile.mobile_phone=row[10]
profile.ticketed_steward=row[22]
profile.ticketed_time_keeper=row[23]
profile.AFA_judge="0"
profile.save()
user_receipts = UserReceipts(user_id=profile.id,recept="",date_paid=date_re(row[17]),membership_valid_to=date_re(row[16]))
html = "<html><body>" + data + "</body></html>"
return HttpResponse(html)
Django says the issue occurs at this:
profile.club=thing
Some help with this would save my sanity! Thanks
try:
club = Club.objects.get(club_name=str(row[1]))
club.save() # <-- You don't need to save. You haven't changed anything on the club.
except:
club = Club.objects.get(club_name="No Club")
club.save() # <-- You don't need to save. You haven't changed anything on the club.
And model ids declared by django are numeric, so don't use thing = str(club.id).
Also, using the attribute pk is preferable over id because pk will always point to the real primary key name. This means if you ever change the primary key of your models, you won't need to change all the id accesses in your code.
You need to change profile.club=thing to profile.club.add(club.pk) because your club attribute is declared as a models.ManyToManyField(Club) which is a sequence of Club objects, not a single one.
Or... you may change it and use a models.ForeignKey(Club) which is more coherent with the attribute name (club) (do this only in case that your users can only be members of one club at the same time)
When this error happens, what is tends to be related to is that you made a mistake when creating one or more foreign key fields for your model.
First of all make sure your model foreign key fields are pointing to the right table.
For instance, if you have the following model:
class ModelA(models.Model):
...
model_b = models.ForeignKey(ModelB, ...)
model_c = models.ForeignKey(ModelB, ...) # <-- wrong model in foreign key
...
You might be accidentally using ModelB on both foreign keys, where you should instead be using ModelC:
class ModelA(models.Model):
...
model_b = models.ForeignKey(ModelB, ...)
model_c = models.ForeignKey(ModelC, ...) # <-- correct model in foreign key
...
Otherwise, when you try to create a new model instance of model A:
>>> ModelA.objects.create(model_b_id=<int>, model_c_id=<int>)
Since model_c_id is setting a value for an id for ModelB, this may throw an error because you are looking for a foreign key that exists in ModelC table, and that does not necessarely exists for the ModelB table.

Categories