How to create a model with 2 different fields with the same db_column?
In my example queue_id and content_type_id are always the same id value. So I don't want to store that information twice in a DB table.
I set a db_column for both fields but got the error
(models.E007) Field 'content_type' has column name 'queue_id' that is used by another field.
I added error supression. As result I have an invalid sql code for migration:
CREATE TABLE `queue_items_generic` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`object_id` integer UNSIGNED NOT NULL,
`queue_id` integer NOT NULL,
`queue_id` integer NOT NULL);
Manual migration patch has helped.
But is there an easier way to do the same stuff? I don't want to patch migrations and supress any errors.
Here is the reproducing problem code:
from django.db.models import (
Model,
ForeignKey,
OneToOneField,
CASCADE,
PositiveIntegerField,
)
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class QueueGeneric(Model):
content_type = OneToOneField(
ContentType,
on_delete = CASCADE,
primary_key = True,
)
last_object_id = PositiveIntegerField(
default = 0,
)
last_object = GenericForeignKey('content_type', 'last_object_id')
class QueueItemsGeneric(Model):
queue = ForeignKey(
QueueGeneric,
db_column = 'queue_id',
on_delete = CASCADE
)
content_type = ForeignKey(
ContentType,
db_column = 'queue_id',
on_delete = CASCADE
)
object_id = PositiveIntegerField()
object = GenericForeignKey('content_type', 'object_id')
Update #1
A bit digging into Fields topic helps to solve the migration problem.
If we provide the db_type is None then it won't produce a new column in DB table.
class ShadowForeignKey(ForeignKey):
def db_type(self, connection):
return None
class QueueItemsGeneric(Model):
queue = ForeignKey(
QueueGeneric,
db_column = 'queue_id',
on_delete = CASCADE
)
content_type = ShadowForeignKey(
ContentType,
db_column = 'queue_id',
on_delete = CASCADE
)
object_id = PositiveIntegerField()
object = GenericForeignKey('content_type', 'object_id')
It looks OK. Some tests will show how it's a stable solution.
Now I have only a problem with error supression. It seems that the field names check into migrations module. For now I have no idea how to override it nicely.
Related
I am using django and Sql server as a database.
I have a table with a multiple primary key using the unique_together
class Attribute_tmp(models.Model):
useridtmp = models.ForeignKey(User_tmp, on_delete=models.CASCADE, blank =True, null = True)
userid = models.ForeignKey(User, on_delete=models.CASCADE, blank =True, null = True)
fk_str = models.ForeignKey(Stream, on_delete=models.CASCADE)
class Meta:
unique_together = (('userid', 'fk_str'),('useridtmp', 'fk_str'))
So when i add objects of this table when the useridtmp is null, it doesn't work because i will have a duplicated key.
My Question is how can i avoid the null values.
Thank you
Did you tried this?
class Meta:
constraints = [
models.UniqueConstraint(fields=['userid', 'fk_str'], name='name of constraint'),
models.UniqueConstraint(fields=['useridtmp', 'fk_str'], name='another name of constraint')
]
Since you have null=True and blank=True in your ForeignKey field, it is reasonable for db to store null values.
If in any case, the two ForeignKeys shouldn't be null, you can mark null and blank as false. Simply removing them from field settings will do the trick as they are set to false by default. You probably need to recreate the database to make the new settings working.
Then, the unique_together will not have an issue with null values.
I'm trying to replace a field in an intermediate table with a generic field. Using Django 1.6, MariaDB/MySQL.
I have a class (PermissionGroup) that links a resource to a group. Works fine. However I have several other tables that are similar - linking some id to a group id.
I thought I could replace these tables with one table that uses a generic foreign key, along with the group id. However this does not validate.
Here's the original, which works:
# core/models.py
class PermissionGroup(models.Model):
resource = models.ForeignKey('core.Resource')
group = models.ForeignKey('auth.Group')
class Resource(models.Model):
groups = models.ManyToManyField('auth.Group', through='core.PermissionGroup')
# auth/models.py
class Group(models.Model):
name = models.CharField(max_length=80, unique=True)
Now, trying to change the PermissionGroup to use a GenericForeignKey:
# core/models.py
class PermissionGroup(models.Model):
content_type = models.ForeignKey('contenttypes.ContentType')
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
group = models.ForeignKey('auth.Group')
class Resource(models.Model):
groups = models.ManyToManyField('auth.Group', through='core.PermissionGroup')
# auth/models.py
class Group(models.Model):
name = models.CharField(max_length=80, unique=True)
The django model validation now fails with:
core.resource: 'groups' is a manually-defined m2m relation through model PermissionGroup, which does not have foreign keys to Group and Resource
Is this simply not possible, or is another means to accomplish this?
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.
I'am trying to make a queryset in django but i'am without luck.
for some reason my model seems to be wrong.
I'll simplify.
I have this Classes in the models.py:
class RcAnalysis(models.Model):
id = models.AutoField(db_column='Id', primary_key = True) # Field name made lowercase.
/*
some other 10 columns (srry can't post here)
*/
class Meta:
db_table = 'rc_Analysis'
class RcAnalysistag(models.Model):
analysisid = models.ForeignKey(RcAnalysis, db_column='AnalysisId') # Field name made lowercase.
tagid = models.ForeignKey(LabTags, db_column='TagId') # Field name made lowercase.
class Meta:
db_table = 'rc_AnalysisTag'
I need to join the RcAnalysis with analysistag model.
But i dont have a field that i can call RcAnalysisTag proper.
Its like this SQL query:
...
from rc_Analysis A
...
inner join rc_AnalysisTag At on ( A.Id = At.AnalysisId )
inner join lab_Tags T on ( T.Id = At.TagId )
Someone?
Add a related_name="tags" to the foreign key definition. Then you can do:
analysis_object = RCAnalysis.object.get(id=1)
related_tags = analysis_object.tags.all()
Table in PostgreSQL database:
CREATE TABLE pmss_recordmodel
(
id serial NOT NULL,
"Name" character varying(100),
CONSTRAINT pmss_recordmodel_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE pmss_recordmodel OWNER TO postgres;
Model:
class RecordModel(models.Model):
def __unicode__(self):
return self.Name
Name = models.CharField(max_length = 100, unique = False, null = True, blank = True)
When I POST data with blank Name field, form.is_valid() returns False. Why? Am I missing something?
EDIT:
class RecordForm(forms.ModelForm):
class Meta:
model = RecordModel
Name = forms.CharField(label = "Имя ", widget = forms.TextInput(attrs = {'size': 15}))
Django forms documentation:
By default, each Field class assumes the value is required
Set the "required" argument to False as such:
Name = forms.CharField(required = False, label = "Имя ", widget = forms.TextInput(attrs = {'size': 15}))
You could be having problems with how the field is defined in your database.
This seems like it could be the common situation of doing syncdb with the field initially not having blank=True null=True and then adding those terms later (after initial syncdb) to make the field not required. These settings will not be applied by simply running syncdb again. It requires a database migration or a database flush (will clear existing data, which isn't necessarily bad in development).